diff options
| author | Irene Knapp <ireneista@irenes.space> | 2025-11-28 20:19:19 -0800 |
|---|---|---|
| committer | Irene Knapp <ireneista@irenes.space> | 2025-11-28 20:19:19 -0800 |
| commit | 445bc67265016be9867127bb5fa38341c5ef9dc0 (patch) | |
| tree | 4875ee1b53d23c3dd65a1039143cf91aa4fbb907 | |
| parent | 7504fa3a7926282fffc4b7c9a34073aafeeda7c1 (diff) | |
add the code to traverse from execution token back to dictionary entry
yay Force-Push: yes Change-Id: I21d21df017db6df3c1b60288f0b8c7270f01ded8
| -rw-r--r-- | quine.asm | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/quine.asm b/quine.asm index 5d79b36..c13744f 100644 --- a/quine.asm +++ b/quine.asm @@ -1259,6 +1259,15 @@ macro rep operation end match end macro +macro repz operation + match =scasb, operation + db 0xF3 ; rep prefix + db 0xAe ; opcode + else + assert 0 + end match +end macro + macro repnz operation match =scasb, operation db 0xF2 ; rep prefix @@ -3318,6 +3327,55 @@ defword stringlen, 0 push.qreg rdi next +; Stack in: +; address of final non-null byte at the end of a string +; Stack out: +; backwards string length not including null byte at start +defword reverse_stringlen, 0 + dq $ + 8 + pop.qreg rdi + + mov.qreg.qreg rbx, rdi + xor.qreg.qreg rax, rax + xor.qreg.qreg rcx, rcx + not.qreg rcx + + std + repnz scasb + cld + + sub.qreg.qreg rbx, rdi + sub.qreg.bimm rbx, 1 + + push.qreg rbx + next + +; If you have a variable-length string followed by alignment padding, and +; you want to traverse it in reverse, you also need to skip the alignment +; padding... +; +; Stack in: +; address of final null byte in alignment padding of total length up to 8 +; Stack out: +; number of null bytes (from end) until nearest non-null byte, or 8 +defword reverse_padding_len, 0 + dq $ + 8 + pop.qreg rdi + + mov.qreg.qreg rbx, rdi + xor.qreg.qreg rax, rax + mov.qreg.dimm rcx, 8 + + std + repz scasb + cld + + sub.qreg.qreg rbx, rdi + sub.qreg.bimm rbx, 1 + + push.qreg rbx + next + ; We make this work using exactly two jump instructions, which is likely the ; minimum possible. To avoid relying on labels, we hand-compute the byte ; offsets, so every instruction within their ranges is annotated with its @@ -4834,6 +4892,22 @@ defword entry_to_execution_token, 0 dq lit, 7, invert, and dq exit +defword entry_to_name, 0 + dq docol + dq lit, 10, add + dq exit + +; Jonesforth calls this "CFA>". Jonesforth's implementation searches the +; entire dictionary, since its word header format isn't designed to be +; traversed in reverse as ours is. +defword execution_token_to_entry, 0 + dq docol + dq lit, 1, sub + dq dup, reverse_padding_len, sub + dq dup, reverse_stringlen, sub + dq lit, 9, sub + dq exit + ; Allocate space by incrementing "here", and output a word header in it. ; Also add it to the "latest" linked list. Use zero as the flag values; ; callers that want something else can do that themselves. |