diff options
Diffstat (limited to 'quine.asm')
| -rw-r--r-- | quine.asm | 114 |
1 files changed, 82 insertions, 32 deletions
diff --git a/quine.asm b/quine.asm index 50f245f..22ebb1e 100644 --- a/quine.asm +++ b/quine.asm @@ -1362,6 +1362,32 @@ macro NEXT end macro ;;; +;;; Macro BEFORENEXT +;;; ---------------- +;;; +;;; Sometimes we want to transfer control from a word implemented in +;;; machine-code to another word, without coming back after, as if we were +;;; simply jumping to it. This is an innovation of ours; Jonesforth doesn't do +;;; it. +;;; +;;; This implementation will work regardless of how the receiving word is +;;; implemented. It impersonates NEXT, setting up rax to point to the codeword +;;; then jumping to the interpreter. Since it doesn't change the control +;;; stack or rsi, when the receiving word eventually invokes NEXT, it will +;;; pick up in the same place as if this sending word had done it. +;;; +;;; Thus, notionally we are doing just this one transfer of control before +;;; eventually getting around to inlining NEXT. Hence the name. +;;; +macro BEFORENEXT target + ; Do a permanent transfer of control by setting rax and invoking the + ; codeword. Of course, we could jump to DOCOL ourselves but this will work + ; regardless of what the receiving codeword is. + mov.qreg.qimm rax, target + jmp.abs.indirect.qreg rax +end macro + +;;; ;;; Macros PUSHCONTROL ;;; POPCONTROL ;;; ------------------ @@ -2152,23 +2178,47 @@ defword WRITE_SELF_RAW_H, 0 ; In: base address, value ; Out: new base address -defword PACK, 0 +defword PACK64, 0 dq DOCOL ; codeword dq SWAP, DUP, ROLLD3, STORE, LIT, 8, ADD dq EXIT -defword PACK8, 0 +defword PACK32, 0 dq DOCOL ; codeword - dq SWAP, DUP, ROLLD3, STORE8, LIT, 1, ADD + dq SWAP, DUP, ROLLD3, STORE32, LIT, 4, ADD dq EXIT defword PACK16, 0 dq DOCOL ; codeword dq SWAP, DUP, ROLLD3, STORE16, LIT, 2, ADD dq EXIT -defword PACK32, 0 +defword PACK8, 0 dq DOCOL ; codeword - dq SWAP, DUP, ROLLD3, STORE32, LIT, 4, ADD + dq SWAP, DUP, ROLLD3, STORE8, LIT, 1, ADD dq EXIT +; In the interests of reducing our executable's size, since a lot of it goes +; to PACK* invocations, we define words that combine LIT with PACK*. This +; shaves roughly 700 bytes as of when it was added. +defword LITPACK64, 0 + dq $ + 0x8 ; codeword + lodsq + push.qreg rax + BEFORENEXT PACK64 +defword LITPACK32, 0 + dq $ + 0x8 ; codeword + lodsq + push.qreg rax + BEFORENEXT PACK32 +defword LITPACK16, 0 + dq $ + 0x8 ; codeword + lodsq + push.qreg rax + BEFORENEXT PACK16 +defword LITPACK8, 0 + dq $ + 0x8 ; codeword + lodsq + push.qreg rax + BEFORENEXT PACK8 + ;;; ;;; ELF header @@ -2179,32 +2229,32 @@ defword PACK32, 0 defword ELF_FILE_HEADER, 0 dq DOCOL ; codeword - dq LIT, 0x7f bappend "ELF", PACK32 ; magic number - dq LIT, 2, PACK8 ; 64-bit - dq LIT, 1, PACK8 ; little-endian - dq LIT, 1, PACK8 ; ELF header format v1 - dq LIT, 0, PACK8 ; System-V ABI - dq LIT, 0, PACK ; (padding) + dq LITPACK32, 0x7f bappend "ELF" ; magic number + dq LITPACK8, 2 ; 64-bit + dq LITPACK8, 1 ; little-endian + dq LITPACK8, 1 ; ELF header format v1 + dq LITPACK8, 0 ; System-V ABI + dq LITPACK64, 0 ; (padding) - dq LIT, 2, PACK16 ; executable - dq LIT, 0x3e, PACK16 ; Intel x86-64 - dq LIT, 1, PACK32 ; ELF format version + dq LITPACK16, 2 ; executable + dq LITPACK16, 0x3e ; Intel x86-64 + dq LITPACK32, 1 ; ELF format version ; Compute the entry pointer. - dq LIT, _start, PACK ; entry point + dq LITPACK64, _start ; entry point ; The offset of _start. This includes the origin, intentionally. - dq LIT, 64, PACK ; program header offset + dq LITPACK64, 64 ; program header offset ; We place the program header immediately after the ELF header. This ; offset is from the start of the file. - dq LIT, 0, PACK ; section header offset - dq LIT, 0, PACK32 ; processor flags - dq LIT, 64, PACK16 ; ELF header size - dq LIT, 56, PACK16 ; program header entry size - dq LIT, 1, PACK16 ; number of program header entries - dq LIT, 0, PACK16 ; section header entry size - dq LIT, 0, PACK16 ; number of section header entries - dq LIT, 0, PACK16 ; section name string table index + dq LITPACK64, 0 ; section header offset + dq LITPACK32, 0 ; processor flags + dq LITPACK16, 64 ; ELF header size + dq LITPACK16, 56 ; program header entry size + dq LITPACK16, 1 ; number of program header entries + dq LITPACK16, 0 ; section header entry size + dq LITPACK16, 0 ; number of section header entries + dq LITPACK16, 0 ; section name string table index dq EXIT @@ -2219,18 +2269,18 @@ defword ELF_FILE_HEADER, 0 defword ELF_PROGRAM_HEADER, 0 dq DOCOL ; codeword - dq LIT, 1, PACK32 ; "loadable" segment type - dq LIT, 0x05, PACK32 ; read+execute permission - dq LIT, 0, PACK ; offset in file - dq LIT, $$, PACK ; virtual address + dq LITPACK32, 1 ; "loadable" segment type + dq LITPACK32, 0x05 ; read+execute permission + dq LITPACK64, 0 ; offset in file + dq LITPACK64, $$ ; virtual address ; required, but can be anything, subject to alignment - dq LIT, 0, PACK16 ; physical address (ignored) + dq LITPACK16, 0 ; physical address (ignored) ; Fill in 0 as the file size for now, to avoid unitialized memory. - dq LIT, 0, PACK ; size in file - dq LIT, 0, PACK ; size in memory + dq LITPACK64, 0 ; size in file + dq LITPACK64, 0 ; size in memory - dq LIT, 0, PACK ; segment alignment + dq LITPACK64, 0 ; segment alignment ; for relocation, but this doesn't apply to us dq EXIT |