From c9d45a13b4531cec1fe4fa8e0b5000c4f271932d Mon Sep 17 00:00:00 2001 From: Jeremiah Orians Date: Sun, 21 Aug 2016 20:53:10 -0400 Subject: [PATCH] Wrote the bare metal Text editor SET in Assembly --- stage1/SET.hex0 | 416 ++++++++++++++++++++++++++++++++++++++++++ stage1/SET.hex2 | 427 +++++++++++++++++++++++++++++++++++++++++++ stage1/SET.s | 467 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1310 insertions(+) create mode 100644 stage1/SET.hex0 create mode 100644 stage1/SET.hex2 create mode 100644 stage1/SET.s diff --git a/stage1/SET.hex0 b/stage1/SET.hex0 new file mode 100644 index 0000000..906918c --- /dev/null +++ b/stage1/SET.hex0 @@ -0,0 +1,416 @@ +# :start +2D2F0394 # LOADUI R15 $stack ; Put stack at end of program +# ;; We will be using R14 for our condition codes +# ;; We will be using R13 for storage of Head +# ;; Main program +# ;; Reads contents of Tape_01 and writes desired contents onto Tape_02 +# ;; Accepts no arguments and HALTS when done +# :main +# ;; Prep TAPE_01 +2D201100 # LOADUI R0 0x1100 +42100000 # FOPEN_READ +# ;; Prepare to Read File +0D00002E # FALSE R14 +0D000021 # FALSE R1 +2D0F0018 # CALLI R15 @ReadFile +# ;; Done reading File +2D201100 # LOADUI R0 0x1100 ; Close TAPE_01 +42100002 # FCLOSE +# ;; Enter Editor Loop +090005D1 # MOVE R13 R1 ; Set R13 to Head +2D0F0134 # CALLI R15 @EditorLoop +# ;; And We are Done +FFFFFFFF # HALT + +# ;; Readfile function +# ;; Recieves pointer to head in R1 +# ;; Creates Nodes and imports text until EOF +# ;; Alters R0 R1 R14 +# ;; Returns to whatever called it +# :ReadFile +# ;; Allocate another Node +2D20000c # LOADUI R0 12 +2D0F0100 # CALLI R15 @malloc +# ;; Get another line into list +0902001F # PUSHR R1 R15 +2D211100 # LOADUI R1 0x1100 ; Read from tape_01 +2D0F001c # CALLI R15 @Readline +0902801F # POPR R1 R15 +09000301 # SWAP R0 R1 +2D0F00a0 # CALLI R15 @addline +09000301 # SWAP R0 R1 +# ;; Loop if not reached EOF +2C9Effdc # JUMP.Z R14 @ReadFile +0D01001F # RET R15 + +# ;; Readline function +# ;; Recieves Pointer to node in R0 +# ;; And Input in R1 +# ;; Allocates Text segment on Heap +# ;; Sets node's pointer to Text segment +# ;; Sets R14 to True if EOF reached +# ;; Returns to whatever called it +# :Readline +# ;; Preserve registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +0902003F # PUSHR R3 R15 +0902004F # PUSHR R4 R15 +# ;; Initialize +09000540 # MOVE R4 R0 +2D200100 # LOADUI R0 256 +2D0F00bc # CALLI R15 @malloc +09000520 # MOVE R2 R0 +0D000023 # FALSE R3 +# :Readline_0 +42100100 # FGETC ; Read a Char +# ;; Flag if reached EOF +A0100000 # CMPSKIP.GE R0 0 +0D00003E # TRUE R14 +# ;; Stop if EOF +A0100000 # CMPSKIP.GE R0 0 +3C00003c # JUMP @Readline_2 +# ;; Handle Backspace +A020007f # CMPSKIP.E R0 127 +3C000010 # JUMP @Readline_1 +# ;; Move back 1 character if R3 > 0 +A0430000 # CMPSKIP.LE R3 0 +11330001 # SUBUI R3 R3 1 +# ;; Hopefully they keep typing +3C00ffdc # JUMP @Readline_0 +# :Readline_1 +# ;; Replace all CR with LF +A030000d # CMPSKIP.NE R0 13 +2D20000a # LOADUI R0 10 +# ;; Store the Byte +05049023 # STOREX8 R0 R2 R3 +# ;; Check for EOL +A030000a # CMPSKIP.NE R0 10 +3C000014 # JUMP @Readline_2 +# ;; Prevent lines from exceeding 255 chars +A04300ff # CMPSKIP.LE R3 255 +3C00000c # JUMP @Readline_2 +# ;; Prep for next loop +0F330001 # ADDUI R3 R3 1 +3C00ffb8 # JUMP @Readline_0 +# :Readline_2 +# ;; Set Text pointer +23240008 # STORE32 R2 R4 8 +# ;; Restore Registers +0902804F # POPR R4 R15 +0902803F # POPR R3 R15 +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + +# ;; addline Function +# ;; Recieves pointers in R0 R1 +# ;; Alters R0 if NULL +# ;; Appends nodes together +# ;; Returns to whatever called it +# :addline +# ;; Preserve Registers +0902002F # PUSHR R2 R15 +0902001F # PUSHR R1 R15 +0902000F # PUSHR R0 R15 +# ;; Handle if Head is NULL +2CA00010 # JUMP.NZ R0 @addline_0 +0902800F # POPR R0 R15 +0902001F # PUSHR R1 R15 +3C000020 # JUMP @addline_2 +# :addline_0 +# ;; Handle if Head->next is NULL +18200000 # LOAD32 R2 R0 0 +2CA20010 # JUMP.NZ R2 @addline_1 +# ;; Set head->next = p +23100000 # STORE32 R1 R0 0 +# ;; Set p->prev = head +23010004 # STORE32 R0 R1 4 +3C00000c # JUMP @addline_2 +# :addline_1 +# ;; Handle case of Head->next not being NULL +18000000 # LOAD32 R0 R0 0 +2D0Fffcc # CALLI R15 @addline +# :addline_2 +# ;; Restore registers +0902800F # POPR R0 R15 +0902801F # POPR R1 R15 +0902802F # POPR R2 R15 +0D01001F # RET R15 + +# ;; Primative malloc function +# ;; Recieves number of bytes to allocate in R0 +# ;; Returns pointer to block of that size in R0 +# ;; Returns to whatever called it +# :malloc +# ;; Preserve registers +0902001F # PUSHR R1 R15 +# ;; Get current malloc pointer +2E010020 # LOADR R1 @malloc_pointer +# ;; Deal with special case +A0310000 # CMPSKIP.NE R1 0 ; If Zero set to our start of heap space +2D214000 # LOADUI R1 0x4000 +# ;; update malloc pointer +09000301 # SWAP R0 R1 +05000101 # ADD R1 R0 R1 +2F01000c # STORER R1 @malloc_pointer +# ;; Done +# ;; Restore registers +0902801F # POPR R1 R15 +0D01001F # RET R15 +# ;; Our static value for malloc pointer +# :malloc_pointer +00000000 # NOP + +# ;; Editor Loop +# ;; Provides user interaction +# ;; Requires R13 to be pointer to Head +# ;; Internally loops +# ;; Returns nothing +# :EditorLoop +0D000021 # FALSE R1 ; Read from tty +42100100 # FGETC ; Read a Char +# ;; Quit if q +A0300071 # CMPSKIP.NE R0 113 +0D01001F # RET R15 +# ;; Print if p +1FE00070 # CMPUI R14 R0 112 +2C6E0014 # JUMP.NE R14 @EditorLoop_0 +180D0008 # LOAD32 R0 R13 8 +0D000021 # FALSE R1 +2D0F0118 # CALLI R15 @PrintLine +3C00ffdc # JUMP @EditorLoop +# :EditorLoop_0 +# ;; Move forward if f +1FE00066 # CMPUI R14 R0 102 +2C6E0014 # JUMP.NE R14 @EditorLoop_1 +180D0000 # LOAD32 R0 R13 0 ; Load head->next +# ;; If head->next isn't null make it the new head +A0200000 # CMPSKIP.E R0 0 +090005D0 # MOVE R13 R0 +3C00ffc4 # JUMP @EditorLoop +# :EditorLoop_1 +# ;; Move backward if b +1FE00062 # CMPUI R14 R0 98 +2C6E0014 # JUMP.NE R14 @EditorLoop_2 +180D0004 # LOAD32 R0 R13 4 ; Load head->prev +# ;; If head->prev isn't null make it the new head +A0200000 # CMPSKIP.E R0 0 +090005D0 # MOVE R13 R0 +3C00ffac # JUMP @EditorLoop +# :EditorLoop_2 +# ;; Edit Line if e +1FE00065 # CMPUI R14 R0 101 +2C6E0014 # JUMP.NE R14 @EditorLoop_3 +# ;; Change Head's Text +0900040D # COPY R0 R13 +0D000021 # FALSE R1 ; Read from tty +2D0Ffe98 # CALLI R15 @Readline +3C00ff94 # JUMP @EditorLoop +# :EditorLoop_3 +# ;; Writeout to tape_02 if w +1FE00077 # CMPUI R14 R0 119 +2C6E0028 # JUMP.NE R14 @EditorLoop_4 +# ;; Prep TAPE_02 +2D201101 # LOADUI R0 0x1101 +42100001 # FOPEN_WRITE +0900040D # COPY R0 R13 +2D211101 # LOADUI R1 0x1101 +2D0F0058 # CALLI R15 @GetRoot +2D0F0074 # CALLI R15 @PrintAll +2D201101 # LOADUI R0 0x1101 ; Close TAPE_02 +42100002 # FCLOSE +3C00ff68 # JUMP @EditorLoop +# :EditorLoop_4 +# ;; Append node if a +1FE00061 # CMPUI R14 R0 97 +2C6E0010 # JUMP.NE R14 @EditorLoop_5 +0900040D # COPY R0 R13 +2D0F00dc # CALLI R15 @AppendLine +3C00ff54 # JUMP @EditorLoop +# :EditorLoop_5 +# ;; Insert node if i +1FE00069 # CMPUI R14 R0 105 +2C6E0010 # JUMP.NE R14 @EditorLoop_6 +0900040D # COPY R0 R13 +2D0F0108 # CALLI R15 @InsertLine +3C00ff40 # JUMP @EditorLoop +# :EditorLoop_6 +# ;; Delete node if d +1FE00064 # CMPUI R14 R0 100 +2C6E0014 # JUMP.NE R14 @EditorLoop_7 +0900040D # COPY R0 R13 +2D0F0134 # CALLI R15 @RemoveLine +090005D0 # MOVE R13 R0 +3C00ff28 # JUMP @EditorLoop +# :EditorLoop_7 +3C00ff24 # JUMP @EditorLoop + +# ;; GetRoot function +# ;; Walks backwards through nodes until beginning +# ;; Recieves node pointer in R0 and Returns result in R0 +# ;; Returns to whatever called it +# :GetRoot +# ;; Preserve registers +0902001F # PUSHR R1 R15 +# :GetRoot_0 +# ;; Get Head->Prev +18100004 # LOAD32 R1 R0 4 +A0310000 # CMPSKIP.NE R1 0 +3C00000c # JUMP @GetRoot_1 +09000501 # MOVE R0 R1 +3C00fff0 # JUMP @GetRoot_0 +# :GetRoot_1 +# ;; Restore registers +0902801F # POPR R1 R15 +0D01001F # RET R15 + +# ;; Printall Function +# ;; Prints all lines to Interface in R1 +# ;; Starting at node in R0 +# ;; Does not alter registers +# ;; Returns to whatever called it +# :PrintAll +# ;; Preserve registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +# :PrintAll_0 +18200000 # LOAD32 R2 R0 0 ; Store Head->Next in R2 +18000008 # LOAD32 R0 R0 8 ; Set R0 to Head->Text +2D0F0024 # CALLI R15 @PrintLine ; Prints Head->Text +A0320000 # CMPSKIP.NE R2 0 ; If Head->Next is NULL +3C00000c # JUMP @PrintAll_1 ; Stop Looping +09000502 # MOVE R0 R2 ; Otherwise Move to Next Node +3C00ffe8 # JUMP @PrintAll_0 ; And Loop +# :PrintAll_1 +# ;; Restore registers +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + +# ;; Printline function +# ;; Recieves a string pointer in R0 +# ;; Prints string interface specified in R1 +# ;; Does not alter registers +# ;; Returns to whatever called it +# :PrintLine +# ;; Preserve registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +0902003F # PUSHR R3 R15 +# ;; Initialize +09000520 # MOVE R2 R0 +0D000023 # FALSE R3 +# ;; Deal with NULL Pointer +A0320000 # CMPSKIP.NE R2 0 +3C00001c # JUMP @PrintLine_1 +# :PrintLine_0 +0503A023 # LOADXU8 R0 R2 R3 ; Load char from string +# ;; Don't print NULLs +A0300000 # CMPSKIP.NE R0 0 +3C000010 # JUMP @PrintLine_1 +42100200 # FPUTC +# ; Print the char +0F330001 # ADDUI R3 R3 1 ; Prep for next loop +3C00ffec # JUMP @PrintLine_0 +# :PrintLine_1 +# ;; Restore registers +0902803F # POPR R3 R15 +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + + +# ;; AppendLine Function +# ;; Recieves a Node in R0 +# ;; Creates a new Node and appends it +# ;; Does not alter registers +# ;; Returns to whatever calls it +# :AppendLine +# ;; Preserve registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +# ;; Initialize +09000510 # MOVE R1 R0 +# ;; Allocate another Node +2D20000c # LOADUI R0 12 +2D0Ffe40 # CALLI R15 @malloc +# ;; Check if head->Next is null +18210000 # LOAD32 R2 R1 0 +A0220000 # CMPSKIP.E R2 0 ; If head->Next is something +23020004 # STORE32 R0 R2 4 ; Set head->next->prev to p +# ;; Setup p and head +23200000 # STORE32 R2 R0 0 ; p->next = head->next +23100004 # STORE32 R1 R0 4 ; p->prev = head +23010000 # STORE32 R0 R1 0 ; head->next = p +# ;; Restore Registers +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + + +# ;; InsertLine Function +# ;; Recieves a Node in R0 +# ;; Creates a new Node and prepends it +# ;; Does not alter registers +# ;; Returns to whatever called it +# :InsertLine +# ;; Preserve Registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +# ;; Initialize +09000510 # MOVE R1 R0 +# ;; Allocate another Node +2D20000c # LOADUI R0 12 +2D0Ffe00 # CALLI R15 @malloc +# ;; Check if Head->Prev is Null +18210004 # LOAD32 R2 R1 4 +A0220000 # CMPSKIP.E R2 0 ; If head->prev is something +23020000 # STORE32 R0 R2 0 ; Set head->prev->next to p +# ;; Setup p and head +23200004 # STORE32 R2 R0 4 ; p->prev = head->prev +23100000 # STORE32 R1 R0 0 ; p->next = head +23010004 # STORE32 R0 R1 4 ; head->prev = p +# ;; Restore Registers +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + + +# ;; RemoveLine Function +# ;; Recieves Node in R0 +# ;; Returns replacement node in R0 +# ;; Returns to whatever called it +# :RemoveLine +# ;; Preserve Registers +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +# ;; Initialize +09000510 # MOVE R1 R0 +18010004 # LOAD32 R0 R1 4 ; put p->prev in R0 +18210000 # LOAD32 R2 R1 0 ; put p->next in R2 +# ;; Keep links +A0200000 # CMPSKIP.E R0 0 ; If p->prev is not null +23200000 # STORE32 R2 R0 0 ; p->prev->next = p->next +A0220000 # CMPSKIP.E R2 0 ; If p->next is not null +23020004 # STORE32 R0 R2 4 ; p->next->prev = p->prev +# ;; Attempt to save what is left of the list +A0300000 # CMPSKIP.NE R0 0 ; If p->prev is null +09000502 # MOVE R0 R2 ; return p->next +# ;; Restore Registers +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0D01001F # RET R15 + +# ;; Where our stack begins +# :stack diff --git a/stage1/SET.hex2 b/stage1/SET.hex2 new file mode 100644 index 0000000..c80ace1 --- /dev/null +++ b/stage1/SET.hex2 @@ -0,0 +1,427 @@ +:start +2D2F $stack # LOADUI R15 $stack ; Put stack at end of program +# ;; We will be using R14 for our condition codes +# ;; We will be using R13 for storage of Head + + +# ;; Main program +# ;; Reads contents of Tape_01 and writes desired contents onto Tape_02 +# ;; Accepts no arguments and HALTS when done +:main +# ;; Prep TAPE_01 +2D201100 # LOADUI R0 0x1100 +42100000 # FOPEN_READ +# ;; Prepare to Read File +0D00002E # FALSE R14 +0D000021 # FALSE R1 +2D0F @ReadFile # CALLI R15 @ReadFile +# ;; Done reading File +2D201100 # LOADUI R0 0x1100 ; Close TAPE_01 +42100002 # FCLOSE +# ;; Enter Editor Loop +090005D1 # MOVE R13 R1 ; Set R13 to Head +2D0F @EditorLoop # CALLI R15 @EditorLoop +# ;; And We are Done +FFFFFFFF # HALT + + +# ;; Readfile function +# ;; Recieves pointer to head in R1 +# ;; Creates Nodes and imports text until EOF +# ;; Alters R0 R1 R14 +# ;; Returns to whatever called it +:ReadFile +# ;; Allocate another Node +2D20000c # LOADUI R0 12 +2D0F @malloc # CALLI R15 @malloc +# ;; Get another line into list +0902001F # PUSHR R1 R15 +2D211100 # LOADUI R1 0x1100 ; Read from tape_01 +2D0F @Readline # CALLI R15 @Readline +0902801F # POPR R1 R15 +09000301 # SWAP R0 R1 +2D0F @addline # CALLI R15 @addline +09000301 # SWAP R0 R1 +# ;; Loop if not reached EOF +2C9E @ReadFile # JUMP.Z R14 @ReadFile +0D01001F # RET R15 + + +# ;; Readline function +# ;; Recieves Pointer to node in R0 +# ;; And Input in R1 +# ;; Allocates Text segment on Heap +# ;; Sets node's pointer to Text segment +# ;; Sets R14 to True if EOF reached +# ;; Returns to whatever called it +:Readline +# ;; Preserve registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +0902003F # PUSHR R3 R15 +0902004F # PUSHR R4 R15 +# ;; Initialize +09000540 # MOVE R4 R0 +2D200100 # LOADUI R0 256 +2D0F @malloc # CALLI R15 @malloc +09000520 # MOVE R2 R0 +0D000023 # FALSE R3 +:Readline_0 +42100100 # FGETC ; Read a Char +# ;; Flag if reached EOF +A0100000 # CMPSKIP.GE R0 0 +0D00003E # TRUE R14 +# ;; Stop if EOF +A0100000 # CMPSKIP.GE R0 0 +3C00 @Readline_2 # JUMP @Readline_2 +# ;; Handle Backspace +A020007f # CMPSKIP.E R0 127 +3C00 @Readline_1 # JUMP @Readline_1 +# ;; Move back 1 character if R3 > 0 +A0430000 # CMPSKIP.LE R3 0 +11330001 # SUBUI R3 R3 1 +# ;; Hopefully they keep typing +3C00 @Readline_0 # JUMP @Readline_0 +:Readline_1 +# ;; Replace all CR with LF +A030000d # CMPSKIP.NE R0 13 +2D20000a # LOADUI R0 10 +# ;; Store the Byte +05049023 # STOREX8 R0 R2 R3 +# ;; Check for EOL +A030000a # CMPSKIP.NE R0 10 +3C00 @Readline_2 # JUMP @Readline_2 +# ;; Prevent lines from exceeding 255 chars +A04300ff # CMPSKIP.LE R3 255 +3C00 @Readline_2 # JUMP @Readline_2 +# ;; Prep for next loop +0F330001 # ADDUI R3 R3 1 +3C00 @Readline_0 # JUMP @Readline_0 +:Readline_2 +# ;; Set Text pointer +23240008 # STORE32 R2 R4 8 +# ;; Restore Registers +0902804F # POPR R4 R15 +0902803F # POPR R3 R15 +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + + +# ;; addline Function +# ;; Recieves pointers in R0 R1 +# ;; Alters R0 if NULL +# ;; Appends nodes together +# ;; Returns to whatever called it +:addline +# ;; Preserve Registers +0902002F # PUSHR R2 R15 +0902001F # PUSHR R1 R15 +0902000F # PUSHR R0 R15 +# ;; Handle if Head is NULL +2CA0 @addline_0 # JUMP.NZ R0 @addline_0 +0902800F # POPR R0 R15 +0902001F # PUSHR R1 R15 +3C00 @addline_2 # JUMP @addline_2 +:addline_0 +# ;; Handle if Head->next is NULL +18200000 # LOAD32 R2 R0 0 +2CA2 @addline_1 # JUMP.NZ R2 @addline_1 +# ;; Set head->next = p +23100000 # STORE32 R1 R0 0 +# ;; Set p->prev = head +23010004 # STORE32 R0 R1 4 +3C00 @addline_2 # JUMP @addline_2 +:addline_1 +# ;; Handle case of Head->next not being NULL +18000000 # LOAD32 R0 R0 0 +2D0F @addline # CALLI R15 @addline +:addline_2 +# ;; Restore registers +0902800F # POPR R0 R15 +0902801F # POPR R1 R15 +0902802F # POPR R2 R15 +0D01001F # RET R15 + + +# ;; Primative malloc function +# ;; Recieves number of bytes to allocate in R0 +# ;; Returns pointer to block of that size in R0 +# ;; Returns to whatever called it +:malloc +# ;; Preserve registers +0902001F # PUSHR R1 R15 +# ;; Get current malloc pointer +2E01 @malloc_pointer # LOADR R1 @malloc_pointer +# ;; Deal with special case +A0310000 # CMPSKIP.NE R1 0 ; If Zero set to our start of heap space +2D214000 # LOADUI R1 0x4000 +# ;; update malloc pointer +09000301 # SWAP R0 R1 +05000101 # ADD R1 R0 R1 +2F01 @malloc_pointer # STORER R1 @malloc_pointer +# ;; Done +# ;; Restore registers +0902801F # POPR R1 R15 +0D01001F # RET R15 +# ;; Our static value for malloc pointer +:malloc_pointer +00000000 # NOP + + +# ;; Editor Loop +# ;; Provides user interaction +# ;; Requires R13 to be pointer to Head +# ;; Internally loops +# ;; Returns nothing +:EditorLoop +0D000021 # FALSE R1 ; Read from tty +42100100 # FGETC ; Read a Char +# ;; Quit if q +A0300071 # CMPSKIP.NE R0 113 +0D01001F # RET R15 +# ;; Print if p +1FE00070 # CMPUI R14 R0 112 +2C6E @EditorLoop_0 # JUMP.NE R14 @EditorLoop_0 +180D0008 # LOAD32 R0 R13 8 +0D000021 # FALSE R1 +2D0F @PrintLine # CALLI R15 @PrintLine +3C00 @EditorLoop # JUMP @EditorLoop +:EditorLoop_0 +# ;; Move forward if f +1FE00066 # CMPUI R14 R0 102 +2C6E @EditorLoop_1 # JUMP.NE R14 @EditorLoop_1 +180D0000 # LOAD32 R0 R13 0 ; Load head->next +# ;; If head->next isn't null make it the new head +A0200000 # CMPSKIP.E R0 0 +090005D0 # MOVE R13 R0 +3C00 @EditorLoop # JUMP @EditorLoop +:EditorLoop_1 +# ;; Move backward if b +1FE00062 # CMPUI R14 R0 98 +2C6E @EditorLoop_2 # JUMP.NE R14 @EditorLoop_2 +180D0004 # LOAD32 R0 R13 4 ; Load head->prev +# ;; If head->prev isn't null make it the new head +A0200000 # CMPSKIP.E R0 0 +090005D0 # MOVE R13 R0 +3C00 @EditorLoop # JUMP @EditorLoop +:EditorLoop_2 +# ;; Edit Line if e +1FE00065 # CMPUI R14 R0 101 +2C6E @EditorLoop_3 # JUMP.NE R14 @EditorLoop_3 +# ;; Change Head's Text +0900040D # COPY R0 R13 +0D000021 # FALSE R1 ; Read from tty +2D0F @Readline # CALLI R15 @Readline +3C00 @EditorLoop # JUMP @EditorLoop +:EditorLoop_3 +# ;; Writeout to tape_02 if w +1FE00077 # CMPUI R14 R0 119 +2C6E @EditorLoop_4 # JUMP.NE R14 @EditorLoop_4 +# ;; Prep TAPE_02 +2D201101 # LOADUI R0 0x1101 +42100001 # FOPEN_WRITE +0900040D # COPY R0 R13 +2D211101 # LOADUI R1 0x1101 +2D0F @GetRoot # CALLI R15 @GetRoot +2D0F @PrintAll # CALLI R15 @PrintAll +2D201101 # LOADUI R0 0x1101 ; Close TAPE_02 +42100002 # FCLOSE +3C00 @EditorLoop # JUMP @EditorLoop +:EditorLoop_4 +# ;; Append node if a +1FE00061 # CMPUI R14 R0 97 +2C6E @EditorLoop_5 # JUMP.NE R14 @EditorLoop_5 +0900040D # COPY R0 R13 +2D0F @AppendLine # CALLI R15 @AppendLine +3C00 @EditorLoop # JUMP @EditorLoop +:EditorLoop_5 +# ;; Insert node if i +1FE00069 # CMPUI R14 R0 105 +2C6E @EditorLoop_6 # JUMP.NE R14 @EditorLoop_6 +0900040D # COPY R0 R13 +2D0F @InsertLine # CALLI R15 @InsertLine +3C00 @EditorLoop # JUMP @EditorLoop +:EditorLoop_6 +# ;; Delete node if d +1FE00064 # CMPUI R14 R0 100 +2C6E @EditorLoop_7 # JUMP.NE R14 @EditorLoop_7 +0900040D # COPY R0 R13 +2D0F @RemoveLine # CALLI R15 @RemoveLine +090005D0 # MOVE R13 R0 +3C00 @EditorLoop # JUMP @EditorLoop +:EditorLoop_7 +3C00 @EditorLoop # JUMP @EditorLoop + + +# ;; GetRoot function +# ;; Walks backwards through nodes until beginning +# ;; Recieves node pointer in R0 and Returns result in R0 +# ;; Returns to whatever called it +:GetRoot +# ;; Preserve registers +0902001F # PUSHR R1 R15 +:GetRoot_0 +# ;; Get Head->Prev +18100004 # LOAD32 R1 R0 4 +A0310000 # CMPSKIP.NE R1 0 +3C00 @GetRoot_1 # JUMP @GetRoot_1 +09000501 # MOVE R0 R1 +3C00 @GetRoot_0 # JUMP @GetRoot_0 +:GetRoot_1 +# ;; Restore registers +0902801F # POPR R1 R15 +0D01001F # RET R15 + + +# ;; Printall Function +# ;; Prints all lines to Interface in R1 +# ;; Starting at node in R0 +# ;; Does not alter registers +# ;; Returns to whatever called it +:PrintAll +# ;; Preserve registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +:PrintAll_0 +18200000 # LOAD32 R2 R0 0 ; Store Head->Next in R2 +18000008 # LOAD32 R0 R0 8 ; Set R0 to Head->Text +2D0F @PrintLine # CALLI R15 @PrintLine ; Prints Head->Text +A0320000 # CMPSKIP.NE R2 0 ; If Head->Next is NULL +3C00 @PrintAll_1 # JUMP @PrintAll_1 ; Stop Looping +09000502 # MOVE R0 R2 ; Otherwise Move to Next Node +3C00 @PrintAll_0 # JUMP @PrintAll_0 ; And Loop +:PrintAll_1 +# ;; Restore registers +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + + +# ;; Printline function +# ;; Recieves a string pointer in R0 +# ;; Prints string interface specified in R1 +# ;; Does not alter registers +# ;; Returns to whatever called it +:PrintLine +# ;; Preserve registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +0902003F # PUSHR R3 R15 +# ;; Initialize +09000520 # MOVE R2 R0 +0D000023 # FALSE R3 +# ;; Deal with NULL Pointer +A0320000 # CMPSKIP.NE R2 0 +3C00 @PrintLine_1 # JUMP @PrintLine_1 +:PrintLine_0 +0503A023 # LOADXU8 R0 R2 R3 ; Load char from string +# ;; Don't print NULLs +A0300000 # CMPSKIP.NE R0 0 +3C00 @PrintLine_1 # JUMP @PrintLine_1 +42100200 # FPUTC +# ; Print the char +0F330001 # ADDUI R3 R3 1 ; Prep for next loop +3C00 @PrintLine_0 # JUMP @PrintLine_0 +:PrintLine_1 +# ;; Restore registers +0902803F # POPR R3 R15 +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + + +# ;; AppendLine Function +# ;; Recieves a Node in R0 +# ;; Creates a new Node and appends it +# ;; Does not alter registers +# ;; Returns to whatever calls it +:AppendLine +# ;; Preserve registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +# ;; Initialize +09000510 # MOVE R1 R0 +# ;; Allocate another Node +2D20000c # LOADUI R0 12 +2D0F @malloc # CALLI R15 @malloc +# ;; Check if head->Next is null +18210000 # LOAD32 R2 R1 0 +A0220000 # CMPSKIP.E R2 0 ; If head->Next is something +23020004 # STORE32 R0 R2 4 ; Set head->next->prev to p +# ;; Setup p and head +23200000 # STORE32 R2 R0 0 ; p->next = head->next +23100004 # STORE32 R1 R0 4 ; p->prev = head +23010000 # STORE32 R0 R1 0 ; head->next = p +# ;; Restore Registers +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + + +# ;; InsertLine Function +# ;; Recieves a Node in R0 +# ;; Creates a new Node and prepends it +# ;; Does not alter registers +# ;; Returns to whatever called it +:InsertLine +# ;; Preserve Registers +0902000F # PUSHR R0 R15 +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +# ;; Initialize +09000510 # MOVE R1 R0 +# ;; Allocate another Node +2D20000c # LOADUI R0 12 +2D0F @malloc # CALLI R15 @malloc +# ;; Check if Head->Prev is Null +18210004 # LOAD32 R2 R1 4 +A0220000 # CMPSKIP.E R2 0 ; If head->prev is something +23020000 # STORE32 R0 R2 0 ; Set head->prev->next to p +# ;; Setup p and head +23200004 # STORE32 R2 R0 4 ; p->prev = head->prev +23100000 # STORE32 R1 R0 0 ; p->next = head +23010004 # STORE32 R0 R1 4 ; head->prev = p +# ;; Restore Registers +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0902800F # POPR R0 R15 +0D01001F # RET R15 + + +# ;; RemoveLine Function +# ;; Recieves Node in R0 +# ;; Returns replacement node in R0 +# ;; Returns to whatever called it +:RemoveLine +# ;; Preserve Registers +0902001F # PUSHR R1 R15 +0902002F # PUSHR R2 R15 +# ;; Initialize +09000510 # MOVE R1 R0 +18010004 # LOAD32 R0 R1 4 ; put p->prev in R0 +18210000 # LOAD32 R2 R1 0 ; put p->next in R2 +# ;; Keep links +A0200000 # CMPSKIP.E R0 0 ; If p->prev is not null +23200000 # STORE32 R2 R0 0 ; p->prev->next = p->next +A0220000 # CMPSKIP.E R2 0 ; If p->next is not null +23020004 # STORE32 R0 R2 4 ; p->next->prev = p->prev +# ;; Attempt to save what is left of the list +A0300000 # CMPSKIP.NE R0 0 ; If p->prev is null +09000502 # MOVE R0 R2 ; return p->next +# ;; Restore Registers +0902802F # POPR R2 R15 +0902801F # POPR R1 R15 +0D01001F # RET R15 + + +# ;; Where our stack begins +:stack diff --git a/stage1/SET.s b/stage1/SET.s new file mode 100644 index 0000000..de16cd1 --- /dev/null +++ b/stage1/SET.s @@ -0,0 +1,467 @@ +:start + LOADUI R15 $stack ; Put stack at end of program + ;; We will be using R14 for our condition codes + ;; We will be using R13 for storage of Head + +;; Main program +;; Reads contents of Tape_01 and writes desired contents onto Tape_02 +;; Accepts no arguments and HALTS when done +:main + ;; Prep TAPE_01 + LOADUI R0 0x1100 + FOPEN_READ + + ;; Prepare to Read File + FALSE R14 + FALSE R1 + CALLI R15 @ReadFile + + ;; Done reading File + LOADUI R0 0x1100 ; Close TAPE_01 + FCLOSE + + ;; Enter Editor Loop + MOVE R13 R1 ; Set R13 to Head + CALLI R15 @EditorLoop + + ;; And We are Done + HALT + +;; Readfile function +;; Recieves pointer to head in R1 +;; Creates Nodes and imports text until EOF +;; Alters R0 R1 R14 +;; Returns to whatever called it +:ReadFile + ;; Allocate another Node + LOADUI R0 12 + CALLI R15 @malloc + ;; Get another line into list + PUSHR R1 R15 + LOADUI R1 0x1100 ; Read from tape_01 + CALLI R15 @Readline + POPR R1 R15 + SWAP R0 R1 + CALLI R15 @addline + SWAP R0 R1 + ;; Loop if not reached EOF + JUMP.Z R14 @ReadFile + RET R15 + +;; Readline function +;; Recieves Pointer to node in R0 +;; And Input in R1 +;; Allocates Text segment on Heap +;; Sets node's pointer to Text segment +;; Sets R14 to True if EOF reached +;; Returns to whatever called it +:Readline + ;; Preserve registers + PUSHR R0 R15 + PUSHR R1 R15 + PUSHR R2 R15 + PUSHR R3 R15 + PUSHR R4 R15 + ;; Initialize + MOVE R4 R0 + LOADUI R0 256 + CALLI R15 @malloc + MOVE R2 R0 + FALSE R3 +:Readline_0 + FGETC ; Read a Char + + ;; Flag if reached EOF + CMPSKIP.GE R0 0 + TRUE R14 + + ;; Stop if EOF + CMPSKIP.GE R0 0 + JUMP @Readline_2 + + ;; Handle Backspace + CMPSKIP.E R0 127 + JUMP @Readline_1 + + ;; Move back 1 character if R3 > 0 + CMPSKIP.LE R3 0 + SUBUI R3 R3 1 + + ;; Hopefully they keep typing + JUMP @Readline_0 + +:Readline_1 + ;; Replace all CR with LF + CMPSKIP.NE R0 13 + LOADUI R0 10 + + ;; Store the Byte + STOREX8 R0 R2 R3 + + ;; Check for EOL + CMPSKIP.NE R0 10 + JUMP @Readline_2 + + ;; Prevent lines from exceeding 255 chars + CMPSKIP.LE R3 255 + JUMP @Readline_2 + + ;; Prep for next loop + ADDUI R3 R3 1 + JUMP @Readline_0 + +:Readline_2 + ;; Set Text pointer + STORE32 R2 R4 8 + ;; Restore Registers + POPR R4 R15 + POPR R3 R15 + POPR R2 R15 + POPR R1 R15 + POPR R0 R15 + RET R15 + +;; addline Function +;; Recieves pointers in R0 R1 +;; Alters R0 if NULL +;; Appends nodes together +;; Returns to whatever called it +:addline + ;; Preserve Registers + PUSHR R2 R15 + PUSHR R1 R15 + PUSHR R0 R15 + + ;; Handle if Head is NULL + JUMP.NZ R0 @addline_0 + POPR R0 R15 + PUSHR R1 R15 + JUMP @addline_2 + +:addline_0 + ;; Handle if Head->next is NULL + LOAD32 R2 R0 0 + JUMP.NZ R2 @addline_1 + ;; Set head->next = p + STORE32 R1 R0 0 + ;; Set p->prev = head + STORE32 R0 R1 4 + JUMP @addline_2 + +:addline_1 + ;; Handle case of Head->next not being NULL + LOAD32 R0 R0 0 + CALLI R15 @addline + +:addline_2 + ;; Restore registers + POPR R0 R15 + POPR R1 R15 + POPR R2 R15 + RET R15 + +;; Primative malloc function +;; Recieves number of bytes to allocate in R0 +;; Returns pointer to block of that size in R0 +;; Returns to whatever called it +:malloc + ;; Preserve registers + PUSHR R1 R15 + ;; Get current malloc pointer + LOADR R1 @malloc_pointer + ;; Deal with special case + CMPSKIP.NE R1 0 ; If Zero set to our start of heap space + LOADUI R1 0x4000 + + ;; update malloc pointer + SWAP R0 R1 + ADD R1 R0 R1 + STORER R1 @malloc_pointer + +;; Done + ;; Restore registers + POPR R1 R15 + RET R15 +;; Our static value for malloc pointer +:malloc_pointer + NOP + + ;; Editor Loop + ;; Provides user interaction + ;; Requires R13 to be pointer to Head + ;; Internally loops + ;; Returns nothing +:EditorLoop + FALSE R1 ; Read from tty + FGETC ; Read a Char + + ;; Quit if q + CMPSKIP.NE R0 113 + RET R15 + + ;; Print if p + CMPUI R14 R0 112 + JUMP.NE R14 @EditorLoop_0 + LOAD32 R0 R13 8 + FALSE R1 + CALLI R15 @PrintLine + JUMP @EditorLoop + +:EditorLoop_0 + ;; Move forward if f + CMPUI R14 R0 102 + JUMP.NE R14 @EditorLoop_1 + LOAD32 R0 R13 0 ; Load head->next + + ;; If head->next isn't null make it the new head + CMPSKIP.E R0 0 + MOVE R13 R0 + JUMP @EditorLoop + +:EditorLoop_1 + ;; Move backward if b + CMPUI R14 R0 98 + JUMP.NE R14 @EditorLoop_2 + LOAD32 R0 R13 4 ; Load head->prev + + ;; If head->prev isn't null make it the new head + CMPSKIP.E R0 0 + MOVE R13 R0 + JUMP @EditorLoop + +:EditorLoop_2 + ;; Edit Line if e + CMPUI R14 R0 101 + JUMP.NE R14 @EditorLoop_3 + + ;; Change Head's Text + COPY R0 R13 + FALSE R1 ; Read from tty + CALLI R15 @Readline + + JUMP @EditorLoop + +:EditorLoop_3 + ;; Writeout to tape_02 if w + CMPUI R14 R0 119 + JUMP.NE R14 @EditorLoop_4 + + ;; Prep TAPE_02 + LOADUI R0 0x1101 + FOPEN_WRITE + + COPY R0 R13 + LOADUI R1 0x1101 + CALLI R15 @GetRoot + CALLI R15 @PrintAll + + LOADUI R0 0x1101 ; Close TAPE_02 + FCLOSE + JUMP @EditorLoop + +:EditorLoop_4 + ;; Append node if a + CMPUI R14 R0 97 + JUMP.NE R14 @EditorLoop_5 + COPY R0 R13 + CALLI R15 @AppendLine + JUMP @EditorLoop + +:EditorLoop_5 + ;; Insert node if i + CMPUI R14 R0 105 + JUMP.NE R14 @EditorLoop_6 + COPY R0 R13 + CALLI R15 @InsertLine + JUMP @EditorLoop + +:EditorLoop_6 + ;; Delete node if d + CMPUI R14 R0 100 + JUMP.NE R14 @EditorLoop_7 + COPY R0 R13 + CALLI R15 @RemoveLine + MOVE R13 R0 + JUMP @EditorLoop + +:EditorLoop_7 + JUMP @EditorLoop + +;; GetRoot function +;; Walks backwards through nodes until beginning +;; Recieves node pointer in R0 and Returns result in R0 +;; Returns to whatever called it +:GetRoot + ;; Preserve registers + PUSHR R1 R15 +:GetRoot_0 + ;; Get Head->Prev + LOAD32 R1 R0 4 + + CMPSKIP.NE R1 0 + JUMP @GetRoot_1 + + MOVE R0 R1 + JUMP @GetRoot_0 + +:GetRoot_1 + ;; Restore registers + POPR R1 R15 + RET R15 + +;; Printall Function +;; Prints all lines to Interface in R1 +;; Starting at node in R0 +;; Does not alter registers +;; Returns to whatever called it +:PrintAll + ;; Preserve registers + PUSHR R0 R15 + PUSHR R1 R15 + PUSHR R2 R15 +:PrintAll_0 + LOAD32 R2 R0 0 ; Store Head->Next in R2 + LOAD32 R0 R0 8 ; Set R0 to Head->Text + CALLI R15 @PrintLine ; Prints Head->Text + CMPSKIP.NE R2 0 ; If Head->Next is NULL + JUMP @PrintAll_1 ; Stop Looping + MOVE R0 R2 ; Otherwise Move to Next Node + JUMP @PrintAll_0 ; And Loop +:PrintAll_1 + ;; Restore registers + POPR R2 R15 + POPR R1 R15 + POPR R0 R15 + RET R15 + +;; Printline function +;; Recieves a string pointer in R0 +;; Prints string interface specified in R1 +;; Does not alter registers +;; Returns to whatever called it +:PrintLine + ;; Preserve registers + PUSHR R0 R15 + PUSHR R1 R15 + PUSHR R2 R15 + PUSHR R3 R15 + ;; Initialize + MOVE R2 R0 + FALSE R3 + ;; Deal with NULL Pointer + CMPSKIP.NE R2 0 + JUMP @PrintLine_1 +:PrintLine_0 + LOADXU8 R0 R2 R3 ; Load char from string + ;; Don't print NULLs + CMPSKIP.NE R0 0 + JUMP @PrintLine_1 + + FPUTC ; Print the char + ADDUI R3 R3 1 ; Prep for next loop + JUMP @PrintLine_0 + +:PrintLine_1 + ;; Restore registers + POPR R3 R15 + POPR R2 R15 + POPR R1 R15 + POPR R0 R15 + RET R15 + +;; AppendLine Function +;; Recieves a Node in R0 +;; Creates a new Node and appends it +;; Does not alter registers +;; Returns to whatever calls it +:AppendLine + ;; Preserve registers + PUSHR R0 R15 + PUSHR R1 R15 + PUSHR R2 R15 + ;; Initialize + MOVE R1 R0 + ;; Allocate another Node + LOADUI R0 12 + CALLI R15 @malloc + + ;; Check if head->Next is null + LOAD32 R2 R1 0 + CMPSKIP.E R2 0 ; If head->Next is something + STORE32 R0 R2 4 ; Set head->next->prev to p + + ;; Setup p and head + STORE32 R2 R0 0 ; p->next = head->next + STORE32 R1 R0 4 ; p->prev = head + STORE32 R0 R1 0 ; head->next = p + + ;; Restore Registers + POPR R2 R15 + POPR R1 R15 + POPR R0 R15 + RET R15 + +;; InsertLine Function +;; Recieves a Node in R0 +;; Creates a new Node and prepends it +;; Does not alter registers +;; Returns to whatever called it +:InsertLine + ;; Preserve Registers + PUSHR R0 R15 + PUSHR R1 R15 + PUSHR R2 R15 + ;; Initialize + MOVE R1 R0 + ;; Allocate another Node + LOADUI R0 12 + CALLI R15 @malloc + + ;; Check if Head->Prev is Null + LOAD32 R2 R1 4 + CMPSKIP.E R2 0 ; If head->prev is something + STORE32 R0 R2 0 ; Set head->prev->next to p + + ;; Setup p and head + STORE32 R2 R0 4 ; p->prev = head->prev + STORE32 R1 R0 0 ; p->next = head + STORE32 R0 R1 4 ; head->prev = p + + ;; Restore Registers + POPR R2 R15 + POPR R1 R15 + POPR R0 R15 + RET R15 + + +;; RemoveLine Function +;; Recieves Node in R0 +;; Returns replacement node in R0 +;; Returns to whatever called it +:RemoveLine + ;; Preserve Registers + PUSHR R1 R15 + PUSHR R2 R15 + ;; Initialize + MOVE R1 R0 + LOAD32 R0 R1 4 ; put p->prev in R0 + LOAD32 R2 R1 0 ; put p->next in R2 + + ;; Keep links + CMPSKIP.E R0 0 ; If p->prev is not null + STORE32 R2 R0 0 ; p->prev->next = p->next + + CMPSKIP.E R2 0 ; If p->next is not null + STORE32 R0 R2 4 ; p->next->prev = p->prev + + ;; Attempt to save what is left of the list + CMPSKIP.NE R0 0 ; If p->prev is null + MOVE R0 R2 ; return p->next + + ;; Restore Registers + POPR R2 R15 + POPR R1 R15 + RET R15 + +;; Where our stack begins +:stack