diff --git a/quine.asm b/quine.asm
index 7e15a51..3b6df78 100644
--- a/quine.asm
+++ b/quine.asm
@@ -14,7 +14,7 @@
;;;
;;; A workflow you may wish to use for debugging is:
;;;
-;;; rm quine2; fasmg quine.asm quine && ./quine > quine2; echo "exit code:" $?; echo; hexdump -C quine; echo; hexdump -C quine2; echo; cmp quine quine2 ; echo cmp: $?
+;;; rm quine2; fasmg quine.asm quine && ./quine > quine2; echo "exit code:" $?; echo; hexdump -C quine; echo; hexdump -C quine2; echo; cmp -l quine quine2 ; echo cmp: $?
;;;
;;; The reason this removes the old one first is that otherwise, there's a
;;; risk the error message will be scrolled off the top of the screen and
@@ -73,7 +73,7 @@ end macro
macro qwordreg result, register
match =rax?, register
result = 0
- else match =rcx?, regiser
+ else match =rcx?, register
result = 1
else match =rdx?, register
result = 2
@@ -265,9 +265,7 @@ end macro
; This uses opcode 0xC6, which has w = 0. Since we run in 64-bit mode, that
; makes the operand size 8 bits, regardless of the current operand-size
; attribute. [Intel] volume 2D, appendix B, section B-1.4.3, table B-6.
-;
-; TODO this should be mov.(something).disp8
-macro mov.rel.b target, offset, source
+macro mov.qreg.disp8.bimm target, offset, source
match =rsp, target
db 0xC6
modrm 1, 0, 4
@@ -286,7 +284,7 @@ end macro
; us an operand size of 32 bits by default. [Intel] volume 1, section 3.6.1,
; table 3-4. We want a 16-bit operand, so we use the operand-size prefix,
; 0x66, and we leave REX.W unset.
-macro mov.rel.w target, offset, source
+macro mov.qreg.disp8.wimm target, offset, source
match =rsp, target
db 0x66
db 0xC7
@@ -305,7 +303,7 @@ end macro
; This uses opcode 0x67, which has w = 1. We run in 64-bit mode, so that gives
; us an operand size of 32 by default. [Intel] volume 2D, section B.1.43,
; table B-6. This is what we want, so we leave it.
-macro mov.rel.d target, offset, source
+macro mov.qreg.disp8.dimm target, offset, source
match =rsp, target
db 0xC7
modrm 1, 0, 4
@@ -321,7 +319,7 @@ end macro
; register, with an 8-bit displacement and no indexing.
;
; This uses opcode 0x89.
-macro mov.rel.q target, offset, source
+macro mov.qreg.disp8.qreg target, offset, source
match =rsp, target
qwordreg sreg, source
rex.w
@@ -343,7 +341,7 @@ end macro
; gives us an operand size of 32 by default. [Intel] volume 2D,
; section B.1.43, table B-6. We want a 64-bit operand, so we use the REX.W
; prefix, 0x48.
-macro mov.rel.q.d target, offset, source
+macro mov.qreg.disp8.dimm target, offset, source
match =rsp, target
rex.w
db 0xC7
@@ -682,9 +680,32 @@ DOCOL:
mov.qreg.qreg rsi, rax
NEXT
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Implementation strategy ;;;
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Routine _start
+;;; --------------
+;;;
+;;; This is the entry point of the whole program, the very first code we
+;;; actually execute. We go with the name linkers generally use for it, though
+;;; it's not very Forth-y. The ELF header points to it.
+;;;
+;;; The kernel gives us most registers zeroed, and rsp pointing to the
+;;; command-line stuff (argc, argv, envp), which is at an ASLR'd address with
+;;; some stack space allocated for us, despite the fact we didn't request any.
+;;; It also gives us all the flags clear except IF, but we don't rely on that.
+;;; Lastly, of course, it loads our code segment and sets the instruction
+;;; pointer where we asked; we don't need to check what those addresses are,
+;;; because they're not randomized.
+;;;
+;;; This routine is really only responsible for one-time initialization.
+;;;
+_start:
+ cld ; clear the DF flag
+ ; If we wanted to save the initial stack pointer, we'd do that here.
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; (old) Implementation strategy ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;
;;; We assemble the entire file contents in a stack-allocated buffer.
;;; We avoid using the stack for any other purpose. When the file is fully
@@ -704,45 +725,40 @@ DOCOL:
;;;
;;; * rsp points to the bottom of the buffer.
;;;
-_start:
- ;;;
- ;;; Initialize registers
- ;;;
- cld ; clear the DF flag
mov.dreg.dimm rdx, 0 ; store running file size here
- sub.qreg.bimm rsp, 0xFF ; reserve stack space
+ ;sub.qreg.bimm rsp, 0xFF ; reserve stack space
;;;
;;; ELF header
;;;
- mov.rel.d rsp, 0x00, 0x7F bappend "ELF" ; magic number
- mov.rel.b rsp, 0x04, 2 ; 64-bit
- mov.rel.b rsp, 0x05, 1 ; little-endian
- mov.rel.b rsp, 0x06, 1 ; ELF header format version 1
- mov.rel.b rsp, 0x07, 0 ; System-V ABI
- mov.rel.q.d rsp, 0x08, 0 ; (padding)
+ mov.qreg.disp8.dimm rsp, 0x00, 0x7F bappend "ELF" ; magic number
+ mov.qreg.disp8.bimm rsp, 0x04, 2 ; 64-bit
+ mov.qreg.disp8.bimm rsp, 0x05, 1 ; little-endian
+ mov.qreg.disp8.bimm rsp, 0x06, 1 ; ELF header format version 1
+ mov.qreg.disp8.bimm rsp, 0x07, 0 ; System-V ABI
+ mov.qreg.disp8.dimm rsp, 0x08, 0 ; (padding)
- mov.rel.w rsp, 0x10, 2 ; executable
- mov.rel.w rsp, 0x12, 0x3E ; Intel x86-64
- mov.rel.d rsp, 0x14, 1 ; ELF format version
+ mov.qreg.disp8.wimm rsp, 0x10, 2 ; executable
+ mov.qreg.disp8.wimm rsp, 0x12, 0x3E ; Intel x86-64
+ mov.qreg.disp8.dimm rsp, 0x14, 1 ; ELF format version
; Compute the entry pointer.
mov.qreg.qimm rax, $$ ; the memory origin
add.qreg.bimm rax, 0x78 ; the size of the headers
add.qreg.dimm rax, 155 ; the offset of _start
- mov.rel.q rsp, 0x18, rax ; entry point
+ mov.qreg.disp8.qreg rsp, 0x18, rax ; entry point
- mov.rel.q.d rsp, 0x20, 64 ; program header offset
+ mov.qreg.disp8.dimm rsp, 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.rel.q.d rsp, 0x28, 0 ; section header offset
- mov.rel.d rsp, 0x30, 0 ; processor flags
- mov.rel.w rsp, 0x34, 64 ; ELF header size
- mov.rel.w rsp, 0x36, 56 ; program header entry size
- mov.rel.w rsp, 0x38, 1 ; number of program header entries
- mov.rel.w rsp, 0x3a, 0 ; section header entry size
- mov.rel.w rsp, 0x3c, 0 ; number of section header entries
- mov.rel.w rsp, 0x3e, 0 ; section name string table index
+ mov.qreg.disp8.dimm rsp, 0x28, 0 ; section header offset
+ mov.qreg.disp8.dimm rsp, 0x30, 0 ; processor flags
+ mov.qreg.disp8.wimm rsp, 0x34, 64 ; ELF header size
+ mov.qreg.disp8.wimm rsp, 0x36, 56 ; program header entry size
+ mov.qreg.disp8.wimm rsp, 0x38, 1 ; number of program header entries
+ mov.qreg.disp8.wimm rsp, 0x3a, 0 ; section header entry size
+ mov.qreg.disp8.wimm rsp, 0x3c, 0 ; number of section header entries
+ mov.qreg.disp8.wimm rsp, 0x3e, 0 ; section name string table index
; Add the size of the ELF header to the running total
mov.dreg.dimm rax, 0x40
@@ -751,19 +767,19 @@ _start:
;;;
;;; Program header
;;;
- mov.rel.d rsp, 0x40, 1 ; "loadable" segment type
- mov.rel.d rsp, 0x44, 0x05 ; read+execute permission
- mov.rel.q.d rsp, 0x48, 0 ; offset in file
- mov.rel.q.d rsp, 0x50, $$ ; virtual address
+ mov.qreg.disp8.dimm rsp, 0x40, 1 ; "loadable" segment type
+ mov.qreg.disp8.dimm rsp, 0x44, 0x05 ; read+execute permission
+ mov.qreg.disp8.dimm rsp, 0x48, 0 ; offset in file
+ mov.qreg.disp8.dimm rsp, 0x50, $$ ; virtual address
; required, but can be anything, subject to alignment
- mov.rel.q.d rsp, 0x58, 0 ; physical address (ignored)
+ mov.qreg.disp8.dimm rsp, 0x58, 0 ; physical address (ignored)
; Fill in 0 as the file size for now, to avoid unitialized memory.
- mov.rel.q.d rsp, 0x60, 0 ; size in file
- mov.rel.q.d rsp, 0x68, 0 ; size in memory
+ mov.qreg.disp8.dimm rsp, 0x60, 0 ; size in file
+ mov.qreg.disp8.dimm rsp, 0x68, 0 ; size in memory
- mov.rel.q.d rsp, 0x70, 0 ; segment alignment
- ; for relocation - will we be ASLR'd?
+ mov.qreg.disp8.dimm rsp, 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
@@ -773,14 +789,14 @@ _start:
;;; way to generate it.
;;;
;;; TODO of course, really we want to for-real track this
- mov.qreg.qimm rax, 0x200
+ mov.qreg.qimm rax, 0x201
add.qreg.qreg rdx, rax
;;;
;;; Go back and fill in the file size now that we know it.
;;;
- mov.rel.q rsp, 0x60, rdx ; size in file
- mov.rel.q rsp, 0x68, rdx ; size in memory
+ mov.qreg.disp8.qreg rsp, 0x60, rdx ; size in file
+ mov.qreg.disp8.qreg rsp, 0x68, rdx ; size in memory
;;;
;;; The buffer is ready; output the file.
|