diff options
-rw-r--r-- | asm-notes.txt | 6 | ||||
-rw-r--r-- | quine.asm | 76 |
2 files changed, 61 insertions, 21 deletions
diff --git a/asm-notes.txt b/asm-notes.txt index 03bf335..e3c4d67 100644 --- a/asm-notes.txt +++ b/asm-notes.txt @@ -1,4 +1,10 @@ +HLT will drop you into the debugger + db 0xf4 ; HLT DO NOT SUBMIT +or perhaps you want to do a clean exit() + mov.b rax, 60 ; DO NOT SUBMIT + mov.b rdi, 0 ; DO NOT SUBMIT + syscall ; DO NOT SUBMIT ; opcode c7 is Ev, Iz. c6 is Eb, Ib diff --git a/quine.asm b/quine.asm index 9e33bbc..5c4357b 100644 --- a/quine.asm +++ b/quine.asm @@ -269,7 +269,7 @@ macro mov.indirect.qreg.qreg target, source qwordreg sreg, source qwordreg treg, target rex.w - rb 0x89 + db 0x89 modrm 1, sreg, treg db 0 end match @@ -532,12 +532,31 @@ end macro ; of doing anything with the memory, just store the address itself into a ; register. macro lea.qreg.qreg.disp8 target, offset, source - rex.w - db 0x8D - qwordreg treg, target - qwordreg sreg, source - modrm 1, treg, sreg - db offset + match =rsp, target + ; This is the SIB case + assert 0 + else + qwordreg treg, target + qwordreg sreg, source + rex.w + db 0x8D + modrm 1, treg, sreg + db offset + end match +end macro + +macro lea.qreg.qreg.disp32 target, offset, source + match =rsp, target + ; This is the SIB case + assert 0 + else + qwordreg treg, target + qwordreg sreg, source + rex.w + db 0x8D + modrm 2, treg, sreg + dd offset + end match end macro ; Clear the DF flag. This makes string instructions increment RSI. @@ -590,7 +609,7 @@ end macro macro jmp.abs.indirect.qreg location qwordreg lreg, location db 0xFF - modrm 0, lreg, 4 + modrm 0, 4, lreg end macro ; There in no 64-bit immediate "near" jump, so we use 32-bit. It's relatve, @@ -898,8 +917,8 @@ DOCOL: NEXT ;;; -;;; Routine start -;;; ------------- +;;; Routine _start +;;; -------------- ;;; ;;; This is the entry point of the whole program, the very first code we ;;; actually execute. Linkers traditionally call this _start, and on balance @@ -1017,6 +1036,19 @@ _start: mov.qreg.qreg rdi, rax ;;; + ;;; We also initialize rbp. We could hold off and let QUIT do this, but + ;;; doing it now is the easiest way to initialize the R0 variable, since + ;;; there's no instruction that moves a 64-bit immediate to memory. + ;;; + ;;; This is the moment at which we decide where the control stack starts! + ;;; Fun, right? "Allocation" is just a fancy word for picking where we want + ;;; something, then being consistent about it - like placing furniture in + ;;; your home. See below for a little more thought about why here in + ;;; particular. + ;;; + lea.qreg.qreg.disp32 rbp, control_stack_size, rdi + + ;;; ;;; Now we save some stuff onto the heap. These are the locations that ;;; will eventually be the backing stores of the Forth variables, but we ;;; don't create the word headers yet, since there's no requirement that @@ -1077,17 +1109,10 @@ _start: push.qreg rdi ;;; - ;;; Notice that, although we are about to set up rsi, and rsp came to us - ;;; already valid, rbp is still uninitialized. This is because we're about - ;;; to hand off to QUIT, which will do that for us. + ;;; We are about to set up rsi, we did rbp already, and rsp came to us + ;;; already set up. That's all that NEXT needs, so take it away! ;;; mov.qreg.qimm rsi, cold_start - - ;;; - ;;; That's all that NEXT needs, so, take it away! - ;;; - jmp.rel.dimm old_code - skip_from_here ; TODO placeholder -skip_from_here: NEXT ;;; @@ -1104,7 +1129,13 @@ cold_start: ;;; QUIT: dq DOCOL ; codeword + dq OLD_CODE + ; TODO this is more like what it should be + ; Although we initialized rbp already, we do so again because we'll want + ; that on subsequent visits to this word - it's the main thing it's for. ;dq R0, CONTROL! ; overwrite rbp to reset the control stack + ; Keep in mind that rsi is the actual "instruction pointer", and we're + ; leaving it unchanged, we just get rid of everything above it. ;dq INTERPRET ; run the repl ;dq BRANCH, QUIT - $ ; if the repl ever exits, start again @@ -1129,9 +1160,12 @@ QUIT: ;;; chunks, this size must be equal to the buffer size; within a chunk it ;;; may be less. ;;; -;;; * rsp points to the bottom of the buffer. +;;; * ~~~~rsp points to the bottom of the buffer.~~~~ +;;; TODO WRONG this is all just scribbling where it shouldn't ;;; -old_code: +OLD_CODE: + dq $ + 0x8 ; The codeword + mov.dreg.dimm rdx, 0 ; store running file size here ;sub.qreg.bimm rsp, 0xFF ; reserve stack space |