From 135fbf911740e88b802d340fe3e747dd39966ec4 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Mon, 29 Mar 2021 13:59:45 -0700 Subject: Trivial assembler. --- asm.rb | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100755 asm.rb (limited to 'asm.rb') diff --git a/asm.rb b/asm.rb new file mode 100755 index 0000000..9ba1e04 --- /dev/null +++ b/asm.rb @@ -0,0 +1,64 @@ +#!/usr/bin/ruby -w + +OPCODES = { + "acc=" => 0x000, + "load" => 0x100, + "store" => 0x200, + "ifeq" => 0x300, + "jmp" => 0x400, + "++acc" => 0xf01, + "--acc" => 0xf02, + "++idx" => 0xf04, + "--idx" => 0xf08, + "swap" => 0xf10, + "idx" => 0xf20, + "tx" => 0xf40, + "halt" => 0xf80, + } + +Line = Struct.new(:opcode, :refs, :code) + +$labels = {} +$code = [] +ARGF.each_line() do | line | + line.chomp!() + next unless line =~ /\S/ + op = 0x000 + refs = [] + line.scan(/\S+/).each() do | word | + if word =~ /^0(\d+)$/ + op |= $1.to_i(8) + elsif word =~ /^-0(\d+)$/ + op |= 0x100 - $1.to_i(8) + elsif word =~ /^(\d+)$/ + op |= $1.to_i(10) + elsif word =~ /^-(\d+)$/ + op |= 0x100 - $1.to_i(10) + elsif word =~ /^0x([0-9a-f]+)$/i + op |= $1.to_i(16) + elsif word =~ /^-0x([0-9a-f]+)$/i + op |= 0x100 - $1.to_i(16) + elsif OPCODES.key?(word) + op |= OPCODES[word] + elsif word =~ /^(.+):$/ + $labels[$1] = $code.size() + else + refs << word + end + end + $code << Line.new(op, refs, line) +end + +$code.each_with_index() do | line, i | + op = line.opcode + line.refs.each() do | ref | + if $labels.key?(ref) + target = $labels[ref] - (i + 1) + target += 0x100 if target < 0 + op |= target + else + throw "I don't understand #{ref.inspect()}" + end + end + $stdout.write("#{op.to_s(16).rjust(3, "0")} // #{line.code}\n") +end -- cgit v1.2.3