mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-08-28 17:29:32 +00:00
49 lines
1.6 KiB
Plaintext
49 lines
1.6 KiB
Plaintext
|
# asm - assembler and interpreter for simple computer
|
||
|
# usage: awk -f asm program-file data-files...
|
||
|
|
||
|
BEGIN {
|
||
|
srcfile = ARGV[1]
|
||
|
ARGV[1] = "" # remaining files are data
|
||
|
tempfile = "/tmp/asm.temp"
|
||
|
n = split("const get put ld st add sub jpos jz j halt", x)
|
||
|
for (i = 1; i <= n; i++) # create table of op codes
|
||
|
op[x[i]] = i-1
|
||
|
|
||
|
# ASSEMBLER PASS 1
|
||
|
FS = "[ \t]+"
|
||
|
while (getline <srcfile > 0) {
|
||
|
sub(/#.*/, "") # strip comments
|
||
|
symtab[$1] = nextmem # remember label location
|
||
|
if ($2 != "") { # save op, addr if present
|
||
|
print $2 "\t" $3 >tempfile
|
||
|
nextmem++
|
||
|
}
|
||
|
}
|
||
|
close(tempfile)
|
||
|
|
||
|
# ASSEMBLER PASS 2
|
||
|
nextmem = 0
|
||
|
while (getline <tempfile > 0) {
|
||
|
if ($2 !~ /^[0-9]*$/) # if symbolic addr,
|
||
|
$2 = symtab[$2] # replace by numeric value
|
||
|
mem[nextmem++] = 1000 * op[$1] + $2 # pack into word
|
||
|
}
|
||
|
|
||
|
# INTERPRETER
|
||
|
for (pc = 0; pc >= 0; ) {
|
||
|
addr = mem[pc] % 1000
|
||
|
code = int(mem[pc++] / 1000)
|
||
|
if (code == op["get"]) { getline acc }
|
||
|
else if (code == op["put"]) { print acc }
|
||
|
else if (code == op["st"]) { mem[addr] = acc }
|
||
|
else if (code == op["ld"]) { acc = mem[addr] }
|
||
|
else if (code == op["add"]) { acc += mem[addr] }
|
||
|
else if (code == op["sub"]) { acc -= mem[addr] }
|
||
|
else if (code == op["jpos"]) { if (acc > 0) pc = addr }
|
||
|
else if (code == op["jz"]) { if (acc == 0) pc = addr }
|
||
|
else if (code == op["j"]) { pc = addr }
|
||
|
else if (code == op["halt"]) { pc = -1 }
|
||
|
else { pc = -1 }
|
||
|
}
|
||
|
}
|