This commit is contained in:
Sven Riwoldt
2024-04-01 20:30:24 +02:00
parent fd333f3514
commit c7bc862c6f
6804 changed files with 1065135 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
require_relative "Writer.rb"
class Assembler
def initialize(asm_file_path)
@asm_file_path = asm_file_path
@hack_file_path = asm_file_path.gsub(".asm", ".hack")
@binary_code_writer = Writer.new(@asm_file_path, @hack_file_path)
end
def compile_asm
@binary_code_writer.write
end
end
if __FILE__ == $0
asm = Assembler.new(ARGV[0])
asm.compile_asm
end

View File

@@ -0,0 +1,68 @@
class Parser
A_INSTRUCTION = /^@\d+$/
SYMBOL = /^@[a-zA-Z._\$\d]+$/
def self.create_label_hash(hash)
(0..15).each do |n|
hash["@R#{n}"] = "@#{n.to_s}"
end
specials = %w(SP LCL ARG THIS THAT)
p specials
specials.each_with_index do |sym, ind|
hash["@" + sym] = "@#{ind}"
p hash["@" + sym]
end
end
def initialize(asmfile_path)
@file = File.open(asmfile_path, "r")
@commands = []
@labels = {}
@counter = 0
@index = 0
@available_token = 16
Parser.create_label_hash(@labels)
readlines
p @labels["@SP"]
end
def readlines
while !@file.eof?
@current_line = @file.gets.gsub(/\/\/.*/, "").strip
if !@current_line.empty?
if @current_line[0] == '('
@labels["@" + @current_line[1..-2]] = "@#{@counter}"
elsif @current_line.match(A_INSTRUCTION)
@commands << @current_line
elsif @current_line.match(SYMBOL)
@commands << set_tokens_mem_slot(@current_line)
@counter += 1
else
@commands << @current_line
@counter += 1
end
end
end
end
def current_command
@commands[@index]
end
def advance
return false if @index == @commands.length
@index += 1
return @commands[@index]
end
def has_more_commands
@index < @commands.length
end
def label_line_number(instruction)
@labels[instruction]
end
def set_tokens_mem_slot(line)
if !@labels.has_key?(line)
@labels[line] = "@#{@available_token}"
@available_token += 1
end
return @labels[line]
end
def close
@file.close
end
end

117
fertige_Projekte/Writer.rb Normal file
View File

@@ -0,0 +1,117 @@
require_relative "Parser.rb"
class Writer
A_INSTRUCTION = /^@\d+$/
def initialize(asm_file_path, hack_file_path)
@hack_file = File.open(hack_file_path, "w")
@parser = Parser.new(asm_file_path)
end
def write
while @parser.has_more_commands
compile
end
@parser.close
@hack_file.close
end
def compile
if command.match(A_INSTRUCTION)
compile_a_ins
else
compile_c_ins
write_txt("", true)
end
@parser.advance
end
def compile_a_ins
ains = command[1..-1].to_i.to_s(base=2)
(16-ains.length).times {ains = "0" + ains}
write_txt(ains, true)
end
def compile_c_ins
write_txt("111")
commands = command.split(/=|;/)
if command.include?("=")
compile_alu(commands[1].strip)
compile_save_to(commands[0].strip)
compile_jump_to("#{commands[2] ? commands[2].strip : nil}")
else
compile_alu(commands[0].strip)
compile_save_to("")
compile_jump_to("#{commands[1] ? commands[1].strip : nil}")
end
end
def compile_alu(cmd)
cmd.include?("M") ? write_txt("1") : write_txt("0")
case cmd
when "0"
write_txt("101010")
when "1"
write_txt("111111")
when "-1"
write_txt("111010")
when "D"
write_txt("001100")
when "A", "M"
write_txt("110000")
when "!D"
write_txt("001101")
when "!A", "!M"
write_txt("110001")
when "-D"
write_txt("001111")
when "-A", "-M"
write_txt("110011")
when "D+1"
write_txt("011111")
when "A+1", "M+1"
write_txt("110111")
when "D-1"
write_txt("001110")
when "A-1", "M-1"
write_txt("110010")
when "D+A", "D+M"
write_txt("000010")
when "D-A", "D-M"
write_txt("010011")
when "A-D", "M-D"
write_txt("000111")
when "D&A", "D&M"
write_txt("000000")
when "D|A", "D|M"
write_txt("010101")
else
raise "no such alu command"
end
end
def compile_save_to(cmd)
cmd.include?("A") ? write_txt("1") : write_txt("0")
cmd.include?("D") ? write_txt("1") : write_txt("0")
cmd.include?("M") ? write_txt("1") : write_txt("0")
end
def compile_jump_to(command)
case command
when nil, ""
write_txt("000")
when "JGT"
write_txt("001")
when "JEQ"
write_txt("010")
when "JGE"
write_txt("011")
when "JLT"
write_txt("100")
when "JNE"
write_txt("101")
when "JLE"
write_txt("110")
when "JMP"
write_txt("111")
end
end
private
def command
@parser.current_command
end
def write_txt(binaries, ending=false)
@hack_file.write("#{binaries}#{ending ? "\n" : ""}")
end
end

Binary file not shown.