summary refs log tree commit diff
path: root/quine.asm
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@irenes.space>2025-10-30 00:47:58 -0700
committerIrene Knapp <ireneista@irenes.space>2025-10-30 00:47:58 -0700
commit7207d6ef21d53a8f5805e3de755d9982c6bdee2e (patch)
tree14ee9fa4d1b8f56614f16ee9759f5314f1e8ad26 /quine.asm
parent088bc863865717433056dd4d959a014c2db7ca8f (diff)
get rid of the redundant copy of the label value
Force-Push: yes
Change-Id: I5709b96b401362564cc0f1dec3953dad13c319b7
Diffstat (limited to 'quine.asm')
-rw-r--r--quine.asm78
1 files changed, 49 insertions, 29 deletions
diff --git a/quine.asm b/quine.asm
index 35c5920..64f55d3 100644
--- a/quine.asm
+++ b/quine.asm
@@ -2605,32 +2605,43 @@ defword QUINE, 0
   ; ... and now we have allocated a block of memory, with its address on the
   ; stack. We also still have HEAP at the bottom of the stack, for future use.
 
-  ; We have one label, and three pieces of information about it: Guessed value,
-  ; actual value, and status. We keep them on the stack in this order, from
-  ; top to bottom: guess, actual, status. Above that, at the actual top of
-  ; the stack, we have a mutable copy of the buffer's address.
+  ; We have one label, and two pieces of information about it: value and
+  ; status. We keep them on the stack. We also have a mutable copy of the
+  ; buffer's address.
+  ;
+  ; This stack layout is the interface used throughout the "assembler"; this
+  ; QUINE routine uses it when calling the routines that build the various
+  ; pieces of the output, and those pieces in turn use it when calling the
+  ; label-handling routines.
+  ;
+  ; Stack:
+  ;   HEAP
+  ;   start address of allocated output
+  ;   label's value
+  ;   label's status
+  ;   address of current output point within allocated block
+  ; (top)
   ;
   ; Status is a bit field:
   ;    bit zero is whether it was used before being defined
   ;    bit one is whether it's been defined
   ;    bit two is whether the guessed value wound up equaling the actual value
-  dq DUP, LIT, 0, LIT, 0, LIT, 0, LIT, 4, ROLL
+  dq DUP, LIT, 0, LIT, 0, ROLL3
 
-  ; This takes an address to write to on the stack and adds an ELF file header
-  ; to it, leaving the adjusted address with the size of the header added.
-  ; Then it does the same thing with an ELF program header.
-  dq ELF_FILE_HEADER, ELF_PROGRAM_HEADER, SELF_RAW
+  ; This takes an address to write to on the stack, writes stuff there, and
+  ; returns the next address after where it stopped Writing.
+  dq ALL_CONTENTS
 
-  ; The two-pass magick.
-  dq SET_LABEL
-  dq DROP, LIT, 4, ROLL, DUP, LIT, 5, UNROLL
-  dq ELF_FILE_HEADER, ELF_PROGRAM_HEADER, SELF_RAW
+  ; The two-pass magick: ; Reset the output offset to the beginning of the
+  ; block.
+  dq DROP, ROLL3, DUP, LIT, 4, UNROLL
+  dq ALL_CONTENTS
 
   ; Drop the copy of the buffer's address.
   dq DROP
 
   ; Drop the label data.
-  dq DROP, DROP, DROP
+  dq DROP, DROP
 
   ; This takes a buffer's address on the stack, skips an ELF file header and
   ; program header based on hardcoded size, computes an offset (secretly
@@ -2647,14 +2658,12 @@ defword QUINE, 0
 
 ; Stack in:
 ;   output memory start
-;   label actual value
-;   label guessed value
+;   label value (guessed or actual)
 ;   label status
 ;   output memory current point
 ; Stack out:
 ;   output memory start
-;   label actual value
-;   label guessed value
+;   label value (guessed or actual)
 ;   label status (potentially modified)
 ;   output memory current point
 ;   label value for caller to use
@@ -2669,7 +2678,7 @@ defword USE_LABEL, 0
   ; If we're here, it has been set already, so just put the status back...
   dq SWAP
   ; Fetch the actual value...
-  dq LIT, 4, ROLL, DUP, LIT, 5, UNROLL
+  dq LIT, 3, ROLL, DUP, LIT, 4, UNROLL
   ; ... and exit
   dq EXIT
 
@@ -2684,32 +2693,33 @@ defword USE_LABEL, 0
 
 ; Stack in:
 ;   output memory start
-;   label actual value (not yet set)
-;   label guessed value
+;   label value (guessed or actual)
 ;   label status
 ;   output memory current point
 ; Stack out:
 ;   output memory start
-;   label actual value (now set)
-;   label guessed value
+;   label value (now set to actual)
 ;   label status (modified)
 ;   output memory current point
 defword SET_LABEL, 0
   dq DOCOL
 
   ; Compute the current offset, to use as the actual value
-  dq DUP, LIT, 6, ROLL, DUP, LIT, 7, UNROLL, SUB
+  dq DUP, LIT, 5, ROLL, DUP, LIT, 6, UNROLL, SUB
+      ; old value, status, point, new value
 
   ; Overwrite the old actual value; keep a copy
-  dq LIT, 5, ROLL, DROP, DUP, LIT, 5, UNROLL
-
-  ; Check equality with the guessed value
-  dq LIT, 4, ROLL, DUP, LIT, 5, UNROLL, EQ
+  dq DUP, LIT, 5, ROLL
+      ; status, point, new value, new value, old value
+  dq EQ, SWAP
+      ; status, point, equality, new value
+  dq LIT, 4, UNROLL
+      ; new value, status, point, equality
 
   ; We don't need to branch. Now we mark the status as having been defined,
   ; and we also set bit 2 if appropriate.
   dq LIT, 4, MUL
-  dq LIT, 3, ROLL, OR, LIT, 2, OR, LIT, 2, UNROLL
+  dq LIT, 3, ROLL, OR, LIT, 2, OR, SWAP
 
   dq EXIT
 
@@ -2719,6 +2729,16 @@ defword HLT, 0
   hlt
 
 
+; This takes an address to write to on the stack, writes stuff there, and
+; returns the next address after where it stopped Writing.
+;
+; It also makes use of label stuff, further back on the stack.
+defword ALL_CONTENTS, 0
+  dq DOCOL                       ; codeword
+  dq ELF_FILE_HEADER, ELF_PROGRAM_HEADER, SELF_RAW
+  dq SET_LABEL
+  dq EXIT
+
 ;;;
 ;;; ELF header
 ;;;