Gidubba/gidubba.asm

1194 lines
27 KiB
NASM

;Gidubba: A simple line editor
;***
;Save a substitute at the start address
load r0, sub
store buffer + 100, r0
;***
;Command prompt
cmdp: load r0, prompt
store ffff, r0
load r0, space
store ffff, r0
;Input the command
cleq r0, r0, input
;Check for escape
load r0, esc
breq r0, r2, cmdp
;Initialise the command and argument
xor r0, r0
store cmd, r0
load r0, zero
store arg, r0
store arg + 1, r0
store arg + 2, r0
store arg + 3, r0
load r0, qmark
store argval, r0
store argval + 1, r0
;Parse the command and its argument if any
;Command
load r0, buffer
store cmd, r0
;Load carriage return and hash
load r1, cr
load r2, hash
;Check for no command
breq r0, r1, cmdp
;First digit
load r0, buffer + 1
breq r0, r1, chkcmd
breq r0, r2, hsharg
store arg + 3, r0
;Second digit
load r0, buffer + 2
breq r0, r1, getarg
load r2, arg + 3
store arg + 2, r2
store arg + 3, r0
;Third digit
load r0, buffer + 3
breq r0, r1, getarg
load r2, arg + 2
store arg + 1, r2
load r2, arg + 3
store arg + 2, r2
store arg + 3, r0
;Fourth digit
load r0, buffer + 4
breq r0, r1, getarg
load r2, arg + 1
store arg, r2
load r2, arg + 2
store arg + 1, r2
load r2, arg + 3
store arg + 2, r2
store arg + 3, r0
;Check for command end
load r0, buffer + 5
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 argval, r0
store argval + 1, r0
breq r0, r0, chkcmd
;Get the value of the argument
;First digit
getarg: load r0, arg
cleq r0, r0, hex2n
load r1, qmark
breq r0, r1, cmderr
xor r2, r2
xor r2, r0
shl r2
shl r2
shl r2
shl r2
;Second digit
load r0, arg + 1
cleq r0, r0, hex2n
load r1, qmark
breq r0, r1, cmderr
;Combine and store the first and second digits
or r0, r2
store argval, r0
;Third digit
load r0, arg + 2
cleq r0, r0, hex2n
load r1, qmark
breq r0, r1, cmderr
xor r2, r2
xor r2, r0
shl r2
shl r2
shl r2
shl r2
;Fourth digit
load r0, arg + 3
cleq r0, r0, hex2n
load r1, qmark
breq r0, r1, cmderr
;Combine and store the third and fourth digits
or r0, r2
store argval + 1, r0
;Check for commands
;Load the command
chkcmd: load r0, cmd
;Check for no argument
load r2, argval
load r3, qmark
breq r2, r3, cnarg
;Insert
load r1, uci
breq r0, r1, insln
load r1, lci
breq r0, r1, insln
;Delete
load r1, ucd
breq r0, r1, delete
load r1, lcd
breq r0, r1, delete
;List
load r1, ucl
breq r0, r1, list
load r1, lcl
breq r0, r1, list
;Branch to error
breq r0, r0, cmderr
;Print
cnarg: load r1, ucp
breq r0, r1, print
load r1, lcp
breq r0, r1, print
;Halt
load r1, uch
breq r0, r1, end
load r1, lch
breq r0, r1, end
;Print an error and return to the command prompt
cmderr: cleq r0, r0, error
breq r0, r0, cmdp
;***
;Insert a line
;Find the argument line in the save and store its number
insln: cleq r0, r0, fend
;Print a line number prompt
instrt: cleq r0, r0, prnln
;Input the line
cleq r0, r0, input
;Check for control characters
;Escape
load r0, esc
breq r0, r2, instrt
;Substitute
load r0, sub
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 argval, r0
store argval + 1, r1
;***
;Make room for the line (To do!)
;Store the save address
;High byte
load r3, sublod + 1
store subchk + 1, r3
store cmpadr, r3
;Low byte
load r0, sublod + 2
store cmpadr + 1, r0
;Find the end of the save address
;Check for a substitute
subchk: load r0, 0
load r1, sub
breq r0, r1, endfnd
;Load the address
load r0, subchk + 1
load r1, subchk + 2
;Increment
cleq r0, r0, incdw
;Store the address
store subchk + 1, r0
store subchk + 2, r1
;Check the next character
breq r0, r0, subchk
;Store the end of the save address
;High byte
endfnd: load r3, subchk + 1
store movlod + 1, r3
;Low byte
load r0, subchk + 2
store movlod + 2, r0
;Calculate the new end of the save
;Increment the low byte
load r2, strsz
cleq r0, r0, sum
;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
;Store the new end of the save
store movsto + 1, r0
store movsto + 2, r3
;Move the substitute
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, save
;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
;***
;Save the line
;Restore the buffer start address
;High byte
save: 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, sublod + 1
store chsave + 1, r0
;Low byte
load r0, sublod + 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, lf
breq r1, r2, insln
;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
;***
;Delete a line
;Find the argument line in the save and store its number
delete: cleq r0, r0, fend
;Get the save address of the line
;High byte
load r0, sublod + 1
store stomov + 1, r0
store chsend + 1, r0
;Low byte
load r0, sublod + 2
store stomov + 2, r0
store chsend + 2, r0
;Check for the save end
chsend: load r0, 0
load r1, sub
breq r0, r1, delend
;Increment the line number
;Load the number
load r0, argval
load r1, argval + 1
;Increment
cleq r0, r0, incdw
;Store the number
store argval, r0
store argval + 1, r1
;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, sublod + 1
store lodmov + 1, r0
;Low byte
load r0, sublod + 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, sub
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
;Find the argument line in the save and store its number
list: cleq r0, r0, fend
;Print a line number prompt
cleq r0, r0, prnln
;Get the save address of the line
;High byte
load r0, sublod + 1
store chlist + 1, r0
;Low byte
load r0, sublod + 2
store chlist + 2, r0
;Load a character from the save
chlist: load r1, 0
;Check for the save end
load r2, sub
breq r1, r2, prnwln
;Print the character
store ffff, r1
;Check for the line end
load r2, lf
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
;Return to the command prompt
lstend: breq r0, r0, cmdp
;***
;Print the text
;Get the save start address
;High byte
print: load r0, svstrt
store chprnt + 1, r0
;Low byte
load r0, svstrt + 1
store chprnt + 2, r0
;Load a character from the save
chprnt: load r1, buffer + 100
;Check for the save end
load r2, sub
breq r1, r2, prend
;Print the character
store fffe, r1
;Increment the save address
;Load the address
load r0, chprnt + 1
load r1, chprnt + 2
;Increment
cleq r0, r0, incdw
;Store the address
store chprnt + 1, r0
store chprnt + 2, r1
;Print the next character
breq r0, r0, chprnt
;Return to the command prompt
prend: breq r0, r0, cmdp
;***
;Halt
end: halt
;***
;Print a newline
newln: load r0, cr
store ffff, r0
load r0, lf
store ffff, r0
ret
;***
;Print an error
error: load r0, space
store ffff, r0
store ffff, r0
load r0, qmark
store ffff, r0
cleq r0, r0, newln
;***
;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
;Check for and store overflow if any
;Check
rol r1
breq r1, r2, nvrflw
;Store
load r1, const1
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, const1
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 (To do!)
;Store the low byte in r3
decdw: xor r3, r3
xor r3, r1
;Decrement the high byte
load r2, cstff
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, cstff
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, constf
and r0, r1
;Get the nibble value
load r1, const0
breq r0, r1, dgt0
load r1, const1
breq r0, r1, dgt1
load r1, const2
breq r0, r1, dgt2
load r1, const3
breq r0, r1, dgt3
load r1, const4
breq r0, r1, dgt4
load r1, const5
breq r0, r1, dgt5
load r1, const6
breq r0, r1, dgt6
load r1, const7
breq r0, r1, dgt7
load r1, const8
breq r0, r1, dgt8
load r1, const9
breq r0, r1, dgt9
load r1, consta
breq r0, r1, dgta
load r1, constb
breq r0, r1, dgtb
load r1, constc
breq r0, r1, dgtc
load r1, constd
breq r0, r1, dgtd
load r1, conste
breq r0, r1, dgte
load r1, constf
breq r0, r1, dgtf
;Load the hexadecimal digit of the nibble
dgt0: load r0, zero
breq r0, r0, n2hend
dgt1: load r0, one
breq r0, r0, n2hend
dgt2: load r0, two
breq r0, r0, n2hend
dgt3: load r0, three
breq r0, r0, n2hend
dgt4: load r0, four
breq r0, r0, n2hend
dgt5: load r0, five
breq r0, r0, n2hend
dgt6: load r0, six
breq r0, r0, n2hend
dgt7: load r0, seven
breq r0, r0, n2hend
dgt8: load r0, eight
breq r0, r0, n2hend
dgt9: load r0, nine
breq r0, r0, n2hend
dgta: load r0, uca
breq r0, r0, n2hend
dgtb: load r0, ucb
breq r0, r0, n2hend
dgtc: load r0, ucc
breq r0, r0, n2hend
dgtd: load r0, ucd
breq r0, r0, n2hend
dgte: load r0, uce
breq r0, r0, n2hend
dgtf: load r0, ucf
breq r0, r0, n2hend
;Return
n2hend: ret
;***
;Get the nibble of a hexadecimal digit
;Get the nibble value
;Numeric digits
hex2n: load r1, zero
breq r0, r1, nbl0
load r1, one
breq r0, r1, nbl1
load r1, two
breq r0, r1, nbl2
load r1, three
breq r0, r1, nbl3
load r1, four
breq r0, r1, nbl4
load r1, five
breq r0, r1, nbl5
load r1, six
breq r0, r1, nbl6
load r1, seven
breq r0, r1, nbl7
load r1, eight
breq r0, r1, nbl8
load r1, nine
breq r0, r1, nbl9
;Uppercase letter digits
load r1, uca
breq r0, r1, nbla
load r1, ucb
breq r0, r1, nblb
load r1, ucc
breq r0, r1, nblc
load r1, ucd
breq r0, r1, nbld
load r1, uce
breq r0, r1, nble
load r1, ucf
breq r0, r1, nblf
;Lowercase letter digits
load r1, lca
breq r0, r1, nbla
load r1, lcb
breq r0, r1, nblb
load r1, lcc
breq r0, r1, nblc
load r1, lcd
breq r0, r1, nbld
load r1, lce
breq r0, r1, nble
load r1, lcf
breq r0, r1, nblf
;Load a question mark if the character is not a digit
load r0, qmark
breq r0, r0, h2nend
;Load the hexadecimal digit of the nibble
nbl0: load r0, const0
breq r0, r0, h2nend
nbl1: load r0, const1
breq r0, r0, h2nend
nbl2: load r0, const2
breq r0, r0, h2nend
nbl3: load r0, const3
breq r0, r0, h2nend
nbl4: load r0, const4
breq r0, r0, h2nend
nbl5: load r0, const5
breq r0, r0, h2nend
nbl6: load r0, const6
breq r0, r0, h2nend
nbl7: load r0, const7
breq r0, r0, h2nend
nbl8: load r0, const8
breq r0, r0, h2nend
nbl9: load r0, const9
breq r0, r0, h2nend
nbla: load r0, consta
breq r0, r0, h2nend
nblb: load r0, constb
breq r0, r0, h2nend
nblc: load r0, constc
breq r0, r0, h2nend
nbld: load r0, constd
breq r0, r0, h2nend
nble: load r0, conste
breq r0, r0, h2nend
nblf: load r0, constf
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
ror r0
ror r0
ror r0
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
;Escape
load r2, esc
breq r1, r2, escbr
;Substitute
load r2, sub
breq r1, r2, subbr
;Carriage return
load r2, cr
breq r1, r2, crbr
;Buffer end
load r2, bfsize
brneq r0, r2, chstor
;Backtrack if at the buffer end
load r2, bs
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, const1
cleq r0, r0, sum
;Store
xor r3, r3
xor r3, r0
;Increment the buffer address
;Low byte
load r0, chstor + 2
load r2, const1
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, space
store ffff, r0
load r0, bslash
store ffff, r0
;Newline
cleq r0, r0, newln
;Return with escape in r2
breq r0, r0, inend
;Print a newline
subbr: cleq r0, r0, newln
;Return with substitute at r2
breq r0, r0, inend
;Increment and store the string size
crbr: load r2, const2
cleq r0, r0, sum
store strsz, r0
;Store the CR of a newline in the buffer
;Get the buffer address
load r1, chstor + 1
store endcr + 1, r1
load r1, chstor + 2
store endcr + 2, r1
;Store
load r0, cr
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
;Print and store the LF of a newline in the buffer
load r0, lf
store ffff, r0
endlf: store 0, r0
;Return
inend: ret
;***
;Find the argument line in the save and store its number
;Reset the line number
fend: xor r0, r0
store lnnum, r0
store lnnum + 1, r0
;Get the save start address
;High byte
load r0, svstrt
store sublod + 1, r0
;Low byte
load r0, svstrt + 1
store sublod + 2, r0
;Check for the argument
charg: load r0, argval
load r1, lnnum
brneq r0, r1, fsub
load r0, argval + 1
load r1, lnnum + 1
breq r0, r1, fendnd
;Check for control characters
;Substitute
fsub: load r0, sub
sublod: load r1, 0
breq r0, r1, fendnd
;Line feed
load r2, lf
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, sublod + 1
load r1, sublod + 2
;Increment
cleq r0, r0, incdw
;Store the address
store sublod + 1, r0
store sublod + 2, r1
;Check the next character
breq r0, r0, charg
;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, zero
breq r0, r2, lead0
store ffff, r0
nlead0: store ffff, r1
load r3, const1
breq r0, r0, lbtln
lead0: load r0, space
store ffff, r0
brneq r1, r2, nlead0
load r1, space
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, zero
brneq r0, r2, nled0s
load r0, space
store ffff, r0
store ffff, r1
breq r0, r0, prcln
nled0s: store ffff, r0
store ffff, r1
;Print a colon
prcln: load r0, colon
store ffff, r0
load r0, space
store ffff, r0
;Return
ret
;***
;Data
;Constants
const0: data 0
const1: data 1
const2: data 2
const3: data 3
const4: data 4
const5: data 5
const6: data 6
const7: data 7
const8: data 8
const9: data 9
consta: data a
constb: data b
constc: data c
constd: data d
conste: data e
constf: data f
constf: data f
cstff: data ff
;Characters
bs: data 8
lf: data a
cr: data d
sub: data 1a
esc: data 1b
space: data 20
hash: data 23
zero: data 30
one: data 31
two: data 32
three: data 33
four: data 34
five: data 35
six: data 36
seven: data 37
eight: data 38
nine: data 39
colon: data 3a
prompt: data 3e
qmark: data 3f
uca: data 41
ucb: data 42
ucc: data 43
ucd: data 44
uce: data 45
ucf: data 46
uch: data 48
uci: data 49
ucl: data 4c
ucp: data 50
bslash: data 5c
lca: data 61
lcb: data 62
lcc: data 63
lcd: data 64
lce: data 65
lcf: data 66
lch: data 68
lci: data 69
lcl: data 6c
lcp: data 70
;Variables
ovrflw: data 0
lnnum: data 0
data 0
strsz: data 0
cmd: data 0
arg: data 30
data 30
data 30
data 30
argval: data 0
data 0
cmpadr: data 0
data 0
;Buffer and save
bfstrt: addr buffer
bfsize: data fe
svstrt: addr buffer + 100
buffer: