diff options
| -rw-r--r-- | quine.asm | 152 |
1 files changed, 149 insertions, 3 deletions
diff --git a/quine.asm b/quine.asm index dc7eb51..52460e4 100644 --- a/quine.asm +++ b/quine.asm @@ -2727,7 +2727,9 @@ defword HLT, 0 ; It also makes use of label stuff, further back on the stack. defword ALL_CONTENTS, 0 dq DOCOL ; codeword - dq ELF_FILE_HEADER, ELF_PROGRAM_HEADER, SELF_RAW + dq ELF_FILE_HEADER, ELF_PROGRAM_HEADER + dq OUTPUT_START_ROUTINE + dq SELF_RAW dq SET_LABEL dq EXIT @@ -2797,13 +2799,28 @@ defword ELF_PROGRAM_HEADER, 0 dq EXIT +defword OUTPUT_START_ROUTINE, 0 + dq DOCOL + dq cld + dq LIT, 9, rax, mov_reg64_imm64 + dq LIT, heap_requested_address, rdi, mov_reg64_imm64 + dq LIT, heap_size, rsi, mov_reg64_imm64 + dq LIT, 0x03, rdx, mov_reg64_imm64 + dq LIT, 0x22, r10, mov_extrareg64_imm64 + dq LIT, 0, r8, mov_extrareg64_imm64 + dq LIT, 0, r9, mov_extrareg64_imm64 + dq syscall + dq rax, rdi, mov_reg64_reg64 + dq EXIT + + ; write() the machine code by using self-reference ; TODO do this in a "real" quine way defword SELF_RAW, 0 dq DOCOL ; codeword dq DUP - dq LIT, elf_header + 0x78 ; source - dq LIT, file_size - 0x78 ; length + dq LIT, elf_header + 0xc4 ; source + dq LIT, file_size - 0xc4 ; length ; destination destination source length dq DUP, LIT, 4, ROLL, ADD, LIT, 4, UNROLL ; result destination source length @@ -2811,6 +2828,135 @@ defword SELF_RAW, 0 dq EXIT +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Assembly language, but in Forth ;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; +;;; It's all backwards and stuff. + +; We define a bunch of keywords, which evaluate to their own codeword +; addresses. +defword rax, 0 + dq DOCOL, LIT, rax, EXIT +defword rcx, 0 + dq DOCOL, LIT, rcx, EXIT +defword rdx, 0 + dq DOCOL, LIT, rdx, EXIT +defword rbx, 0 + dq DOCOL, LIT, rbx, EXIT +defword rsp, 0 + dq DOCOL, LIT, rsp, EXIT +defword rbp, 0 + dq DOCOL, LIT, rbp, EXIT +defword rsi, 0 + dq DOCOL, LIT, rsi, EXIT +defword rdi, 0 + dq DOCOL, LIT, rdi, EXIT +defword r8, 0 + dq DOCOL, LIT, r8, EXIT +defword r9, 0 + dq DOCOL, LIT, r9, EXIT +defword r10, 0 + dq DOCOL, LIT, r10, EXIT +defword r11, 0 + dq DOCOL, LIT, r11, EXIT +defword r12, 0 + dq DOCOL, LIT, r12, EXIT +defword r13, 0 + dq DOCOL, LIT, r13, EXIT +defword r14, 0 + dq DOCOL, LIT, r14, EXIT +defword r15, 0 + dq DOCOL, LIT, r15, EXIT + +; Stack in: +; register name +; Stack out: +; 3-bit encoded value for register +defword reg64, 0 + dq DOCOL + dq DUP, rax, EQ, ZBRANCH, 5*8, DROP, LIT, 0, EXIT + dq DUP, rcx, EQ, ZBRANCH, 5*8, DROP, LIT, 1, EXIT + dq DUP, rdx, EQ, ZBRANCH, 5*8, DROP, LIT, 2, EXIT + dq DUP, rbx, EQ, ZBRANCH, 5*8, DROP, LIT, 3, EXIT + dq DUP, rsp, EQ, ZBRANCH, 5*8, DROP, LIT, 4, EXIT + dq DUP, rbp, EQ, ZBRANCH, 5*8, DROP, LIT, 5, EXIT + dq DUP, rsi, EQ, ZBRANCH, 5*8, DROP, LIT, 6, EXIT + dq DUP, rdi, EQ, ZBRANCH, 5*8, DROP, LIT, 7, EXIT + dq SYS_EXIT + +; Stack in: +; register name +; Stack out: +; 3-bit encoded value for register +defword extrareg64, 0 + dq DOCOL + dq DUP, r8, EQ, ZBRANCH, 5*8, DROP, LIT, 0, EXIT + dq DUP, r9, EQ, ZBRANCH, 5*8, DROP, LIT, 1, EXIT + dq DUP, r10, EQ, ZBRANCH, 5*8, DROP, LIT, 2, EXIT + dq DUP, r11, EQ, ZBRANCH, 5*8, DROP, LIT, 3, EXIT + dq DUP, r12, EQ, ZBRANCH, 5*8, DROP, LIT, 4, EXIT + dq DUP, r13, EQ, ZBRANCH, 5*8, DROP, LIT, 5, EXIT + dq DUP, r14, EQ, ZBRANCH, 5*8, DROP, LIT, 6, EXIT + dq DUP, r15, EQ, ZBRANCH, 5*8, DROP, LIT, 7, EXIT + dq SYS_EXIT + +; Stack: +; output point +defword rex_w, 0 + dq DOCOL, LIT, 0x48, PACK8, EXIT +defword rex_wb, 0 + dq DOCOL, LIT, 0x49, PACK8, EXIT + +; Stack: +; output point +; 3-bit encoded value for register +; opcode byte +defword opcodereg, 0 + dq DOCOL, OR, PACK8, EXIT + +; Stack +; output point +; mode ("mod") field +; register/opcode field +; register/memory ("RM") field +defword modrm, 0 + dq DOCOL, SWAP, LIT, 8, MUL, OR, SWAP, LIT, 64, MUL, OR, PACK8, EXIT + +; Stack: +; output point +defword cld, 0 + dq DOCOL, LIT, 0xFC, PACK8, EXIT + +; Stack: +; output point +; immediate value +; register name +defword mov_reg64_imm64, 0 + dq DOCOL + dq ROLL3, rex_w, SWAP, reg64, LIT, 0xB8, opcodereg, SWAP, PACK64 + dq EXIT +defword mov_extrareg64_imm64, 0 + dq DOCOL + dq ROLL3, rex_wb, SWAP, extrareg64, LIT, 0xB8, opcodereg, SWAP, PACK64 + dq EXIT + +; Stack: +; output point +; source register name +; target register name +defword mov_reg64_reg64, 0 + dq DOCOL + dq ROLL3, rex_w, LIT, 0x89, PACK8, UNROLL3 + dq reg64, SWAP, reg64, SWAP, LIT, 3, UNROLL3, modrm + dq EXIT + +; Stack: +; output point +defword syscall, 0 + dq DOCOL, LIT, 0x0F, PACK8, LIT, 0x05, PACK8, EXIT + + code_size = $ - code_start file_size = $ - $$ |