Gidubba/gidubba.asm

1931 lines
47 KiB
NASM
Raw Normal View History

;Gidubba: A simple line editor
;***
;Check the RAM size
;Initialise the comparison value
load r0, #1b
;Check a memory location
mchks: store ffef, r0
mchkl: load r1, ffef
breq r0, r1, svlmit
;Decrement the pointer
load r0, mchks + 1
load r2, #fc
cleq r0, r0, sum
store mchks + 1, r0
store mchkl + 1, r0
;Check the next location
breq r0, r0, mchks
;Save the RAM limit
svlmit: load r0, mchks + 1
store limit, r0
;***
;Save an end-of-file at the start address
load r0, #1a
store buffer + 100, r0
;***
;Command prompt
cmdp: load r0, #3e
store ffff, r0
load r0, #20
store ffff, r0
;Input the command
cmdin: cleq r0, r0, input
;Check for control characters
;Escape
load r0, #1b
breq r0, r2, cmdesc
;End-of-file
load r0, #1a
breq r0, r2, end
;Initialise the command and argument
xor r0, r0
store cmd, r0
store argf1, r0
store argf2, r0
load r0, #30
store arg1, r0
store arg1 + 1, r0
store arg1 + 2, r0
store arg1 + 3, r0
store arg2, r0
store arg2 + 1, r0
;Parse the command and its first argument
;Command
load r0, buffer
store cmd, r0
;Load carriage return and hash
load r1, #d
load r2, #23
;Check for no command
breq r0, r1, cmdp
;First digit
load r0, buffer + 1
breq r0, r1, chkcmd
load r3, #1
store argf1, r3
breq r0, r2, hsharg
load r3, arg1d2 + 1
store arg2d1 + 1, r3
load r3, arg1d2 + 2
store arg2d1 + 2, r3
load r3, #2c
breq r0, r3, 2ndarg
store arg1 + 3, r0
;Second digit
arg1d2: load r0, buffer + 2
breq r0, r1, getarg
load r3, arg1d3 + 1
store arg2d1 + 1, r3
load r3, arg1d3 + 2
store arg2d1 + 2, r3
load r3, #2c
breq r0, r3, 2ndarg
load r2, arg1 + 3
store arg1 + 2, r2
store arg1 + 3, r0
;Third digit
arg1d3: load r0, buffer + 3
breq r0, r1, getarg
load r3, arg1d4 + 1
store arg2d1 + 1, r3
load r3, arg1d4 + 2
store arg2d1 + 2, r3
load r3, #2c
breq r0, r3, 2ndarg
load r2, arg1 + 2
store arg1 + 1, r2
load r2, arg1 + 3
store arg1 + 2, r2
store arg1 + 3, r0
;Fourth digit
arg1d4: load r0, buffer + 4
breq r0, r1, getarg
load r3, arg1d5 + 1
store arg2d1 + 1, r3
load r3, arg1d5 + 2
store arg2d1 + 2, r3
load r3, #2c
breq r0, r3, 2ndarg
load r2, arg1 + 1
store arg1, r2
load r2, arg1 + 2
store arg1 + 1, r2
load r2, arg1 + 3
store arg1 + 2, r2
store arg1 + 3, r0
;Check for command end
load r0, arg1d5 + 1
load r1, arg1d5 + 2
cleq r0, r0, incdw
store arg2d1 + 1, r0
store arg2d1 + 2, r1
load r1, #d
arg1d5: load r0, buffer + 5
breq r0, r1, getarg
load r3, #2c
breq r0, r3, 2ndarg
breq r0, r0, cmderr
;Parse the second argument
;Set the addresses
2ndarg: load r0, arg2d1 + 1
load r1, arg2d1 + 2
cleq r0, r0, incdw
store arg2d2 + 1, r0
store arg2d2 + 2, r1
cleq r0, r0, incdw
store arg2d3 + 1, r0
store arg2d3 + 2, r1
;Load carriage return
load r1, #d
;First digit
arg2d1: load r0, 0
breq r0, r1, chkcmd
load r3, #1
store argf2, r3
store arg2 + 1, r0
;Second digit
arg2d2: load r0, 0
breq r0, r1, getarg
load r2, arg2 + 1
store arg2, r2
store arg2 + 1, r0
;Check for command end
arg2d3: load r0, 0
breq r0, r1, getarg
breq r0, r0, cmderr
;Hash is a shortcut for FFFF
;Check for command end
hsharg: load r0, buffer + 2
brneq r0, r1, cmderr
;Save FFFF
xor r0, r0
nand r0, r0
store target, r0
store target + 1, r0
breq r0, r0, chkcmd
;Get the value of the first argument
;First digit
getarg: load r0, arg1
cleq r0, r0, hex2n
load r1, #3f
breq r0, r1, cmderr
xor r2, r2
xor r2, r0
shl r2, 4
;Second digit
load r0, arg1 + 1
cleq r0, r0, hex2n
load r1, #3f
breq r0, r1, cmderr
;Combine and store the first and second digits
or r0, r2
store target, r0
;Third digit
load r0, arg1 + 2
cleq r0, r0, hex2n
load r1, #3f
breq r0, r1, cmderr
xor r2, r2
xor r2, r0
shl r2, 4
;Fourth digit
load r0, arg1 + 3
cleq r0, r0, hex2n
load r1, #3f
breq r0, r1, cmderr
;Combine and store the third and fourth digits
or r0, r2
store target + 1, r0
;Get the value of the second argument
;First digit
load r0, arg2
cleq r0, r0, hex2n
load r1, #3f
breq r0, r1, cmderr
xor r2, r2
xor r2, r0
shl r2, 4
;Second digit
load r0, arg2 + 1
cleq r0, r0, hex2n
load r1, #3f
breq r0, r1, cmderr
;Combine and store the first and second digits
or r0, r2
store count, r0
;Check for commands
;Load the command
chkcmd: load r0, cmd
;Check for no argument
load r2, argf1
xor r3, r3
breq r2, r3, cnarg
;Check for single argument
load r2, argf2
xor r3, r3
breq r2, r3, onearg
;Copy to mark
load r1, #43
breq r0, r1, copy
load r1, #63
breq r0, r1, copy
;Delete
load r1, #44
breq r0, r1, delete
load r1, #64
breq r0, r1, delete
;List
load r1, #4c
breq r0, r1, list
load r1, #6c
breq r0, r1, list
;Branch to error
breq r0, r0, cmderr
;Insert
onearg: load r1, #49
breq r0, r1, insln
load r1, #69
breq r0, r1, insln
;Set a mark
load r1, #4d
breq r0, r1, setmrk
load r1, #6d
breq r0, r1, setmrk
;Branch to error
breq r0, r0, cmderr
;Print
cnarg: load r1, #50
breq r0, r1, print
load r1, #70
breq r0, r1, print
;Write to tape
load r1, #57
breq r0, r1, write
load r1, #77
breq r0, r1, write
;Read from tape
load r1, #52
breq r0, r1, read
load r1, #72
breq r0, r1, read
;Print an error and return to the command prompt
cmderr: load r0, #3f
store ffff, r0
cleq r0, r0, newln
breq r0, r0, cmdp
cmdesc: load r0, #20
store ffff, r0
store ffff, r0
breq r0, r0, cmdin
;***
;Insert a line
;Reset the line number
insln: xor r0, r0
store lnnum, r0
store lnnum + 1, r0
;Get the save start address
;High byte
load r0, svstrt
store eoflod + 1, r0
;Low byte
load r0, svstrt + 1
store eoflod + 2, r0
;Find the argument line in the save and store its number
nextln: cleq r0, r0, fend
;Print a line number prompt
instrt: cleq r0, r0, prnln
;Input the line
inline: cleq r0, r0, input
;Check for control characters
;Escape
load r0, #1b
breq r0, r2, inesc
;End-of-file
load r0, #1a
breq r0, r2, cmdp
;Increment the line number
;Load the number
load r0, lnnum
load r1, lnnum + 1
;Increment
cleq r0, r0, incdw
;Store the number
store target, r0
store target + 1, r1
;Store the save address
;High byte
load r3, eoflod + 1
store eofchk + 1, r3
store cmpadr, r3
;Low byte
load r0, eoflod + 2
store eofchk + 2, r0
store cmpadr + 1, r0
;Make room for the line
cleq r0, r0, eofchk
xor r0, r0
brneq r0, r1, cmdp
;Restore the buffer start address
;High byte
load r0, bfstrt
store chload + 1, r0
;Low byte
load r0, bfstrt + 1
store chload + 2, r0
;Store the save address
;High byte
load r0, eoflod + 1
store chsave + 1, r0
;Low byte
load r0, eoflod + 2
store chsave + 2, r0
;Load and save a character from the buffer
;Load
chload: load r1, buffer
;Save
chsave: store buffer + 100, r1
;Check for line end
load r2, #a
breq r1, r2, nextln
;Increment the buffer address
;Load the address
load r0, chload + 1
load r1, chload + 2
;Increment
cleq r0, r0, incdw
;Store the address
store chload + 1, r0
store chload + 2, r1
;Increment the save address
;Load the address
load r0, chsave + 1
load r1, chsave + 2
;Increment
cleq r0, r0, incdw
;Store the address
store chsave + 1, r0
store chsave + 2, r1
;Load and save the next character
breq r0, r0, chload
inesc: load r0, #20
store ffff, r0
store ffff, r0
store ffff, r0
store ffff, r0
store ffff, r0
store ffff, r0
breq r0, r0, inline
;***
;Set a mark for copying
setmrk: load r0, target
store mark, r0
load r0, target + 1
store mark + 1, r0
breq r0, r0, cmdp
;***
2022-08-23 15:31:36 +00:00
;Copy to mark
;Check for an empty counter
2022-08-23 15:31:36 +00:00
copy: xor r0, r0
load r1, count
breq r0, r1, cmdp
;Reset the line number
xor r0, r0
store lnnum, r0
store lnnum + 1, r0
;Get the save start address
;High byte
load r0, svstrt
store eoflod + 1, r0
;Low byte
load r0, svstrt + 1
store eoflod + 2, r0
;Find the argument line in the save and store its number
2022-08-23 15:31:36 +00:00
cleq r0, r0, fend
;Get the save address of the line
;High byte
load r0, eoflod + 1
store strsz, r0
2022-08-23 15:31:36 +00:00
store chsend + 1, r0
;Low byte
load r0, eoflod + 2
store strsz + 1, r0
2022-08-23 15:31:36 +00:00
store chsend + 2, r0
;Check for the save end
2022-08-23 15:31:36 +00:00
chsend: load r0, 0
load r1, #1a
breq r0, r1, cmdp
;Save the buffer address to tmp1 and increment it
;Low byte
load r0, target + 1
store tmp1 + 1, r0
load r2, count
cleq r0, r0, sum
store target + 1, r0
;Add the overflow to the high byte
load r0, target
store tmp1, r0
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store target, r0
;Find the next line in the save and store its number
cleq r0, r0, fend
;Get the save address of the line
;High byte
load r0, eoflod + 1
store tmp2, r0
;Low byte
load r0, eoflod + 2
store tmp2 + 1, r0
;Negate the first address
;Low byte
load r0, strsz + 1
nand r0, r0
load r2, #1
cleq r0, r0, sum
store strsz + 1, r0
;Reverse and add the overflow to the high byte
load r0, strsz
nand r0, r0
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store strsz, r0
;Get the copy length
;High byte
load r0, tmp2
load r2, strsz
cleq r0, r0, sum
store strsz, r0
;Low byte
load r0, tmp2 + 1
load r2, strsz + 1
cleq r0, r0, sum
store strsz + 1, r0
;Reverse and add the overflow to the high byte
load r0, strsz
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store strsz, r0
;Load the mark to target
load r0, mark
store target, r0
load r0, mark + 1
store target + 1, r0
;Reset the line number
xor r0, r0
store lnnum, r0
store lnnum + 1, r0
;Get the save start address
;High byte
load r0, svstrt
store eoflod + 1, r0
;Low byte
load r0, svstrt + 1
store eoflod + 2, r0
2022-08-23 15:31:36 +00:00
;Find the marked line in the save and store its number
cleq r0, r0, fend
;Store the save address
;High byte
load r3, eoflod + 1
store eofchk + 1, r3
store cmpadr, r3
store cstor + 1, r3
store cinit + 1, r3
;Low byte
load r0, eoflod + 2
store eofchk + 2, r0
store cmpadr + 1, r0
store cstor + 2, r0
store cinit + 2, r0
;Make room for the copy
cleq r0, r0, eofchk
xor r0, r0
brneq r0, r1, cmdp
;Check for the end of the space
cendsp: load r0, movsto + 1
load r1, cinit + 1
brneq r0, r1, cinist
load r0, movsto + 2
load r1, cinit + 2
brneq r0, r1, cinist
breq r0, r1, relodt
;Initialise a character
cinist: load r0, #0
cinit: store 0, r0
;Increment the source address
;Load the address
incini: load r0, cinit + 1
load r1, cinit + 2
;Increment
cleq r0, r0, incdw
;Store the address
store cinit + 1, r0
store cinit + 2, r1
2022-08-23 15:31:36 +00:00
;Initialise the next character
breq r0, r0, cendsp
2022-08-23 15:31:36 +00:00
;Reload the target from tmp1
relodt: load r0, tmp1
2022-08-23 15:31:36 +00:00
store target, r0
load r0, tmp1 + 1
2022-08-23 15:31:36 +00:00
store target + 1, r0
;Reset the line number
xor r0, r0
store lnnum, r0
store lnnum + 1, r0
;Get the save start address
;High byte
load r0, svstrt
store eoflod + 1, r0
;Low byte
load r0, svstrt + 1
store eoflod + 2, r0
2022-08-23 15:31:36 +00:00
;Find the marked line in the save and store its number
cleq r0, r0, fend
;Store the save address
;High byte
load r3, eoflod + 1
store cload + 1, r3
2022-08-23 15:31:36 +00:00
;Low byte
load r0, eoflod + 2
store cload + 2, r0
2022-08-23 15:31:36 +00:00
;Copy a character
;Load
cload: load r1, 0
;Check for a null
xor r2, r2
breq r1, r2, skip0
;Check for save end
load r2, #1a
breq r1, r2, cmdp
;Save
cstor: store 0, r1
;Check for line end
load r2, #a
brneq r1, r2, cincs
2022-08-23 15:31:36 +00:00
;Decrement the counter
load r0, count
load r2, #ff
2022-08-23 15:31:36 +00:00
cleq r0, r0, sum
store count, r0
;Check the counter
xor r0, r0
load r1, count
breq r0, r1, cmdp
;Increment the source address
;Load the address
cincs: load r0, cload + 1
load r1, cload + 2
;Increment
2022-08-23 15:31:36 +00:00
cleq r0, r0, incdw
;Store the address
store cload + 1, r0
store cload + 2, r1
;Increment the copy address
;Load the address
load r0, cstor + 1
load r1, cstor + 2
;Increment
2022-08-23 15:31:36 +00:00
cleq r0, r0, incdw
;Store the address
store cstor + 1, r0
store cstor + 2, r1
2022-08-23 15:31:36 +00:00
;Load and save the next character
breq r0, r0, cload
;Increment the source address
;Load the address
skip0: load r0, cload + 1
load r1, cload + 2
;Increment
cleq r0, r0, incdw
;Store the address
store cload + 1, r0
store cload + 2, r1
;Load the next character
breq r0, r0, cload
;***
;Delete a line
;Check for an empty counter
delete: xor r0, r0
load r1, count
breq r0, r1, cmdp
;Reset the line number
xor r0, r0
store lnnum, r0
store lnnum + 1, r0
;Get the save start address
;High byte
load r0, svstrt
store eoflod + 1, r0
;Low byte
load r0, svstrt + 1
store eoflod + 2, r0
;Find the argument line in the save and store its number
cleq r0, r0, fend
;Get the save address of the line
;High byte
load r0, eoflod + 1
store stomov + 1, r0
store dchend + 1, r0
;Low byte
load r0, eoflod + 2
store stomov + 2, r0
store dchend + 2, r0
;Check for the save end
dchend: load r0, 0
load r1, #1a
breq r0, r1, cmdp
;Increment the buffer address
;Low byte
load r0, target + 1
load r2, count
cleq r0, r0, sum
store target + 1, r0
;Add the overflow to the high byte
load r0, target
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store target, r0
;Find the next line in the save and store its number
cleq r0, r0, fend
;Get the save address of the line
;High byte
load r0, eoflod + 1
store lodmov + 1, r0
;Low byte
load r0, eoflod + 2
store lodmov + 2, r0
;Move the remainder of the text back
lodmov: load r0, 0
stomov: store 0, r0
;Check for the save end
load r1, #1a
breq r0, r1, delend
;Increment the first save address
;Load the address
load r0, stomov + 1
load r1, stomov + 2
;Increment
cleq r0, r0, incdw
;Store the address
store stomov + 1, r0
store stomov + 2, r1
;Increment the second save address
;Load the address
load r0, lodmov + 1
load r1, lodmov + 2
;Increment
cleq r0, r0, incdw
;Store the address
store lodmov + 1, r0
store lodmov + 2, r1
;Move the next character
breq r0, r0, lodmov
;Return to the command prompt
delend: breq r0, r0, cmdp
;***
;List a line
;Reset the line number
list: xor r0, r0
store lnnum, r0
store lnnum + 1, r0
;Get the save start address
;High byte
load r0, svstrt
store eoflod + 1, r0
;Low byte
load r0, svstrt + 1
store eoflod + 2, r0
;Check the counter
lcount: xor r0, r0
load r1, count
breq r0, r1, cmdp
;Find the argument line in the save and store its number
cleq r0, r0, fend
;Get the save address of the line
;High byte
load r0, eoflod + 1
store chlist + 1, r0
store lchend + 1, r0
;Low byte
load r0, eoflod + 2
store chlist + 2, r0
store lchend + 2, r0
;Check for the save end
lchend: load r0, 0
load r1, #1a
breq r0, r1, cmdp
;Print a line number prompt
cleq r0, r0, prnln
;Load a character from the save
chlist: load r1, 0
;Check for the save end
load r2, #1a
breq r1, r2, prnwln
;Print the character
store ffff, r1
;Check for the line end
load r2, #a
breq r1, r2, lstend
;Increment the save address
;Load the address
load r0, chlist + 1
load r1, chlist + 2
;Increment
cleq r0, r0, incdw
;Store the address
store chlist + 1, r0
store chlist + 2, r1
;Print the next character
breq r0, r0, chlist
;Print a newline
prnwln: cleq r0, r0, newln
;Loop
;Decrement the counter
lstend: load r0, count
load r2, #ff
cleq r0, r0, sum
store count, r0
;Increment the line number
load r0, target
load r1, target + 1
cleq r0, r0, incdw
store target, r0
store target + 1, r1
;Loop
breq r0, r0, lcount
;***
;Print the text
;Get the printer address
;High byte
print: load r0, #ff
store prwrch + 1, r0
;Low byte
load r0, #fe
store prwrch + 2, r0
;Print
cleq r0, r0, prwr
;Return to the command prompt
breq r0, r0, cmdp
;***
;Write the text to the tape punch
;Get the tape punch address
;High byte
write: load r0, #ff
store prwrch + 1, r0
;Low byte
load r0, #fd
store prwrch + 2, r0
;Write
cleq r0, r0, prwr
;Return to the command prompt
breq r0, r0, cmdp
;***
;Read the text from the tape reader
;Get the save start address
;High byte
read: load r0, svstrt
store chrsto + 1, r0
;Low byte
load r0, svstrt + 1
store chrsto + 2, r0
;Ignore the leader
iglead: load r1, fffd
xor r2, r2
breq r1, r2, iglead
breq r0, r0, chkend
;Check for the RAM limit
load r0, chrsto + 1
load r1, chrsto + 2
chkram: cleq r0, r0, ramchk
xor r2, r2
brneq r1, r2, cmdp
;Read a character
chread: load r1, fffd
;Check for trailer or empty tape reader
;Trailer
chkend: xor r2, r2
brneq r1, r2, chkntp
load r1, #1a
breq r0, r0, chrsto
;Empty tape reader
chkntp: nand r2, r2
brneq r1, r2, chklf
load r1, #1a
breq r0, r0, chrsto
;Check for a line feed
chklf: load r2, #a
load r3, #0
brneq r1, r2, chrsto
load r1, #d
load r3, #a
;Store a character
chrsto: store buffer + 100, r1
;Check for a newline
;Line feed
load r2, #a
breq r2, r3, readlf
;Carriage return
load r2, #d
breq r1, r2, readcr
;Check for the save end
load r2, #1a
breq r1, r2, redend
;Increment the save address
;Load the address
load r0, chrsto + 1
load r1, chrsto + 2
;Increment
cleq r0, r0, incdw
;Store the address
store chrsto + 1, r0
store chrsto + 2, r1
;Read the next character
breq r0, r0, chkram
;Read a newline beginning with a carriage return
readcr: cleq r0, r0, readnl
;Check for a line feed
load r2, #a
breq r1, r2, chread
breq r0, r0, chkend
;Read a newline beginning with a line feed
readlf: cleq r0, r0, readnl
;Check for a carriage return
load r2, #d
breq r1, r2, chread
breq r0, r0, chkend
;Return to the command prompt
redend: breq r0, r0, cmdp
;***
;Halt
end: halt
;***
;Print a newline
newln: load r0, #d
store ffff, r0
load r0, #a
store ffff, r0
ret
;***
;Add r2 to r0 with the overflow stored in r1
;Reset overflow
sum: xor r1, r1
store ovrflw, r1
;Copy the first argument to r1
sumlop: xor r1, r1
xor r1, r0
;Calculate the sum and carry and copy the pre-shift carry to r1
;Sum
xor r0, r2
;Carry
and r2, r1
;Copy the pre-shift carry
xor r1, r1
xor r1, r2
;Shift the carry
shl r2, 1
;Check for and store overflow if any
;Check
rol r1, 1
breq r1, r2, nvrflw
;Store
load r1, #1
store ovrflw, r1
;Check for no carry
nvrflw: xor r1, r1
breq r1, r2, sumend
;Loop
breq r0, r0, sumlop
;Load overflow and return
sumend: load r1, ovrflw
ret
;***
;Increment a value stored in r0 and r1
;Store the high byte in r3
incdw: xor r3, r3
xor r3, r0
;Load the low byte to r0
xor r0, r0
xor r0, r1
;Increment the low byte
load r2, #1
cleq r0, r0, sum
;Load the high byte to r0 and store the low byte in r3
;Move the high byte to r2
xor r2, r2
xor r2, r3
;Store the low byte to r3
xor r3, r3
xor r3, r0
;Load the high byte to r0
xor r0, r0
xor r0, r2
;Add the overflow to the high byte
xor r2, r2
xor r2, r1
cleq r0, r0, sum
;Load the low byte in r1
xor r1, r1
xor r1, r3
;Return
ret
;***
;Decrement a value stored in r0 and r1
;Store the low byte in r3
decdw: xor r3, r3
xor r3, r1
;Decrement the high byte
load r2, #ff
cleq r0, r0, sum
;Load the low byte to r0 and store the high byte in r3
;Move the low byte to r2
xor r2, r2
xor r2, r3
;Store the high byte to r3
xor r3, r3
xor r3, r0
;Load the low byte to r0
xor r0, r0
xor r0, r2
;Decrement the low byte
load r2, #ff
cleq r0, r0, sum
;Load the high byte to r0 and store the low byte in r3
;Move the high byte to r2
xor r2, r2
xor r2, r3
;Store the low byte to r3
xor r3, r3
xor r3, r0
;Load the high byte to r0
xor r0, r0
xor r0, r2
;Add the overflow to the high byte
xor r2, r2
xor r2, r1
cleq r0, r0, sum
;Load the low byte in r1
xor r1, r1
xor r1, r3
;Return
ret
;***
;Get the hexadecimal digit of a nibble
;Extract the low nibble
n2hex: load r1, #f
and r0, r1
;Get the nibble value
load r1, #0
breq r0, r1, dgt0
load r1, #1
breq r0, r1, dgt1
load r1, #2
breq r0, r1, dgt2
load r1, #3
breq r0, r1, dgt3
load r1, #4
breq r0, r1, dgt4
load r1, #5
breq r0, r1, dgt5
load r1, #6
breq r0, r1, dgt6
load r1, #7
breq r0, r1, dgt7
load r1, #8
breq r0, r1, dgt8
load r1, #9
breq r0, r1, dgt9
load r1, #a
breq r0, r1, dgta
load r1, #b
breq r0, r1, dgtb
load r1, #c
breq r0, r1, dgtc
load r1, #d
breq r0, r1, dgtd
load r1, #e
breq r0, r1, dgte
load r1, #f
breq r0, r1, dgtf
;Load the hexadecimal digit of the nibble
dgt0: load r0, #30
breq r0, r0, n2hend
dgt1: load r0, #31
breq r0, r0, n2hend
dgt2: load r0, #32
breq r0, r0, n2hend
dgt3: load r0, #33
breq r0, r0, n2hend
dgt4: load r0, #34
breq r0, r0, n2hend
dgt5: load r0, #35
breq r0, r0, n2hend
dgt6: load r0, #36
breq r0, r0, n2hend
dgt7: load r0, #37
breq r0, r0, n2hend
dgt8: load r0, #38
breq r0, r0, n2hend
dgt9: load r0, #39
breq r0, r0, n2hend
dgta: load r0, #41
breq r0, r0, n2hend
dgtb: load r0, #42
breq r0, r0, n2hend
dgtc: load r0, #43
breq r0, r0, n2hend
dgtd: load r0, #44
breq r0, r0, n2hend
dgte: load r0, #45
breq r0, r0, n2hend
dgtf: load r0, #46
breq r0, r0, n2hend
;Return
n2hend: ret
;***
;Get the nibble of a hexadecimal digit
;Get the nibble value
;Numeric digits
hex2n: load r1, #30
breq r0, r1, nbl0
load r1, #31
breq r0, r1, nbl1
load r1, #32
breq r0, r1, nbl2
load r1, #33
breq r0, r1, nbl3
load r1, #34
breq r0, r1, nbl4
load r1, #35
breq r0, r1, nbl5
load r1, #36
breq r0, r1, nbl6
load r1, #37
breq r0, r1, nbl7
load r1, #38
breq r0, r1, nbl8
load r1, #39
breq r0, r1, nbl9
;Uppercase letter digits
load r1, #41
breq r0, r1, nbla
load r1, #42
breq r0, r1, nblb
load r1, #43
breq r0, r1, nblc
load r1, #44
breq r0, r1, nbld
load r1, #45
breq r0, r1, nble
load r1, #46
breq r0, r1, nblf
;Lowercase letter digits
load r1, #61
breq r0, r1, nbla
load r1, #62
breq r0, r1, nblb
load r1, #63
breq r0, r1, nblc
load r1, #64
breq r0, r1, nbld
load r1, #65
breq r0, r1, nble
load r1, #66
breq r0, r1, nblf
;Load a question mark if the character is not a digit
load r0, #3f
breq r0, r0, h2nend
;Load the hexadecimal digit of the nibble
nbl0: load r0, #0
breq r0, r0, h2nend
nbl1: load r0, #1
breq r0, r0, h2nend
nbl2: load r0, #2
breq r0, r0, h2nend
nbl3: load r0, #3
breq r0, r0, h2nend
nbl4: load r0, #4
breq r0, r0, h2nend
nbl5: load r0, #5
breq r0, r0, h2nend
nbl6: load r0, #6
breq r0, r0, h2nend
nbl7: load r0, #7
breq r0, r0, h2nend
nbl8: load r0, #8
breq r0, r0, h2nend
nbl9: load r0, #9
breq r0, r0, h2nend
nbla: load r0, #a
breq r0, r0, h2nend
nblb: load r0, #b
breq r0, r0, h2nend
nblc: load r0, #c
breq r0, r0, h2nend
nbld: load r0, #d
breq r0, r0, h2nend
nble: load r0, #e
breq r0, r0, h2nend
nblf: load r0, #f
breq r0, r0, h2nend
;Return
h2nend: ret
;***
;Get the hexadecimal digits of a byte
;Load the byte to to r2
bt2hex: xor r2, r2
xor r2, r0
;Convert the low nibble to a digit and store it in r2
;Convert
cleq r0, r0, n2hex
;Store
xor r1, r1
xor r1, r0
;Re-load the byte to r0
xor r0, r0
xor r0, r2
;Store the low nibble in r2
xor r2, r2
xor r2, r1
;Convert the high nibble to a digit
ror r0, 4
cleq r0, r0, n2hex
;Load the digit of the low nibble to r1
xor r1, r1
xor r1, r2
;Return
ret
;***
;Input a character
;Restore the buffer start address
;High byte
input: load r0, bfstrt
store chstor + 1, r0
;Low byte
load r0, bfstrt + 1
store chstor + 2, r0
;Initialise the character counter
xor r0, r0
;Read a character
inloop: load r1, ffff
;Check for control characters and the buffer end
;Null
load r2, #0
breq r1, r2, inloop
;FF
load r2, #ff
breq r1, r2, inloop
;Delete
load r2, #7f
breq r1, r2, delbr
;Escape
load r2, #1b
breq r1, r2, escbr
;End-of-file
load r2, #1a
breq r1, r2, eofbr
;Carriage return
load r2, #d
breq r1, r2, crbr
;Line feed
load r2, #a
breq r1, r2, lfbr
;Buffer end
load r2, bfsize
brneq r0, r2, chstor
;Ignore the input and print an underscore if at the buffer end
load r2, #5f
store ffff, r2
breq r0, r0, inloop
;Store the character in the buffer
chstor: store buffer, r1
;Increment the character counter and store it in r3
;Increment
load r2, #1
cleq r0, r0, sum
;Store
xor r3, r3
xor r3, r0
;Increment the buffer address
;Low byte
load r0, chstor + 2
load r2, #1
cleq r0, r0, sum
store chstor + 2, r0
;Add the overflow to the high byte
load r0, chstor + 1
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store chstor + 1, r0
;Reload the character counter to r0
xor r0, r0
xor r0, r3
;Read the next character
breq r0, r0, inloop
;Print an underscore
delbr: load r2, #5f
store ffff, r2
;Check for buffer start
xor r2, r2
breq r0, r2, inloop
;Decrement the character counter and store it in r3
;Decrement
load r2, #ff
cleq r0, r0, sum
;Store
xor r3, r3
xor r3, r0
;Decrement the buffer address
;High byte
load r0, chstor + 1
load r2, #ff
cleq r0, r0, sum
store chstor + 1, r0
;Low byte
load r0, chstor + 2
load r2, #ff
cleq r0, r0, sum
store chstor + 2, r0
;Add the overflow to the high byte
load r0, chstor + 1
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store chstor + 1, r0
;Reload the character counter to r0
xor r0, r0
xor r0, r3
;Read the next character
breq r0, r0, inloop
;Print a backslash and a newline
;Backslash
escbr: load r0, #20
store ffff, r0
load r0, #5c
store ffff, r0
;Newline
cleq r0, r0, newln
;Return with escape in r2
ret
;Print a newline
eofbr: cleq r0, r0, newln
;Return with End-of-file at r2
ret
;Print a line feed
crbr: load r1, #a
store ffff, r1
breq r0, r0, endnl
;Print a carriage return and a null
lfbr: load r1, #d
store ffff, r1
load r1, #0
store ffff, r1
;Increment and store the string size
endnl: load r2, #2
cleq r0, r0, sum
store strsz + 1, r0
load r0, #0
store strsz, r0
;Get the buffer address
load r1, chstor + 1
store endcr + 1, r1
load r1, chstor + 2
store endcr + 2, r1
;Store the CR of a newline in the buffer
load r0, #d
endcr: store 0, r0
;Increment the buffer address
;Load the address
load r0, chstor + 1
load r1, chstor + 2
;Increment
cleq r0, r0, incdw
;Store the address
store endlf + 1, r0
store endlf + 2, r1
;Store the LF of a newline in the buffer
load r0, #a
endlf: store 0, r0
;Return
ret
;***
;Make room for the line
;Find the end of the save address
;Check for an end-of-file
eofchk: load r0, 0
load r1, #1a
breq r0, r1, endfnd
;Load the address
load r0, eofchk + 1
load r1, eofchk + 2
;Increment
cleq r0, r0, incdw
;Store the address
store eofchk + 1, r0
store eofchk + 2, r1
;Check the next character
breq r0, r0, eofchk
;Store the end of the save address
;High byte
endfnd: load r0, eofchk + 1
store movlod + 1, r0
;Low byte
load r3, eofchk + 2
store movlod + 2, r3
;Calculate the new end of the save
;High byte
load r2, strsz
cleq r0, r0, sum
store strsz, r0
;Check for overflow from the high byte
xor r0, r0
brneq r0, r1, lmterr
;Low byte
xor r0, r0
xor r0, r3
load r2, strsz + 1
cleq r0, r0, sum
store strsz + 1, r0
;Add the overflow to the high byte
load r0, strsz
xor r2, r2
xor r2, r1
cleq r0, r0, sum
;Store the new end of the save
store movsto + 1, r0
load r3, strsz + 1
store movsto + 2, r3
;Check for overflow from the high byte
xor r0, r0
brneq r0, r1, lmterr
;Negate the RAM limit
;Low byte
load r0, limit + 1
nand r0, r0
load r2, #1
cleq r0, r0, sum
store tmp2 + 1, r0
;Reverse and add the overflow to the high byte
load r0, limit
nand r0, r0
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store tmp2, r0
;Subtract the RAM limit from the new end of the save
;High byte
load r0, movsto + 1
load r2, tmp2
cleq r0, r0, sum
store tmp2, r0
;Check for overflow from the high byte
xor r0, r0
brneq r0, r1, lmterr
;Low byte
load r0, movsto + 2
load r2, tmp2 + 1
cleq r0, r0, sum
store tmp2 + 1, r0
;Add the overflow to the high byte
load r0, tmp2
xor r2, r2
xor r2, r1
cleq r0, r0, sum
store tmp2, r0
;Check for overflow from the high byte
xor r0, r0
brneq r0, r1, lmterr
;Move the End-of-file
movlod: load r0, 0
movsto: store 0, r0
;Check for the address of the new line
load r0, cmpadr
load r1, movlod + 1
brneq r0, r1, decsav
load r0, cmpadr + 1
load r1, movlod + 2
brneq r0, r1, decsav
breq r0, r1, roomnd
;Decrement the old save address
;load the address
decsav: load r0, movlod + 1
load r1, movlod + 2
;Decrement
cleq r0, r0, decdw
;Store the address
store movlod + 1, r0
store movlod + 2, r1
;Decrement the new save address
;load the address
load r0, movsto + 1
load r1, movsto + 2
;Decrement
cleq r0, r0, decdw
;Store the address
store movsto + 1, r0
store movsto + 2, r1
;Move the next character
breq r0, r0, movlod
;Return with a null at r1
roomnd: xor r1, r1
ret
;Print an error and return with an exclamation mark at r1
lmterr: load r0, #21
store ffff, r0
cleq r0, r0, newln
load r1, #21
ret
;***
;Find the argument line in the save and store its number
;Check for the argument
fend: load r0, target
load r1, lnnum
brneq r0, r1, feof
load r0, target + 1
load r1, lnnum + 1
breq r0, r1, fendnd
;Check for control characters
;End-of-file
feof: load r0, #1a
eoflod: load r1, 0
breq r0, r1, fendnd
;Line feed
load r2, #a
brneq r1, r2, incsav
;Increment the line number
;Load the number
load r0, lnnum
load r1, lnnum + 1
;Increment
cleq r0, r0, incdw
;Store the number
store lnnum, r0
store lnnum + 1, r1
;Increment the save address
;Load the address
incsav: load r0, eoflod + 1
load r1, eoflod + 2
;Increment
cleq r0, r0, incdw
;Store the address
store eoflod + 1, r0
store eoflod + 2, r1
;Check the next character
breq r0, r0, fend
;Return
fendnd: ret
;***
;Print a line number prompt
;Print the high byte
;Get the byte
prnln: load r0, lnnum
;Convert
cleq r0, r0, bt2hex
;Print
load r2, #30
breq r0, r2, lead0
store ffff, r0
nlead0: store ffff, r1
load r3, #1
breq r0, r0, lbtln
lead0: load r0, #20
store ffff, r0
brneq r1, r2, nlead0
load r1, #20
store ffff, r1
xor r3, r3
;Print the low byte
;Get the byte
lbtln: load r0, lnnum + 1
;Convert
cleq r0, r0, bt2hex
;Check for preceding leading zeroes
xor r2, r2
brneq r2, r3, nled0s
;Print
load r2, #30
brneq r0, r2, nled0s
load r0, #20
store ffff, r0
store ffff, r1
breq r0, r0, prcln
nled0s: store ffff, r0
store ffff, r1
;Print a colon
prcln: load r0, #3a
store ffff, r0
load r0, #20
store ffff, r0
;Return
ret
;***
;Print or write to tape
;Get the save start address
;High byte
prwr: load r0, svstrt
store chprwr + 1, r0
;Low byte
load r0, svstrt + 1
store chprwr + 2, r0
;Load a character from the save
chprwr: load r1, buffer + 100
2022-10-14 17:19:00 +00:00
;Print the character
prwrch: store fffe, r1
;Check for the save end
load r2, #1a
breq r1, r2, pwend
;Increment the save address
;Load the address
load r0, chprwr + 1
load r1, chprwr + 2
;Increment
cleq r0, r0, incdw
;Store the address
store chprwr + 1, r0
store chprwr + 2, r1
;Print the next character
breq r0, r0, chprwr
;Return
pwend: ret
;***
;Check for the RAM limit
;Check
ramchk: load r2, limit
load r3, limit + 1
brneq r0, r2, ramend
brneq r1, r3, ramend
;Save an end-of-file at the start address
load r0, #1a
store buffer + 100, r0
;Print an error
load r0, #21
store ffff, r0
cleq r0, r0, newln
;Return with an exclamation mark at r1
load r1, #21
ret
;Return with a null at r1
ramend: load r1, #0
ret
;***
;Read a newline
;Increment the save address
;Load the address
readnl: load r0, chrsto + 1
load r1, chrsto + 2
;Increment
cleq r0, r0, incdw
;Store the address
store chrsto + 1, r0
store lfstor + 1, r0
store chrsto + 2, r1
store lfstor + 2, r1
;Check for the RAM limit
cleq r0, r0, ramchk
xor r2, r2
brneq r1, r2, cmdp
;Store a line feed
load r1, #a
lfstor: store 0, r1
;Increment the save address
;Load the address
load r0, chrsto + 1
load r1, chrsto + 2
;Increment
cleq r0, r0, incdw
;Store the address
store chrsto + 1, r0
store chrsto + 2, r1
;Check for the RAM limit
cleq r0, r0, ramchk
xor r2, r2
brneq r1, r2, cmdp
;Read a character
load r1, fffd
;Return
ret
;***
;Data
;Variables
ovrflw: data 0
lnnum: data 0
data 0
strsz: data 0
data 0
dgtcnt: data 0
dgtadr: addr buffer + 2
cmd: data 0
arg1: data 30
data 30
data 30
data 30
argf1: data 0
arg2: data 30
data 30
argf2: data 0
target: data 0
data 0
count: data 0
mark: data 0
data 0
mrkadr: data 0
data 0
cmpadr: data 0
data 0
tmp1: data 0
data 0
tmp2: data 0
data 0
;Buffer and save
bfstrt: addr buffer
bfsize: data fe
svstrt: addr buffer + 100
limit: data 0
data 0
buffer: