summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--quine.asm145
1 files changed, 94 insertions, 51 deletions
diff --git a/quine.asm b/quine.asm
index a25e1c5..50f245f 100644
--- a/quine.asm
+++ b/quine.asm
@@ -2118,9 +2118,14 @@ 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.
 
-  ; This takes a buffer's address on the stack, populates it, then finishes by
-  ; pushing its length and address. Thus we don't need to care about how it
-  ; internally uses registers.
+  ; This takes a buffer's address on the stack and adds an ELF file header to
+  ; it, leaving nothing on the stack afterwards.
+  dq DUP, ELF_FILE_HEADER, ELF_PROGRAM_HEADER, DROP
+
+  ; This takes a buffer's address on the stack, skips an ELF file header based
+  ; on hardcoded size, appends an ELF program header, then finishes by pushing
+  ; the length of the part of the buffer that has now been used. Thus we don't
+  ; need to care about how it internally uses registers.
   dq DUP, OLD_CODE, SWAP
 
   ; write() from stack-allocated buffer
@@ -2145,6 +2150,92 @@ defword WRITE_SELF_RAW_H, 0
   NEXT
 
 
+; In: base address, value
+; Out: new base address
+defword PACK, 0
+  dq DOCOL                       ; codeword
+  dq SWAP, DUP, ROLLD3, STORE, LIT, 8, ADD
+  dq EXIT
+defword PACK8, 0
+  dq DOCOL                       ; codeword
+  dq SWAP, DUP, ROLLD3, STORE8, LIT, 1, ADD
+  dq EXIT
+defword PACK16, 0
+  dq DOCOL                       ; codeword
+  dq SWAP, DUP, ROLLD3, STORE16, LIT, 2, ADD
+  dq EXIT
+defword PACK32, 0
+  dq DOCOL                       ; codeword
+  dq SWAP, DUP, ROLLD3, STORE32, LIT, 4, ADD
+  dq EXIT
+
+
+;;;
+;;; ELF header
+;;;
+;;;   This is the top-level ELF header, for the entire file. An ELF always has
+;;; exactly one of this header, which is always at the start of the file.
+;;;
+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 LIT, 2, PACK16                         ; executable
+  dq LIT, 0x3e, PACK16                      ; Intel x86-64
+  dq LIT, 1, PACK32                         ; ELF format version
+
+  ; Compute the entry pointer.
+  dq LIT, _start, PACK                      ; entry point
+    ; The offset of _start. This includes the origin, intentionally.
+
+  dq LIT, 64, PACK                          ; 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 EXIT
+
+
+;;;
+;;; Program header
+;;;
+;;;   An ELF program header consists of any number of these entries; they are
+;;; always consecutive, but may be anywhere in the file. We always have
+;;; exactly one, and it's always right after the ELF file header.
+;;;
+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
+    ; required, but can be anything, subject to alignment
+  dq LIT, 0, PACK16                        ; 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 LIT, 0, PACK                          ; segment alignment
+    ; for relocation, but this doesn't apply to us
+
+  dq EXIT
+
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;; (old) Implementation strategy ;;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2179,58 +2270,10 @@ defword OLD_CODE, 0
   pop.qreg rcx                             ; our parameter - a block of memory
   mov.dreg.dimm rdx, 0                     ; store running file size here
 
-  ;;;
-  ;;; ELF header
-  ;;;
-  mov.qreg.disp8.dimm rcx, 0x00, 0x7F bappend "ELF"  ; magic number
-  mov.qreg.disp8.bimm rcx, 0x04, 2         ; 64-bit
-  mov.qreg.disp8.bimm rcx, 0x05, 1         ; little-endian
-  mov.qreg.disp8.bimm rcx, 0x06, 1         ; ELF header format version 1
-  mov.qreg.disp8.bimm rcx, 0x07, 0         ; System-V ABI
-  mov.qreg.disp8.dimm rcx, 0x08, 0         ; (padding)
-
-  mov.qreg.disp8.wimm rcx, 0x10, 2         ; executable
-  mov.qreg.disp8.wimm rcx, 0x12, 0x3E      ; Intel x86-64
-  mov.qreg.disp8.dimm rcx, 0x14, 1         ; ELF format version
-
-  ; Compute the entry pointer.
-  mov.qreg.qimm rax, _start                ; the offset of _start
-    ; This includes the origin, intentionally.
-  mov.qreg.disp8.qreg rcx, 0x18, rax       ; entry point
-
-  mov.qreg.disp8.dimm rcx, 0x20, 64        ; program header offset
-    ; We place the program header immediately after the ELF header. This
-    ; offset is from the start of the file.
-  mov.qreg.disp8.dimm rcx, 0x28, 0         ; section header offset
-  mov.qreg.disp8.dimm rcx, 0x30, 0         ; processor flags
-  mov.qreg.disp8.wimm rcx, 0x34, 64        ; ELF header size
-  mov.qreg.disp8.wimm rcx, 0x36, 56        ; program header entry size
-  mov.qreg.disp8.wimm rcx, 0x38, 1         ; number of program header entries
-  mov.qreg.disp8.wimm rcx, 0x3a, 0         ; section header entry size
-  mov.qreg.disp8.wimm rcx, 0x3c, 0         ; number of section header entries
-  mov.qreg.disp8.wimm rcx, 0x3e, 0         ; section name string table index
-
   ; Add the size of the ELF header to the running total
   mov.dreg.dimm rax, 0x40
   add.qreg.qreg rdx, rax
 
-  ;;;
-  ;;; Program header
-  ;;;
-  mov.qreg.disp8.dimm rcx, 0x40, 1         ; "loadable" segment type
-  mov.qreg.disp8.dimm rcx, 0x44, 0x05      ; read+execute permission
-  mov.qreg.disp8.dimm rcx, 0x48, 0         ; offset in file
-  mov.qreg.disp8.dimm rcx, 0x50, $$        ; virtual address
-    ; required, but can be anything, subject to alignment
-  mov.qreg.disp8.dimm rcx, 0x58, 0         ; physical address (ignored)
-
-  ; Fill in 0 as the file size for now, to avoid unitialized memory.
-  mov.qreg.disp8.dimm rcx, 0x60, 0         ; size in file
-  mov.qreg.disp8.dimm rcx, 0x68, 0         ; size in memory
-
-  mov.qreg.disp8.dimm rcx, 0x70, 0         ; segment alignment
-    ; for relocation, but this doesn't apply to us
-
   ; Add the size of the program header to the running total
   mov.dreg.dimm rax, 0x38
   add.qreg.qreg rdx, rax