From 7207d6ef21d53a8f5805e3de755d9982c6bdee2e Mon Sep 17 00:00:00 2001 From: Irene Knapp Date: Thu, 30 Oct 2025 00:47:58 -0700 Subject: get rid of the redundant copy of the label value Force-Push: yes Change-Id: I5709b96b401362564cc0f1dec3953dad13c319b7 --- quine.asm | 78 +++++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 29 deletions(-) (limited to 'quine.asm') 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 ;;; -- cgit 1.4.1