asm
This commit is contained in:
15
fertige_Projekte/Assembler.rb
Normal file
15
fertige_Projekte/Assembler.rb
Normal 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
|
||||
68
fertige_Projekte/Parser.rb
Normal file
68
fertige_Projekte/Parser.rb
Normal 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
117
fertige_Projekte/Writer.rb
Normal 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
|
||||
BIN
fertige_Projekte/nand2tetrisAssembler-master.zip
Normal file
BIN
fertige_Projekte/nand2tetrisAssembler-master.zip
Normal file
Binary file not shown.
Reference in New Issue
Block a user