stack-machine/asm/monitor.txt

269 lines
4.7 KiB
Plaintext

# vim: set sw=3 tw=80:
include "include/memory-map.txt"
export read_char
export write_char
export newline
export read_hex
export write_hex
export puts
export end_of_monitor
import decode_base64
start_of_monitor:
_start:
jump main
include "lib/rs232.txt"
to_upper:
dup; immed 'a'; sub
jump .not_lc rel lt drop
dup; immed 'z'; sub
jump .not_lc rel gt drop
immed 32
sub return
.not_lc:
return
start_str: byte "Stack CPU Monitor Program" 10 0
prompt_str: byte "> " 0
error_str: byte "ERROR" 10 0
access_str: byte "ACCESS DENIED" 10 0
# Commands:
# READ addr
# WRITE value addr
# STORE start_addr
# CALL addr
main:
immed start_str
call puts
.prompt:
immed prompt_str
call puts
.getcmd:
call read_char
call to_upper
dup; immed ' '; sub
jump .ignore_sp rel eq drop
dup; immed 10; sub
jump .ignore_nl rel eq drop
dup; immed 'R'; sub
jump .read rel eq drop
dup; immed 'W'; sub
jump .write rel eq drop
dup; immed 'S'; sub
jump .store rel eq drop
dup; immed 'C'; sub
jump .call rel eq drop
dup; immed 35; sub
jump .comment rel eq drop
drop
.invalid:
call newline
immed error_str
call puts
jump .prompt
.ignore_sp:
jump .getcmd rel drop
.ignore_nl:
jump .prompt rel drop
.expect_char:
call read_char
call to_upper
sub
jump .correct rel eq drop
rdrop # Don't return to caller
jump .invalid rel
.correct:
return
.read:
drop #R
immed 'E'; call .expect_char rel
immed 'A'; call .expect_char rel
immed 'D'; call .expect_char rel
immed ' '; call .expect_char rel
call read_hex
immed 10; sub
jump ..invalid rel ne drop
load
call write_hex
call newline
jump .prompt rel
..invalid:
jump .invalid rel drop
.write:
drop #W
immed 'R'; call .expect_char rel
immed 'I'; call .expect_char rel
immed 'T'; call .expect_char rel
immed 'E'; call .expect_char rel
immed ' '; call .expect_char rel
call read_hex
immed ' '; sub
jump ..invalid1 rel ne drop
call read_hex
immed 10; sub
jump ..invalid2 rel ne drop
dup; immed start_of_monitor; sub
jump ..ok rel lt drop
dup; immed end_of_monitor; sub
jump ..denied rel lt drop
..ok:
store
jump .prompt
..invalid2:
drop
..invalid1:
jump .invalid rel drop
..denied:
drop2
immed access_str
call puts
jump .prompt
.store:
drop #S
immed 'T'; call .expect_char rel
immed 'O'; call .expect_char rel
immed 'R'; call .expect_char rel
immed 'E'; call .expect_char rel
immed ' '; call .expect_char rel
call read_hex
immed 10; sub
jump ..invalid rel ne drop
immed read_char
immed .store_byte
call decode_base64
drop2
jump .prompt rel
..invalid:
jump .invalid rel drop
.store_byte: # ( buffer byte -- buffer' )
over
store byte
immed 1
add return
.call:
drop #C
immed 'A'; call .expect_char rel
immed 'L'; call .expect_char rel
immed 'L'; call .expect_char rel
immed ' '; call .expect_char rel
call read_hex
immed 10; sub
jump ..invalid rel ne drop
call # expected: ( -- )
jump .prompt rel
..invalid:
jump .invalid rel drop
.comment:
immed 10; sub
jump .prompt eq drop
call read_char
jump .comment
# Reads an arbitrary number of hex digits, returning the last eight as
# a 32-bit integer along with the following non-hex character.
read_hex: # ( -- integer last_char )
immed 0
call read_char
call to_upper
dup; push
dup; immed '-'; sub
jump .after_first_char rel ne drop
.negative:
drop
.get_next_char:
call read_char
call to_upper
.after_first_char:
dup; immed '0'; sub
jump .not_hex rel lt drop
dup; immed '9'; sub
jump .number rel le drop
dup; immed 'A'; sub
jump .not_hex rel lt drop
dup; immed 'F'; sub
jump .letter rel le drop
.not_hex:
swap
pop; immed '-'; sub
jump .positive rel ne drop
immed 0; swap; sub
.positive:
swap
return
.number:
immed '0'; sub
.merge:
push
immed -4; rshift
pop
or
jump .get_next_char rel
.letter:
immed 55; sub # 55 = 'A'-10
jump .merge rel
# Displays integer as eight hex digits
write_hex: # ( integer -- )
immed 8
.loop:
push
dup
immed -4; rshift
push
immed 28; rshift
dup; immed 10; sub
jump .letter rel ge drop
immed '0'
.common:
add
call write_char
jump .next rel
.letter:
immed 10; sub
immed 'A'
jump .common rel
.next:
pop
pop
immed 1; sub
jump .loop rel gt
drop2
return
include "lib/base64.txt"
# ( addr -- ) [ addr -> null-terminated ASCII string ]
puts:
dup
load byte
jump .nul rel eq
call write_char
immed 1
add
jump puts rel
.nul:
drop2
return
end_of_monitor: