;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 ;*** ;Copy to mark ;Check for an empty counter 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 cleq r0, r0, fend ;Get the save address of the line ;High byte load r0, eoflod + 1 store strsz, r0 store chsend + 1, r0 ;Low byte load r0, eoflod + 2 store strsz + 1, r0 store chsend + 2, r0 ;Check for the save end 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 ;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 ;Initialise the next character breq r0, r0, cendsp ;Reload the target from tmp1 relodt: load r0, tmp1 store target, r0 load r0, tmp1 + 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 ;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 ;Low byte load r0, eoflod + 2 store cload + 2, r0 ;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 ;Decrement the counter load r0, count load r2, #ff 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 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 cleq r0, r0, incdw ;Store the address store cstor + 1, r0 store cstor + 2, r1 ;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 ;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: