;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: