From ff8ec9bcff7577ba923fe7868ea62ecceed55ee7 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Fri, 14 May 2021 11:54:42 -0700 Subject: [PATCH] insert a compile phase to emit some debug info --- linux/labels_baremetal | Bin 0 -> 51490 bytes linux/labels_baremetal.subx | 2831 +++++++++++++++++++++++++++++++++++ linux/survey_baremetal | Bin 53111 -> 47436 bytes linux/survey_baremetal.subx | 2359 +---------------------------- linux/test_apps | 4 +- linux/test_apps_emulated | 4 +- translate_subx | 17 +- translate_subx_emulated | 26 +- 8 files changed, 2921 insertions(+), 2320 deletions(-) create mode 100755 linux/labels_baremetal create mode 100644 linux/labels_baremetal.subx diff --git a/linux/labels_baremetal b/linux/labels_baremetal new file mode 100755 index 0000000000000000000000000000000000000000..f6fc997ef42337a5387d053ebd721d8e22a005af GIT binary patch literal 51490 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 1 and argv[1] == "test", then return run_tests() + # if (argc <= 1) goto interactive + 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0/disp8 1/imm32 # compare *ebp + 7e/jump-if-<= $subx-labels-main:interactive/disp8 + # if (!kernel-string-equal?(argv[1], "test")) goto interactive + # . eax = kernel-string-equal?(argv[1], "test") + # . . push args + 68/push "test"/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call kernel-string-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax == false) goto interactive + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= $subx-labels-main:interactive/disp8 + # run-tests() +#? e8/call test-emit-output-with-padding/disp32 + e8/call run-tests/disp32 + # syscall(exit, *Num-test-failures) + 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx + eb/jump $subx-labels-main:end/disp8 +$subx-labels-main:interactive: + # - otherwise convert stdin + # var labels-file/esi: (addr buffered-file) from syscall_open("labels", READ) + # . data + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x1000/imm32 # subtract from esp + # . size + 68/push 0x1000/imm32 + # . read + 68/push 0/imm32/read + # . write + 68/push 0/imm32/write + # . fd = syscall_open("labels", READ) + bb/copy-to-ebx Label-file/imm32 + b9/copy-to-ecx 0/imm32/read-mode + ba/copy-to-edx 0x180/imm32/permissions + e8/call syscall_open/disp32 + 50/push-eax + 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi + # subx-labels(Stdin, label-fd, Stdout) + # . . push args + 68/push Stdout/imm32 + 56/push-esi + 68/push Stdin/imm32 + # . . call + e8/call subx-labels/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-stream(2/stderr, Trace-stream) +#? # . . push args +#? ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # push *Trace-stream +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # syscall(exit, 0) + bb/copy-to-ebx 0/imm32 +$subx-labels-main:end: + e8/call syscall_exit/disp32 + +== data + +Label-file: + 6c/l 61/a 62/b 65/e 6c/l 73/s 00/nul + +== code + +subx-labels: # infile: (addr buffered-file), labels-file: (addr buffered-file), out: (addr buffered-file) + # pseudocode + # var labels: (stream {label-name, address} Max-labels) + # load-labels(labels-file, labels) + # var in: (stream byte Input-size) + # slurp(infile, in) + # emit-output(in, out, labels) + # + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 52/push-edx + 56/push-esi + # var labels/edx: (stream {label-name, address} Max-labels) + # (we get more rows than Max-labels advertises because row size is smaller than in survey_elf) + # . data + 2b/subtract 0/mod/indirect 5/rm32/.disp32 . . 4/r32/esp Max-labels/disp32 # subtract *Max-labels from esp + # . size + ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Max-labels/disp32 # push *Max-labels + # . read + 68/push 0/imm32/read + # . write + 68/push 0/imm32/write + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # load-labels(labels-file, labels) + # . . push args + 52/push-edx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call load-labels/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # var in/esi: (stream byte Input-size) + # . data + 2b/subtract 0/mod/indirect 5/rm32/.disp32 . . 4/r32/esp Input-size/disp32 # subtract *Input-size from esp + # . size + ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Input-size/disp32 # push *Input-size + # . read + 68/push 0/imm32/read + # . write + 68/push 0/imm32/write + 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi + # slurp(infile, in) + # . . push args + 56/push-esi + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call slurp/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # emit-output(in, out, labels) + # . . push args + 52/push-edx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) + 56/push-esi + # . . call + e8/call emit-output/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # flush(out) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) + # . . call + e8/call flush/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +$subx-labels:end: + # . reclaim locals + 03/add 0/mod/indirect 5/rm32/.disp32 . . 4/r32/esp Max-labels/disp32 # add *Max-labels to esp + 03/add 0/mod/indirect 5/rm32/.disp32 . . 4/r32/esp Input-size/disp32 # add *Input-size to esp + # . restore registers + 5e/pop-to-esi + 5a/pop-to-edx + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +load-labels: # in: (addr buffered-file), labels: (stream {label-name, address} Max-labels) + # pseudocode + # var line: (stream byte 512) + # while true + # clear-stream(line) + # read-line-buffered(in, line) + # if (line->write == 0) break # end of file + # var word-slice/ecx: (addr slice) = next-word(line) + # var dest/edi: (addr int) = get-or-insert-slice(labels, word-slice, 12 bytes/row) + # word-slice = next-word(line) + # var address/eax: int = parse-hex-int-from-slice(word-slice) + # *dest = address + # + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 56/push-esi + 57/push-edi + # var line/ecx: (stream byte 512) + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp + 68/push 0x200/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # var word-slice/edx: slice + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx +$load-labels:loop: + # clear-stream(line) + # . . push args + 51/push-ecx + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # read-line-buffered(in, line) + # . . push args + 51/push-ecx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call read-line-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # dump line {{{ +#? # . write(2/stderr, "LL: ") +#? # . . push args +#? 68/push "LL: "/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # write-stream(2/stderr, line) +#? # . . push args +#? 51/push-ecx +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . rewind-stream(line) +#? # . . push args +#? 51/push-ecx +#? # . . call +#? e8/call rewind-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # }}} + # if (line->write == 0) break + 81 7/subop/compare 0/mod/indirect 1/rm32/ecx . . . . . 0/imm32 # compare *ecx + 0f 84/jump-if-= $load-labels:end/disp32 + # next-word(line, word-slice) + # . . push args + 52/push-edx + 51/push-ecx + # . . call + e8/call next-word/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # dump word-slice {{{ +#? # . write(2/stderr, "w: ") +#? # . . push args +#? 68/push "w: "/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-slice-buffered(Stderr, word-slice) +#? # . . push args +#? 52/push-edx +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call write-slice-buffered/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . flush(Stderr) +#? # . . push args +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call flush/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # }}} + # var dest/edi: (addr int) = get-or-insert-slice(labels, word-slice, 12 bytes/row, Heap) + # . eax = get-or-insert-slice(labels, word-slice, 12 bytes/row, Heap) + # . . push args + 68/push Heap/imm32 + 68/push 0xc/imm32/row-size + 52/push-edx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call get-or-insert-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # . edi = eax + 89/copy 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # copy eax to edi + # next-word(line, word-slice) + # . . push args + 52/push-edx + 51/push-ecx + # . . call + e8/call next-word/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # var address/esi: int = parse-hex-int-from-slice(word-slice) + # . . push args + 52/push-edx + # . . call + e8/call parse-hex-int-from-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . esi = eax + 89/copy 3/mod/direct 6/rm32/esi . . . 0/r32/eax . . # copy eax to esi + # *dest = address + 89/copy 0/mod/indirect 7/rm32/edi . . 6/r32/esi . . # copy esi to *edi + # + e9/jump $load-labels:loop/disp32 +$load-labels:end: + # . reclaim locals + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x214/imm32 # add to esp + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +# global scratch space for emit-output +== data + +emit-output:datum: # slice + 0/imm32/start + 0/imm32/end + +== code + +emit-output: # in: (addr stream byte), out: (addr buffered-file), labels: (addr stream {(handle array byte), address}) + # pseudocode: + # var address-of-next-instruction = 0x7c00 + # var line: (stream byte 512) + # line-loop: + # while true + # clear-stream(line) + # read-line(in, line) + # if (line->write == 0) break # end of file + # address-of-next-instruction += num-bytes(line) + # var far-jump-or-call? = far-jump-or-call?(line) + # rewind-stream(line) + # while true + # var word-slice = next-word(line) + # if slice-empty?(word-slice) # end of line + # break + # if slice-starts-with?(word-slice, "#") # comment + # break + # if label?(word-slice) # no need for label declarations anymore + # goto line-loop # don't insert empty lines + # if slice-equal?(word-slice, "==") # no need for segment header lines + # word-slice = next-word(line) # skip segment name + # word-slice = next-word(line) + # if !slice-empty?(word-slice) + # new-address = parse-hex-int-from-slice(word-slice) + # write-buffered(out, "# " address-of-next-instruction "\n") + # while address-of-next-instruction < new-address + # write-buffered("00") + # ++address-of-next-instruction + # write-buffered(out, "# " address-of-next-instruction "\n") + # goto line-loop # don't insert empty lines + # if length(word-slice) == 2 + # write-slice-buffered(out, word-slice) + # write-buffered(out, " ") + # continue + # var datum: (addr slice) = next-token-from-slice(word-slice->start, word-slice->end, "/") + # var address: (addr int) = get-slice(labels, datum) + # if has-metadata?(word-slice, "imm8") + # emit(out, *address, 1) + # else if has-metadata?(word-slice, "imm16") + # emit(out, *address, 2) + # else if has-metadata?(word-slice, "imm32") + # emit(out, *address, 4) + # else if has-metadata?(word-slice, "disp8") + # value = *address - address-of-next-instruction + # emit(out, value, 1) + # else if has-metadata?(word-slice, "disp32") + # if far-jump-or-call? + # value = *address - address-of-next-instruction + # else + # value = *address + # emit(out, value, 4) + # else + # abort + # write-buffered(out, "\n") + # + # registers: + # line: ecx + # word-slice: edx + # address-of-next-instruction: ebx + # far-jump-or-call?: edi + # address: esi (inner loop only) + # temporaries: eax, esi (outer loop) + # + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 53/push-ebx + 56/push-esi + 57/push-edi + # var line/ecx: (stream byte 512) + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp + 68/push 0x200/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # var word-slice/edx: slice + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # var address-of-next-instruction/ebx = 0x7c00 + bb/copy-to-ebx 0x7c00/imm32 +$emit-output:line-loop: + # clear-stream(line) + # . . push args + 51/push-ecx + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # read-line(in, line) + # . . push args + 51/push-ecx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call read-line/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # dump line {{{ +#? # . write(2/stderr, "LL: ") +#? # . . push args +#? 68/push "LL: "/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # write-stream(2/stderr, line) +#? # . . push args +#? 51/push-ecx +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . rewind-stream(line) +#? # . . push args +#? 51/push-ecx +#? # . . call +#? e8/call rewind-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # }}} +$emit-output:check-for-end-of-input: + # if (line->write == 0) break + 81 7/subop/compare 0/mod/indirect 1/rm32/ecx . . . . . 0/imm32 # compare *ecx + 0f 84/jump-if-= $emit-output:end/disp32 + # address-of-next-instruction += num-bytes(line) + # . eax = num-bytes(line) + # . . push args + 51/push-ecx + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . ebx += eax + 01/add 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # add eax to ebx + # var far-jump-or-call?/edi: boolean = far-jump-or-call?(line) + # . . push args + 51/push-ecx + # . . call + e8/call far-jump-or-call?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # rewind-stream(line) + # . . push args + 51/push-ecx + # . . call + e8/call rewind-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +$emit-output:word-loop: + # next-word(line, word-slice) + # . . push args + 52/push-edx + 51/push-ecx + # . . call + e8/call next-word/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # dump word-slice {{{ +#? # . write(2/stderr, "w: ") +#? # . . push args +#? 68/push "w: "/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-slice-buffered(Stderr, word-slice) +#? # . . push args +#? 52/push-edx +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call write-slice-buffered/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . flush(Stderr) +#? # . . push args +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call flush/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # }}} +$emit-output:check-for-end-of-line: + # if (slice-empty?(word-slice)) break + # . eax = slice-empty?(word-slice) + # . . push args + 52/push-edx + # . . call + e8/call slice-empty?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . if (eax != 0) break + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $emit-output:next-line/disp32 +$emit-output:check-for-comment: + # if (slice-starts-with?(word-slice, "#")) break + # . start/esi = word-slice->start + 8b/copy 0/mod/indirect 2/rm32/edx . . . 6/r32/esi . . # copy *edx to esi + # . c/eax = *start + 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL + # . if (eax == '#') break + 3d/compare-eax-and 0x23/imm32/hash + 0f 84/jump-if-= $emit-output:next-line/disp32 +$emit-output:check-for-label: + # if label?(word-slice) break + # . eax = label?(word-slice) + # . . push args + 52/push-edx + # . . call + e8/call label?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $emit-output:line-loop/disp32 +$emit-output:check-for-segment-header: + # if !slice-equal?(word-slice, "==") goto next check + # . eax = slice-equal?(word-slice, "==") + # . . push args + 68/push "=="/imm32 + 52/push-edx + # . . call + e8/call slice-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false + 0f 84/jump-if-= $emit-output:2-character/disp32 + # skip segment name + # . next-word(line, word-slice) + # . . push args + 52/push-edx + 51/push-ecx + # . . call + e8/call next-word/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # compute segment address if it exists + # . next-word(line, word-slice) + # . . push args + 52/push-edx + 51/push-ecx + # . . call + e8/call next-word/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if slice-empty?(word-slice) goto padding-done + # . . push args + 52/push-edx + # . . call + e8/call slice-empty?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . . + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $emit-output:padding-done/disp32 + # . var new-address/eax: int = parse-hex-int-from-slice(word-slice) + # . . push args + 52/push-edx + # . . call + e8/call parse-hex-int-from-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # write-buffered(out, "# " address-of-next-instruction "\n") + # . write-buffered(out, "# ") + # . . push args + 68/push "# "/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write-int32-hex-buffered(out, address-of-next-instruction) + # . . push args + 53/push-ebx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-int32-hex-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write-buffered(out, "\n") + # . . push args + 68/push Newline/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +$emit-output:padding-loop: + # if (address-of-next-instruction >= new-address) goto padding-loop-done + 39/compare 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # compare ebx with eax + 73/jump-if-addr>= $emit-output:padding-loop-done/disp8 + # if (address-of-next-instruction % 8 == 0) write-buffered("\n") + 53/push-ebx + 81 4/subop/and 3/mod/direct 3/rm32/ebx . . . . . 7/imm32 # bitwise and of ebx + 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32 # compare ebx + 5b/pop-to-ebx + 75/jump-if-!= $emit-output:padding-core/disp8 + # . write-buffered(out, "\n") + # . . push args + 68/push Newline/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +$emit-output:padding-core: + # write-buffered("00") + # . . push args + 68/push "00 "/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # ++address-of-next-instruction + 43/increment-ebx + # loop + eb/jump $emit-output:padding-loop/disp8 +$emit-output:padding-loop-done: + # . write-buffered(out, "\n") + # . . push args + 68/push Newline/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +$emit-output:padding-done: + # write-buffered(out, "# " address-of-next-instruction "\n") + # . write-buffered(out, "# ") + # . . push args + 68/push "# "/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write-int32-hex-buffered(out, address-of-next-instruction) + # . . push args + 53/push-ebx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-int32-hex-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write-buffered(out, "\n") + # . . push args + 68/push Newline/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # + e9/jump $emit-output:line-loop/disp32 +$emit-output:2-character: + # if (size(word-slice) != 2) goto next check + # . eax = size(word-slice) + 8b/copy 1/mod/*+disp8 2/rm32/edx . . . 0/r32/eax 4/disp8 . # copy *(edx+4) to eax + 2b/subtract 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # subtract *edx from eax + # . if (eax != 2) goto next check + 3d/compare-eax-and 2/imm32 + 75/jump-if-!= $emit-output:check-metadata/disp8 + # write-slice-buffered(out, word-slice) + # . . push args + 52/push-edx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-slice-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # write-buffered(out, " ") + # . . push args + 68/push Space/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # continue + e9/jump $emit-output:word-loop/disp32 +$emit-output:check-metadata: + # - if we get here, 'word-slice' must be a label to be looked up + # datum = next-token-from-slice(word-slice->start, word-slice->end, "/") + # . . push args + 68/push emit-output:datum/imm32 + 68/push 0x2f/imm32/slash + ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) + ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx + # . . call + e8/call next-token-from-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp +#? # dump datum {{{ +#? # . write(2/stderr, "datum: ") +#? # . . push args +#? 68/push "datum: "/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-slice-buffered(Stderr, datum) +#? # . . push args +#? 68/push emit-output:datum/imm32 +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call write-slice-buffered/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . flush(Stderr) +#? # . . push args +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call flush/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # }}} + # address/esi: (addr int) = get-slice(labels, datum, row-size=12, "label table") + # . eax = get-slice(labels, datum, row-size=24, "label table") + # . . push args + 68/push "label table"/imm32 + 68/push 0xc/imm32/row-size + 68/push emit-output:datum/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) + # . . call + e8/call get-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # . esi = eax + 89/copy 3/mod/direct 6/rm32/esi . . . 0/r32/eax . . # copy eax to esi +$emit-output:check-imm8: + # if (!has-metadata?(word-slice, "imm8")) goto next check + # . eax = has-metadata?(edx, "imm8") + # . . push args + 68/push "imm8"/imm32 + 52/push-edx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax != false) abort + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= $emit-output:check-imm16/disp8 +$emit-output:emit-imm8: + # emit-hex(out, *address, 1) + # . . push args + 68/push 1/imm32 + ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call emit-hex/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # continue + e9/jump $emit-output:word-loop/disp32 +$emit-output:check-imm16: + # if (!has-metadata?(word-slice, "imm16")) goto next check + # . eax = has-metadata?(edx, "imm16") + # . . push args + 68/push "imm16"/imm32 + 52/push-edx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= $emit-output:check-imm32/disp8 +#? # dump *address {{{ +#? # . write(2/stderr, "*address: ") +#? # . . push args +#? 68/push "*address: "/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-int32-hex-buffered(Stderr, *address) +#? # . . push args +#? ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call write-int32-hex-buffered/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . flush(Stderr) +#? # . . push args +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call flush/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # }}} +$emit-output:emit-imm16: + # emit-hex(out, *address, 2) + # . . push args + 68/push 2/imm32 + ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call emit-hex/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # TODO: ensure that the higher 2 bytes are zero + # continue + e9/jump $emit-output:word-loop/disp32 +$emit-output:check-imm32: + # if (!has-metadata?(word-slice, "imm32")) goto next check + # . eax = has-metadata?(edx, "imm32") + # . . push args + 68/push "imm32"/imm32 + 52/push-edx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= $emit-output:check-disp8/disp8 +#? # dump *address {{{ +#? # . write(2/stderr, "*address: ") +#? # . . push args +#? 68/push "*address: "/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-int32-hex-buffered(Stderr, *address) +#? # . . push args +#? ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call write-int32-hex-buffered/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . flush(Stderr) +#? # . . push args +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call flush/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # }}} +$emit-output:emit-imm32: + # emit-hex(out, *address, 4) + # . . push args + 68/push 4/imm32 + ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call emit-hex/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # continue + e9/jump $emit-output:word-loop/disp32 +$emit-output:check-disp8: + # if (!has-metadata?(word-slice, "disp8")) goto next check + # . eax = has-metadata?(edx, "disp8") + # . . push args + 68/push "disp8"/imm32 + 52/push-edx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= $emit-output:check-disp16/disp8 +$emit-output:emit-disp8: + # emit-hex(out, *address - address-of-next-instruction, 1) + # . . push args + 68/push 1/imm32 + 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax + 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax + 50/push-eax + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call emit-hex/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # continue + e9/jump $emit-output:word-loop/disp32 +$emit-output:check-disp16: + # if (!has-metadata?(word-slice, "disp16")) goto next check + # . eax = has-metadata?(edx, "disp16") + # . . push args + 68/push "disp16"/imm32 + 52/push-edx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax == false) goto next check + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= $emit-output:check-disp32/disp8 +$emit-output:emit-disp16: + # emit-hex(out, *address - address-of-next-instruction, 2) + # . . push args + 68/push 2/imm32 + 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax + 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax + 50/push-eax + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call emit-hex/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # continue + e9/jump $emit-output:word-loop/disp32 +$emit-output:check-disp32: + # if (!has-metadata?(word-slice, "disp32")) abort + # . eax = has-metadata?(edx, "disp32") + # . . push args + 68/push "disp32"/imm32 + 52/push-edx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax == false) abort + 3d/compare-eax-and 0/imm32/false + 0f 84/jump-if-= $emit-output:abort/disp32 +$emit-output:emit-disp32: + # var value/eax = *address + 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax + # if (far-jump-or-call?) value -= address-of-next-instruction + 81 7/subop/compare 3/mod/direct 7/rm32/edi . . . . . 0/imm32/false # compare edi + 74/jump-if-= $emit-output:really-emit-disp32/disp8 + 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax +$emit-output:really-emit-disp32: + # emit-hex(out, value, 4) + # . . push args + 68/push 4/imm32 + 50/push-eax + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call emit-hex/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # continue + e9/jump $emit-output:word-loop/disp32 +$emit-output:next-line: + # write-buffered(out, "\n") + # . . push args + 68/push Newline/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # loop + e9/jump $emit-output:line-loop/disp32 +$emit-output:end: + # . reclaim locals + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x214/imm32 # add to esp + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 5b/pop-to-ebx + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +$emit-output:abort: + # print(stderr, "missing metadata in " word-slice) + # . _write(2/stderr, "missing metadata in word ") + # . . push args + 68/push "emit-output: missing metadata in "/imm32 + 68/push 2/imm32/stderr + # . . call + e8/call _write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write-slice-buffered(Stderr, word-slice) + # . . push args + 52/push-edx + 68/push Stderr/imm32 + # . . call + e8/call write-slice-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . flush(Stderr) + # . . push args + 68/push Stderr/imm32 + # . . call + e8/call flush/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . syscall(exit, 1) + bb/copy-to-ebx 1/imm32 + e8/call syscall_exit/disp32 + # never gets here + +test-emit-output-non-far-control-flow: + # labels turn into absolute addresses if opcodes are not far jumps or calls + # + # input: + # in: + # == code + # ab cd ef gh + # ij x/disp32 + # == data + # 00 + # 34 + # labels: + # - 'x': 0x11223344 + # + # output: + # ab cd ef gh + # ij 44 33 22 11 + # 00 + # 34 + # + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream($_test-output-buffered-file->buffer) + # . . push args + 68/push $_test-output-buffered-file->buffer/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . var labels/edx: (stream byte 8*24) + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xc0/imm32 # subtract from esp + 68/push 0xc0/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # . var h/ebx: (handle array byte) + 68/push 0/imm32 + 68/push 0/imm32 + 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx + # initialize input + # . write(_test-input-stream, "== code\n") + # . . push args + 68/push "== code\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "ab cd ef gh\n") + # . . push args + 68/push "ab cd ef gh\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "ij x/disp32\n") + # . . push args + 68/push "ij x/disp32\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "== data\n") + # . . push args + 68/push "== data\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "00\n") + # . . push args + 68/push "00\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "34\n") + # . . push args + 68/push "34\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . stream-add2(labels, "x", 0x11223344) + 68/push 0x11223344/imm32/label-address + # . . push handle for "x" + 53/push-ebx + 68/push "x"/imm32 + 68/push Heap/imm32 + e8/call copy-array/disp32 + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + ff 6/subop/push 1/mod/*+disp8 3/rm32/ebx . . . . 4/disp8 . # push *(ebx+4) + ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx + # . . push labels + 52/push-edx + # . . call + e8/call stream-add2/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # component under test + # . emit-output(_test-input-stream, _test-output-buffered-file, labels) + # . . push args + 52/push-edx + 68/push _test-output-buffered-file/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call emit-output/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # checks + # . flush(_test-output-buffered-file) + # . . push args + 68/push _test-output-buffered-file/imm32 + # . . call + e8/call flush/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # dump output {{{ +#? # . write(2/stderr, "result: ^") +#? # . . push args +#? 68/push "result: ^"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-stream(2/stderr, _test-output-stream) +#? # . . push args +#? 68/push _test-output-stream/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . rewind-stream(_test-output-stream) +#? # . . push args +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call rewind-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # }}} + # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg) + # . . push args + 68/push "F - test-emit-output-non-far-control-flow/0"/imm32 + 68/push "# 0x00007c00"/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "ab cd ef gh ", msg) + # . . push args + 68/push "F - test-emit-output-non-far-control-flow/1"/imm32 + 68/push "ab cd ef gh "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "ij 44 33 22 11 ", msg) + # . . push args + 68/push "F - test-emit-output-non-far-control-flow/2"/imm32 + 68/push "ij 44 33 22 11 "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c09", msg) + # . . push args + 68/push "F - test-emit-output-non-far-control-flow/3"/imm32 + 68/push "# 0x00007c09"/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "00 ", msg) + # . . push args + 68/push "F - test-emit-output-non-far-control-flow/3"/imm32 + 68/push "00 "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "34 ", msg) + # . . push args + 68/push "F - test-emit-output-non-far-control-flow/4"/imm32 + 68/push "34 "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-emit-output-with-padding: + # labels turn into absolute addresses if opcodes are not far jumps or calls + # + # input: + # in: + # == code + # ab cd ef gh + # == data 0x7c10 + # 34 + # + # output: + # ab cd ef gh + # # 0x7c04 + # 00 00 00 00 + # 00 00 00 00 00 00 00 00 + # # 0x7c10 + # 34 + # + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream($_test-output-buffered-file->buffer) + # . . push args + 68/push $_test-output-buffered-file->buffer/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . var labels/edx: (stream byte 8*24) + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xc0/imm32 # subtract from esp + 68/push 0xc0/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # . var h/ebx: (handle array byte) + 68/push 0/imm32 + 68/push 0/imm32 + 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx + # initialize input + # . write(_test-input-stream, "== code\n") + # . . push args + 68/push "== code\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "ab cd ef gh\n") + # . . push args + 68/push "ab cd ef gh\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "== data 0x7c10\n") + # . . push args + 68/push "== data 0x7c10\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "34\n") + # . . push args + 68/push "34\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # component under test + # . emit-output(_test-input-stream, _test-output-buffered-file, labels) + # . . push args + 52/push-edx + 68/push _test-output-buffered-file/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call emit-output/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # checks + # . flush(_test-output-buffered-file) + # . . push args + 68/push _test-output-buffered-file/imm32 + # . . call + e8/call flush/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # dump output {{{ +#? # . write(2/stderr, "result: ^") +#? # . . push args +#? 68/push "result: ^"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-stream(2/stderr, _test-output-stream) +#? # . . push args +#? 68/push _test-output-stream/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . rewind-stream(_test-output-stream) +#? # . . push args +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call rewind-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # }}} + # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg) + # . . push args + 68/push "F - test-emit-output-with-padding/0"/imm32 + 68/push "# 0x00007c00"/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "ab cd ef gh ", msg) + # . . push args + 68/push "F - test-emit-output-with-padding/1"/imm32 + 68/push "ab cd ef gh "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c04", msg) + # . . push args + 68/push "F - test-emit-output-with-padding/0"/imm32 + 68/push "# 0x00007c04"/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "00 00 00 00 ", msg) + # . . push args + 68/push "F - test-emit-output-with-padding/2"/imm32 + 68/push "00 00 00 00 "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "00 00 00 00 ", msg) + # . . push args + 68/push "F - test-emit-output-with-padding/3"/imm32 + 68/push "00 00 00 00 00 00 00 00 "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c10", msg) + # . . push args + 68/push "F - test-emit-output-with-padding/0"/imm32 + 68/push "# 0x00007c10"/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "34 ", msg) + # . . push args + 68/push "F - test-emit-output-with-padding/4"/imm32 + 68/push "34 "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-emit-output-code-label: + # labels turn into PC-relative addresses if opcodes are far jumps or calls + # + # input: + # in: + # == code + # ab cd + # ef gh + # e8 l1/disp32 + # labels: + # - 'l1': 0x7c10 + # + # output: + # ab cd + # ef gh + # e8 07 00 00 00 # 0x7c10 - 0x7c09 = 7 + # + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream($_test-output-buffered-file->buffer) + # . . push args + 68/push $_test-output-buffered-file->buffer/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . var labels/edx: (stream byte 8*24) + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xc0/imm32 # subtract from esp + 68/push 0xc0/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # . var h/ebx: (handle array byte) + 68/push 0/imm32 + 68/push 0/imm32 + 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx + # initialize input + # . write(_test-input-stream, "== code\n") + # . . push args + 68/push "== code\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "ab cd\n") + # . . push args + 68/push "ab cd\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "ef gh\n") + # . . push args + 68/push "ef gh\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "e8 l1/disp32\n") + # . . push args + 68/push "e8 l1/disp32\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . stream-add2(labels, "l1", 0x7c10) + 68/push 0x7c10/imm32/label-address + # . . push handle for "l1" + 53/push-ebx + 68/push "l1"/imm32 + 68/push Heap/imm32 + e8/call copy-array/disp32 + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + ff 6/subop/push 1/mod/*+disp8 3/rm32/ebx . . . . 4/disp8 . # push *(ebx+4) + ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx + # . . push labels + 52/push-edx + # . . call + e8/call stream-add2/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # component under test + # . emit-output(_test-input-stream, _test-output-buffered-file, labels) + # . . push args + 52/push-edx + 68/push _test-output-buffered-file/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call emit-output/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # checks + # . flush(_test-output-buffered-file) + # . . push args + 68/push _test-output-buffered-file/imm32 + # . . call + e8/call flush/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # dump output {{{ +#? # . write(2/stderr, "result: ^") +#? # . . push args +#? 68/push "result: ^"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-stream(2/stderr, _test-output-stream) +#? # . . push args +#? 68/push _test-output-stream/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . rewind-stream(_test-output-stream) +#? # . . push args +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call rewind-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # }}} + # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg) + # . . push args + 68/push "F - test-emit-output-code-label/0"/imm32 + 68/push "# 0x00007c00"/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "ab cd ", msg) + # . . push args + 68/push "F - test-emit-output-code-label/1"/imm32 + 68/push "ab cd "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "ef gh ", msg) + # . . push args + 68/push "F - test-emit-output-code-label/2"/imm32 + 68/push "ef gh "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "e8 07 00 00 00 ", msg) + # . . push args + 68/push "F - test-emit-output-code-label/3"/imm32 + 68/push "e8 07 00 00 00 "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-emit-output-code-label-absolute: + # labels can also convert to absolute addresses + # + # input: + # in: + # == code + # ab cd + # ef gh + # ij l1/imm32 + # labels: + # - 'l1': 0x1056 + # + # output: + # ab cd + # ef gh + # ij 56 10 00 00 + # + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream($_test-output-buffered-file->buffer) + # . . push args + 68/push $_test-output-buffered-file->buffer/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . var labels/edx: (stream byte 8*24) + 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xc0/imm32 # subtract from esp + 68/push 0xc0/imm32/size + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # . var h/ebx: (handle array byte) + 68/push 0/imm32 + 68/push 0/imm32 + 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx + # initialize input + # . write(_test-input-stream, "== code 0x1000\n") + # . . push args + 68/push "== code\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "ab cd\n") + # . . push args + 68/push "ab cd\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "ef gh\n") + # . . push args + 68/push "ef gh\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . write(_test-input-stream, "ij l1/imm32\n") + # . . push args + 68/push "ij l1/imm32\n"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . stream-add2(labels, "l1", 0x1056) + 68/push 0x1056/imm32/label-address + # . . push handle for "l1" + 53/push-ebx + 68/push "l1"/imm32 + 68/push Heap/imm32 + e8/call copy-array/disp32 + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + ff 6/subop/push 1/mod/*+disp8 3/rm32/ebx . . . . 4/disp8 . # push *(ebx+4) + ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx + # . . push labels + 52/push-edx + # . . call + e8/call stream-add2/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # component under test + # . emit-output(_test-input-stream, _test-output-buffered-file, labels) + # . . push args + 52/push-edx + 68/push _test-output-buffered-file/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call emit-output/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # checks + # . flush(_test-output-buffered-file) + # . . push args + 68/push _test-output-buffered-file/imm32 + # . . call + e8/call flush/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # dump output {{{ +#? # . write(2/stderr, "result: ^") +#? # . . push args +#? 68/push "result: ^"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-stream(2/stderr, _test-output-stream) +#? # . . push args +#? 68/push _test-output-stream/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . rewind-stream(_test-output-stream) +#? # . . push args +#? 68/push _test-output-stream/imm32 +#? # . . call +#? e8/call rewind-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # }}} + # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg) + # . . push args + 68/push "F - test-emit-output-code-label-absolute/0"/imm32 + 68/push "# 0x00007c00"/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "ab cd ", msg) + # . . push args + 68/push "F - test-emit-output-code-label-absolute/1"/imm32 + 68/push "ab cd "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "ef gh ", msg) + # . . push args + 68/push "F - test-emit-output-code-label-absolute/2"/imm32 + 68/push "ef gh "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . check-next-stream-line-equal(_test-output-stream, "ij f9 ff ff ff ", msg) + # . . push args + 68/push "F - test-emit-output-code-label-absolute/3"/imm32 + 68/push "ij 56 10 00 00 "/imm32 + 68/push _test-output-stream/imm32 + # . . call + e8/call check-next-stream-line-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +# reads line to make some checks +# don't assume the read state of line after calling this function +far-jump-or-call?: # line: (addr stream byte) -> result/edi: boolean + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 53/push-ebx + # ecx = line + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx + # var word-slice/edx: slice + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + # var datum-slice/ebx: slice + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx + # result = false + bf/copy-to-edi 0/imm32/false +$far-jump-or-call?:check-first-word: + # next-word(line, word-slice) + # . . push args + 52/push-edx + 51/push-ecx + # . . call + e8/call next-word/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (slice-empty?(word-slice)) return false + # . eax = slice-empty?(word-slice) + # . . push args + 52/push-edx + # . . call + e8/call slice-empty?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . if (eax != 0) return + 3d/compare-eax-and 0/imm32/false + 0f 85/jump-if-!= $far-jump-or-call?:end/disp32 + # datum = next-token-from-slice(word-slice->start, word-slice->end, "/") + # . . push args + 53/push-ebx + 68/push 0x2f/imm32/slash + ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) + ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx + # . . call + e8/call next-token-from-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # if (datum-slice == "e8") return true + # . eax = slice-equal?(datum-slice, "e8") + # . . push args + 68/push "e8"/imm32 + 53/push-ebx + # . . call + e8/call slice-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax != false) return true + 3d/compare-eax-and 0/imm32/false + 75/jump-if-!= $far-jump-or-call?:return-true/disp8 + # if (datum-slice == "e9") return true + # . eax = slice-equal?(datum-slice, "e9") + # . . push args + 68/push "e9"/imm32 + 53/push-ebx + # . . call + e8/call slice-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax != false) return true + 3d/compare-eax-and 0/imm32/false + 75/jump-if-!= $far-jump-or-call?:return-true/disp8 + # if (datum-slice != "0f") return false + # . eax = slice-equal?(datum-slice, "0f") + # . . push args + 68/push "0f"/imm32 + 53/push-ebx + # . . call + e8/call slice-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax == false) return + 3d/compare-eax-and 0/imm32/false + 74/jump-if-= $far-jump-or-call?:end/disp8 +$far-jump-or-call?:check-second-word: + # next-word(line, word-slice) + # . . push args + 52/push-edx + 51/push-ecx + # . . call + e8/call next-word/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # if (slice-empty?(word-slice)) return false + # . eax = slice-empty?(word-slice) + # . . push args + 52/push-edx + # . . call + e8/call slice-empty?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . if (eax != 0) return + 3d/compare-eax-and 0/imm32/false + 75/jump-if-!= $far-jump-or-call?:end/disp8 + # if datum of word-slice does not start with "8", return false + # . start/eax = word-slice->start + 8b/copy 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # copy *edx to eax + # . c/eax = *start + 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL + 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax + # . if (eax != '8') return + 3d/compare-eax-and 0x38/imm32/8 + 75/jump-if-!= $far-jump-or-call?:end/disp8 + # otherwise return true +$far-jump-or-call?:return-true: + bf/copy-to-edi 1/imm32/true +$far-jump-or-call?:end: + # . reclaim locals + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # . restore registers + 5b/pop-to-ebx + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +# - some helpers for tests + +stream-add2: # in: (addr stream byte), key: handle, val: int + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 50/push-eax + 51/push-ecx + 52/push-edx + 56/push-esi + # esi = in + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi + # curr/eax = &in->data[in->write] + # . eax = in->write + 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax + # . eax = esi+eax+12 + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 0/r32/eax 0xc/disp8 . # copy esi+eax+12 to eax + # max/edx = &in->data[in->size] + # . edx = in->size + 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 8/disp8 . # copy *(esi+8) to edx + # . edx = esi+edx+12 + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 2/index/edx . 2/r32/edx 0xc/disp8 . # copy esi+edx+12 to edx + # if (curr >= max) abort + 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax with edx + 73/jump-if-addr>= $stream-add2:abort/disp8 + # *curr = key->alloc-id + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx + 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax + # curr += 4 + 05/add-to-eax 4/imm32 + # if (curr >= max) abort + 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax with edx + 73/jump-if-addr>= $stream-add2:abort/disp8 + # *curr = key->payload + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 0x10/disp8 . # copy *(ebp+16) to ecx + 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax + # curr += 4 + 05/add-to-eax 4/imm32 + # if (curr >= max) abort + 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax with edx + 73/jump-if-addr>= $stream-add2:abort/disp8 + # *curr = val + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 0x14/disp8 . # copy *(ebp+20) to ecx + 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax + # in->write += 0xc + 81 0/subop/add 0/mod/indirect 6/rm32/esi . . . . . 0xc/imm32 # add to *esi +$stream-add2:end: + # . restore registers + 5e/pop-to-esi + 5a/pop-to-edx + 59/pop-to-ecx + 58/pop-to-eax + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +$stream-add2:abort: + # . _write(2/stderr, error) + # . . push args + 68/push "overflow in stream-add2\n"/imm32 + 68/push 2/imm32/stderr + # . . call + e8/call _write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . syscall(exit, 1) + bb/copy-to-ebx 1/imm32 + e8/call syscall_exit/disp32 + # never gets here + +# some variants of 'trace' that take multiple arguments in different combinations of types: +# n: int +# c: character [4-bytes, will eventually be UTF-8] +# s: (addr array byte) +# l: (addr slice) +# one gotcha: 's5' must not be empty + +trace-slsns: # s1: (addr array byte), l2: (addr slice), s3: (addr array byte), n4: int, s5: (addr array byte) + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # write(*Trace-stream, s1) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # push *Trace-stream + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # write-slice(*Trace-stream, l2) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # push *Trace-stream + # . . call + e8/call write-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # write(*Trace-stream, s3) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) + ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # push *Trace-stream + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # write-int32-hex(*Trace-stream, n4) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 . # push *(ebp+20) + ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # push *Trace-stream + # . . call + e8/call write-int32-hex/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # trace(s5) # implicitly adds a newline and finalizes the trace line + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x18/disp8 . # push *(ebp+24) + # . . call + e8/call trace/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +$trace-slsns:end: + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-trace-slsns: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . *Trace-stream->write = 0 + 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/eax Trace-stream/disp32 # copy *Trace-stream to eax + c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0/imm32 # clear *eax + # (eax..ecx) = "b" + b8/copy-to-eax "b"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/eax 1/index/ecx . 1/r32/ecx 4/disp8 . # copy eax+ecx+4 to ecx + 05/add-to-eax 4/imm32 + # var b/ebx: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx + # trace-slsls("A" b "c " 3 " e") + # . . push args + 68/push " e"/imm32 + 68/push 3/imm32 + 68/push "c "/imm32 + 53/push-ebx + 68/push "A"/imm32 + # . . call + e8/call trace-slsns/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp +#? # dump *Trace-stream {{{ +#? # . write(2/stderr, "^") +#? # . . push args +#? 68/push "^"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write-stream(2/stderr, *Trace-stream) +#? # . . push args +#? ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Trace-stream/disp32 # push *Trace-stream +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # }}} + # check-trace-contains("Abc 0x00000003 e") + # . . push args + 68/push "F - test-trace-slsls"/imm32 + 68/push "Abc 0x00000003 e"/imm32 + # . . call + e8/call check-trace-contains/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +num-bytes: # line: (addr stream byte) -> eax: int + # pseudocode: + # result = 0 + # while true + # var word-slice = next-word(line) + # if slice-empty?(word-slice) # end of line + # break + # if slice-starts-with?(word-slice, "#") # comment + # break + # if label?(word-slice) # no need for label declarations anymore + # break + # if slice-equal?(word-slice, "==") + # break # no need for segment header lines + # result += compute-width(word-slice) + # return result + # + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 51/push-ecx + 52/push-edx + 53/push-ebx + # var result/eax = 0 + 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + # var word-slice/ecx: slice + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +#? # dump line {{{ +#? # . write(2/stderr, "LL: ") +#? # . . push args +#? 68/push "LL: "/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # write-stream(2/stderr, line) +#? # . . push args +#? ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # }}} + # . rewind-stream(line) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call rewind-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +$num-bytes:loop: + # next-word(line, word-slice) + # . . push args + 51/push-ecx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call next-word/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # dump word-slice {{{ +#? # . write(2/stderr, "AA: ") +#? # . . push args +#? 68/push "AA: "/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . clear-stream($Stderr->buffer) +#? # . . push args +#? 68/push $Stderr->buffer/imm32 +#? # . . call +#? e8/call clear-stream/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # . write-slice-buffered(Stderr, word-slice) +#? # . . push args +#? 51/push-ecx +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call write-slice-buffered/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # . flush(Stderr) +#? # . . push args +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call flush/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +#? # . write(2/stderr, "$\n") +#? # . . push args +#? 68/push "$\n"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +#? # }}} +$num-bytes:check0: + # if (slice-empty?(word-slice)) break + # . save result + 50/push-eax + # . eax = slice-empty?(word-slice) + # . . push args + 51/push-ecx + # . . call + e8/call slice-empty?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false + # . restore result now that ZF is set + 58/pop-to-eax + 75/jump-if-!= $num-bytes:end/disp8 +$num-bytes:check-for-comment: + # if (slice-starts-with?(word-slice, "#")) break + # . start/edx = word-slice->start + 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx + # . c/ebx = *start + 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx + 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 3/r32/BL . . # copy byte at *edx to BL + # . if (ebx == '#') break + 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x23/imm32/hash # compare ebx + 74/jump-if-= $num-bytes:end/disp8 +$num-bytes:check-for-label: + # if (slice-ends-with?(word-slice, ":")) break + # . end/edx = word-slice->end + 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx + # . c/ebx = *(end-1) + 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx + 8a/copy-byte 1/mod/*+disp8 2/rm32/edx . . . 3/r32/BL -1/disp8 . # copy byte at *ecx to BL + # . if (ebx == ':') break + 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x3a/imm32/colon # compare ebx + 74/jump-if-= $num-bytes:end/disp8 +$num-bytes:check-for-segment-header: + # if (slice-equal?(word-slice, "==")) break + # . push result + 50/push-eax + # . eax = slice-equal?(word-slice, "==") + # . . push args + 68/push "=="/imm32 + 51/push-ecx + # . . call + e8/call slice-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax != false) break + 3d/compare-eax-and 0/imm32/false + # . restore result now that ZF is set + 58/pop-to-eax + 75/jump-if-!= $num-bytes:end/disp8 +$num-bytes:loop-body: + # result += compute-width-of-slice(word-slice) + # . copy result to edx + 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx + # . eax = compute-width-of-slice(word-slice) + # . . push args + 51/push-ecx + # . . call + e8/call compute-width-of-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . eax += result + 01/add 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # add edx to eax + e9/jump $num-bytes:loop/disp32 +$num-bytes:end: + # . rewind-stream(line) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call rewind-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . reclaim locals + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . restore registers + 5b/pop-to-ebx + 5a/pop-to-edx + 59/pop-to-ecx + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-num-bytes-handles-empty-string: + # if a line starts with '#', return 0 + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # no contents in input + # eax = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-num-bytes-handles-empty-string"/imm32 + 68/push 0/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-num-bytes-ignores-comments: + # if a line starts with '#', return 0 + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # initialize input + # . write(_test-input-stream, "# abcd") + # . . push args + 68/push "# abcd"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-num-bytes-ignores-comments"/imm32 + 68/push 0/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-num-bytes-ignores-labels: + # if the first word ends with ':', return 0 + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # initialize input + # . write(_test-input-stream, "ab: # cd") + # . . push args + 68/push "ab: # cd"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-num-bytes-ignores-labels"/imm32 + 68/push 0/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-num-bytes-ignores-segment-headers: + # if the first word is '==', return 0 + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # initialize input + # . write(_test-input-stream, "== ab cd") + # . . push args + 68/push "== ab cd"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-num-bytes-ignores-segment-headers"/imm32 + 68/push 0/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-num-bytes-counts-words-by-default: + # without metadata, count words + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # initialize input + # . write(_test-input-stream, "ab cd ef") + # . . push args + 68/push "ab cd ef"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 3, msg) + # . . push args + 68/push "F - test-num-bytes-counts-words-by-default"/imm32 + 68/push 3/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-num-bytes-ignores-trailing-comment: + # trailing comments appropriately ignored + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # initialize input + # . write(_test-input-stream, "ab cd # ef") + # . . push args + 68/push "ab cd # ef"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 2, msg) + # . . push args + 68/push "F - test-num-bytes-ignores-trailing-comment"/imm32 + 68/push 2/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-num-bytes-handles-imm32: + # if a word has the /imm32 metadata, count it as 4 bytes + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # setup + # . clear-stream(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . clear-stream(_test-output-stream) + # . . push args + 68/push _test-output-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # initialize input + # . write(_test-input-stream, "ab cd/imm32 ef") + # . . push args + 68/push "ab cd/imm32 ef"/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # eax = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 6, msg) + # . . push args + 68/push "F - test-num-bytes-handles-imm32"/imm32 + 68/push 6/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +# . . vim:nowrap:textwidth=0 diff --git a/linux/survey_baremetal b/linux/survey_baremetal index 91e0c5752bd85d94c357704201f8798fbddf176a..46de25b79adc1329b1c191528087226522a5f7d5 100755 GIT binary patch literal 47436 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 diff --git a/linux/survey_baremetal.subx b/linux/survey_baremetal.subx index 016757a8..d1d62906 100644 --- a/linux/survey_baremetal.subx +++ b/linux/survey_baremetal.subx @@ -1,6 +1,5 @@ # Assign addresses (co-ordinates) to instructions (landmarks) in a program # (landscape). -# Use the addresses assigned to replace labels. # # To build: # $ bootstrap/bootstrap translate [01]*.subx subx-params.subx survey_baremetal.subx -o survey_baremetal @@ -23,18 +22,12 @@ # foo: # 34 # -# The output is the stream of bytes without segment headers or label definitions, -# and with label references replaced with numeric values/displacements. +# The output is a list of labels and their computed addresses. # # $ cat x |bootstrap/bootstrap run survey_baremetal -# # 0x7c00 -# aa bb nn # some computed address -# cc dd nn nn nn nn # some computed displacement -# ee nn nn nn nn # address right after this instruction -# # 0x7c0e -# 00 00 # padding -# # 0x7c10 -# 34 # data segment interleaved with code +# 0x7c00 l1 +# 0x7c09 l2 +# 0x7c10 foo == code # instruction effective address register displacement immediate @@ -78,7 +71,6 @@ Entry: # run tests if necessary, convert stdin if not 3d/compare-eax-and 0/imm32/false 74/jump-if-= $subx-survey-main:interactive/disp8 # run-tests() -#? e8/call test-emit-output-with-padding/disp32 e8/call run-tests/disp32 # syscall(exit, *Num-test-failures) 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx @@ -112,8 +104,7 @@ subx-survey: # infile: (addr buffered-file), out: (addr buffered-file) # slurp(infile, in) # var labels: (stream {label-name, address} Max-labels) # compute-addresses(in, labels) - # rewind-stream(in) - # emit-output(in, out, labels) + # emit-labels(out, labels) # # . prologue 55/push-ebp @@ -159,22 +150,14 @@ subx-survey: # infile: (addr buffered-file), out: (addr buffered-file) e8/call compute-addresses/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # rewind-stream(in) - # . . push args - 56/push-esi - # . . call - e8/call rewind-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # emit-output(in, out, labels) + # emit-labels(out, labels) # . . push args 52/push-edx ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - 56/push-esi # . . call - e8/call emit-output/disp32 + e8/call emit-labels/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # flush(out) # . . push args ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) @@ -936,78 +919,19 @@ test-compute-addresses: 5d/pop-to-ebp c3/return -# global scratch space for emit-output -== data - -emit-output:datum: # slice - 0/imm32/start - 0/imm32/end - -== code - -emit-output: # in: (addr stream byte), out: (addr buffered-file), labels: (addr stream {(handle array byte), address}) +emit-labels: # out: (addr buffered-file), labels: (addr stream {(handle array byte), address}) # pseudocode: - # var address-of-next-instruction = 0x7c00 - # var line: (stream byte 512) - # line-loop: - # while true - # clear-stream(line) - # read-line(in, line) - # if (line->write == 0) break # end of file - # address-of-next-instruction += num-bytes(line) - # var far-jump-or-call? = far-jump-or-call?(line) - # rewind-stream(line) - # while true - # var word-slice = next-word(line) - # if slice-empty?(word-slice) # end of line - # break - # if slice-starts-with?(word-slice, "#") # comment - # break - # if label?(word-slice) # no need for label declarations anymore - # goto line-loop # don't insert empty lines - # if slice-equal?(word-slice, "==") # no need for segment header lines - # word-slice = next-word(line) # skip segment name - # word-slice = next-word(line) - # if !slice-empty?(word-slice) - # new-address = parse-hex-int-from-slice(word-slice) - # write-buffered(out, "# " address-of-next-instruction "\n") - # while address-of-next-instruction < new-address - # write-buffered("00") - # ++address-of-next-instruction - # write-buffered(out, "# " address-of-next-instruction "\n") - # goto line-loop # don't insert empty lines - # if length(word-slice) == 2 - # write-slice-buffered(out, word-slice) - # write-buffered(out, " ") - # continue - # var datum: (addr slice) = next-token-from-slice(word-slice->start, word-slice->end, "/") - # var address: (addr int) = get-slice(labels, datum) - # if has-metadata?(word-slice, "imm8") - # emit(out, *address, 1) - # else if has-metadata?(word-slice, "imm16") - # emit(out, *address, 2) - # else if has-metadata?(word-slice, "imm32") - # emit(out, *address, 4) - # else if has-metadata?(word-slice, "disp8") - # value = *address - address-of-next-instruction - # emit(out, value, 1) - # else if has-metadata?(word-slice, "disp32") - # if far-jump-or-call? - # value = *address - address-of-next-instruction - # else - # value = *address - # emit(out, value, 4) - # else - # abort - # write-buffered(out, "\n") - # - # registers: - # line: ecx - # word-slice: edx - # address-of-next-instruction: ebx - # far-jump-or-call?: edi - # address: esi (inner loop only) - # temporaries: eax, esi (outer loop) + # curr = table->data + # max = &table->data[table->write] + # while curr < max + # var label: (addr array byte) = lookup(*curr) + # curr += 8 + # write-buffered(out, label) + # write-buffered(out, ' ') + # write-buffered(out, *curr) + # curr += 4 + # write(out, '\n') + # return 0 # # . prologue 55/push-ebp @@ -1016,671 +940,44 @@ emit-output: # in: (addr stream byte), out: (addr buffered-file), labels: (addr 50/push-eax 51/push-ecx 52/push-edx - 53/push-ebx 56/push-esi - 57/push-edi - # var line/ecx: (stream byte 512) - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp - 68/push 0x200/imm32/size - 68/push 0/imm32/read - 68/push 0/imm32/write - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # var word-slice/edx: slice - 68/push 0/imm32/end - 68/push 0/imm32/start - 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # var address-of-next-instruction/ebx = 0x7c00 - bb/copy-to-ebx 0x7c00/imm32 -$emit-output:line-loop: - # clear-stream(line) + # esi = table + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi + # var curr/ecx: (addr handle array byte) = table->data + 8d/copy-address 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 0xc/disp8 . # copy esi+12 to ecx + # var max/edx: (addr byte) = &table->data[table->write] + 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx + 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx . . # copy ecx+edx to edx +$emit-labels:loop: + # if (curr >= max) return null + 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx + 0f 83/jump-if-addr>= $emit-labels:end/disp32 + # var label/eax: (addr array byte) = lookup(*curr) # . . push args - 51/push-ecx + ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) + ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx # . . call - e8/call clear-stream/disp32 + e8/call lookup/disp32 # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # read-line(in, line) + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # curr += 8 + 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 8/imm32 # add to ecx + # write-buffered(out, label) # . . push args - 51/push-ecx + 50/push-eax ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) # . . call - e8/call read-line/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # dump line {{{ -#? # . write(2/stderr, "LL: ") -#? # . . push args -#? 68/push "LL: "/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # write-stream(2/stderr, line) -#? # . . push args -#? 51/push-ecx -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . rewind-stream(line) -#? # . . push args -#? 51/push-ecx -#? # . . call -#? e8/call rewind-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # }}} -$emit-output:check-for-end-of-input: - # if (line->write == 0) break - 81 7/subop/compare 0/mod/indirect 1/rm32/ecx . . . . . 0/imm32 # compare *ecx - 0f 84/jump-if-= $emit-output:end/disp32 - # address-of-next-instruction += num-bytes(line) - # . eax = num-bytes(line) - # . . push args - 51/push-ecx - # . . call - e8/call num-bytes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . ebx += eax - 01/add 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # add eax to ebx - # var far-jump-or-call?/edi: boolean = far-jump-or-call?(line) - # . . push args - 51/push-ecx - # . . call - e8/call far-jump-or-call?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # rewind-stream(line) - # . . push args - 51/push-ecx - # . . call - e8/call rewind-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -$emit-output:word-loop: - # next-word(line, word-slice) - # . . push args - 52/push-edx - 51/push-ecx - # . . call - e8/call next-word/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # dump word-slice {{{ -#? # . write(2/stderr, "w: ") -#? # . . push args -#? 68/push "w: "/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write-slice-buffered(Stderr, word-slice) -#? # . . push args -#? 52/push-edx -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call write-slice-buffered/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . flush(Stderr) -#? # . . push args -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call flush/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # }}} -$emit-output:check-for-end-of-line: - # if (slice-empty?(word-slice)) break - # . eax = slice-empty?(word-slice) - # . . push args - 52/push-edx - # . . call - e8/call slice-empty?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) break - 3d/compare-eax-and 0/imm32/false - 0f 85/jump-if-!= $emit-output:next-line/disp32 -$emit-output:check-for-comment: - # if (slice-starts-with?(word-slice, "#")) break - # . start/esi = word-slice->start - 8b/copy 0/mod/indirect 2/rm32/edx . . . 6/r32/esi . . # copy *edx to esi - # . c/eax = *start - 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL - # . if (eax == '#') break - 3d/compare-eax-and 0x23/imm32/hash - 0f 84/jump-if-= $emit-output:next-line/disp32 -$emit-output:check-for-label: - # if label?(word-slice) break - # . eax = label?(word-slice) - # . . push args - 52/push-edx - # . . call - e8/call label?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != false) break - 3d/compare-eax-and 0/imm32/false - 0f 85/jump-if-!= $emit-output:line-loop/disp32 -$emit-output:check-for-segment-header: - # if !slice-equal?(word-slice, "==") goto next check - # . eax = slice-equal?(word-slice, "==") - # . . push args - 68/push "=="/imm32 - 52/push-edx - # . . call - e8/call slice-equal?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == false) goto next check - 3d/compare-eax-and 0/imm32/false - 0f 84/jump-if-= $emit-output:2-character/disp32 - # skip segment name - # . next-word(line, word-slice) - # . . push args - 52/push-edx - 51/push-ecx - # . . call - e8/call next-word/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # compute segment address if it exists - # . next-word(line, word-slice) - # . . push args - 52/push-edx - 51/push-ecx - # . . call - e8/call next-word/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if slice-empty?(word-slice) goto padding-done - # . . push args - 52/push-edx - # . . call - e8/call slice-empty?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . . - 3d/compare-eax-and 0/imm32/false - 0f 85/jump-if-!= $emit-output:padding-done/disp32 - # . var new-address/eax: int = parse-hex-int-from-slice(word-slice) - # . . push args - 52/push-edx - # . . call - e8/call parse-hex-int-from-slice/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # write-buffered(out, "# " address-of-next-instruction "\n") - # . write-buffered(out, "# ") - # . . push args - 68/push "# "/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call e8/call write-buffered/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write-int32-hex-buffered(out, address-of-next-instruction) - # . . push args - 53/push-ebx - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-int32-hex-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write-buffered(out, "\n") - # . . push args - 68/push Newline/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -$emit-output:padding-loop: - # if (address-of-next-instruction >= new-address) goto padding-loop-done - 39/compare 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # compare ebx with eax - 73/jump-if-addr>= $emit-output:padding-loop-done/disp8 - # if (address-of-next-instruction % 8 == 0) write-buffered("\n") - 53/push-ebx - 81 4/subop/and 3/mod/direct 3/rm32/ebx . . . . . 7/imm32 # bitwise and of ebx - 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32 # compare ebx - 5b/pop-to-ebx - 75/jump-if-!= $emit-output:padding-core/disp8 - # . write-buffered(out, "\n") - # . . push args - 68/push Newline/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -$emit-output:padding-core: - # write-buffered("00") - # . . push args - 68/push "00 "/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # ++address-of-next-instruction - 43/increment-ebx - # loop - eb/jump $emit-output:padding-loop/disp8 -$emit-output:padding-loop-done: - # . write-buffered(out, "\n") - # . . push args - 68/push Newline/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -$emit-output:padding-done: - # write-buffered(out, "# " address-of-next-instruction "\n") - # . write-buffered(out, "# ") - # . . push args - 68/push "# "/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write-int32-hex-buffered(out, address-of-next-instruction) - # . . push args - 53/push-ebx - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-int32-hex-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write-buffered(out, "\n") - # . . push args - 68/push Newline/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # - e9/jump $emit-output:line-loop/disp32 -$emit-output:2-character: - # if (size(word-slice) != 2) goto next check - # . eax = size(word-slice) - 8b/copy 1/mod/*+disp8 2/rm32/edx . . . 0/r32/eax 4/disp8 . # copy *(edx+4) to eax - 2b/subtract 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # subtract *edx from eax - # . if (eax != 2) goto next check - 3d/compare-eax-and 2/imm32 - 75/jump-if-!= $emit-output:check-metadata/disp8 - # write-slice-buffered(out, word-slice) - # . . push args - 52/push-edx - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-slice-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # write-buffered(out, " ") + # write-buffered(out, ' ') # . . push args 68/push Space/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) # . . call e8/call write-buffered/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # continue - e9/jump $emit-output:word-loop/disp32 -$emit-output:check-metadata: - # - if we get here, 'word-slice' must be a label to be looked up - # datum = next-token-from-slice(word-slice->start, word-slice->end, "/") - # . . push args - 68/push emit-output:datum/imm32 - 68/push 0x2f/imm32/slash - ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) - ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx - # . . call - e8/call next-token-from-slice/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp -#? # dump datum {{{ -#? # . write(2/stderr, "datum: ") -#? # . . push args -#? 68/push "datum: "/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write-slice-buffered(Stderr, datum) -#? # . . push args -#? 68/push emit-output:datum/imm32 -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call write-slice-buffered/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . flush(Stderr) -#? # . . push args -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call flush/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # }}} - # address/esi: (addr int) = get-slice(labels, datum, row-size=12, "label table") - # . eax = get-slice(labels, datum, row-size=24, "label table") - # . . push args - 68/push "label table"/imm32 - 68/push 0xc/imm32/row-size - 68/push emit-output:datum/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) - # . . call - e8/call get-slice/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # . esi = eax - 89/copy 3/mod/direct 6/rm32/esi . . . 0/r32/eax . . # copy eax to esi -$emit-output:check-imm8: - # if (!has-metadata?(word-slice, "imm8")) goto next check - # . eax = has-metadata?(edx, "imm8") - # . . push args - 68/push "imm8"/imm32 - 52/push-edx - # . . call - e8/call has-metadata?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) abort - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $emit-output:check-imm16/disp8 -$emit-output:emit-imm8: - # emit-hex(out, *address, 1) - # . . push args - 68/push 1/imm32 - ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call emit-hex/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # continue - e9/jump $emit-output:word-loop/disp32 -$emit-output:check-imm16: - # if (!has-metadata?(word-slice, "imm16")) goto next check - # . eax = has-metadata?(edx, "imm16") - # . . push args - 68/push "imm16"/imm32 - 52/push-edx - # . . call - e8/call has-metadata?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == false) goto next check - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $emit-output:check-imm32/disp8 -#? # dump *address {{{ -#? # . write(2/stderr, "*address: ") -#? # . . push args -#? 68/push "*address: "/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write-int32-hex-buffered(Stderr, *address) -#? # . . push args -#? ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call write-int32-hex-buffered/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . flush(Stderr) -#? # . . push args -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call flush/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # }}} -$emit-output:emit-imm16: - # emit-hex(out, *address, 2) - # . . push args - 68/push 2/imm32 - ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call emit-hex/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # TODO: ensure that the higher 2 bytes are zero - # continue - e9/jump $emit-output:word-loop/disp32 -$emit-output:check-imm32: - # if (!has-metadata?(word-slice, "imm32")) goto next check - # . eax = has-metadata?(edx, "imm32") - # . . push args - 68/push "imm32"/imm32 - 52/push-edx - # . . call - e8/call has-metadata?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == false) goto next check - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $emit-output:check-disp8/disp8 -#? # dump *address {{{ -#? # . write(2/stderr, "*address: ") -#? # . . push args -#? 68/push "*address: "/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write-int32-hex-buffered(Stderr, *address) -#? # . . push args -#? ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call write-int32-hex-buffered/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . flush(Stderr) -#? # . . push args -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call flush/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # }}} -$emit-output:emit-imm32: - # emit-hex(out, *address, 4) - # . . push args - 68/push 4/imm32 - ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call emit-hex/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # continue - e9/jump $emit-output:word-loop/disp32 -$emit-output:check-disp8: - # if (!has-metadata?(word-slice, "disp8")) goto next check - # . eax = has-metadata?(edx, "disp8") - # . . push args - 68/push "disp8"/imm32 - 52/push-edx - # . . call - e8/call has-metadata?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == false) goto next check - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $emit-output:check-disp16/disp8 -$emit-output:emit-disp8: - # emit-hex(out, *address - address-of-next-instruction, 1) - # . . push args - 68/push 1/imm32 - 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax - 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax - 50/push-eax - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call emit-hex/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # continue - e9/jump $emit-output:word-loop/disp32 -$emit-output:check-disp16: - # if (!has-metadata?(word-slice, "disp16")) goto next check - # . eax = has-metadata?(edx, "disp16") - # . . push args - 68/push "disp16"/imm32 - 52/push-edx - # . . call - e8/call has-metadata?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == false) goto next check - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $emit-output:check-disp32/disp8 -$emit-output:emit-disp16: - # emit-hex(out, *address - address-of-next-instruction, 2) - # . . push args - 68/push 2/imm32 - 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax - 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax - 50/push-eax - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call emit-hex/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # continue - e9/jump $emit-output:word-loop/disp32 -$emit-output:check-disp32: - # if (!has-metadata?(word-slice, "disp32")) abort - # . eax = has-metadata?(edx, "disp32") - # . . push args - 68/push "disp32"/imm32 - 52/push-edx - # . . call - e8/call has-metadata?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == false) abort - 3d/compare-eax-and 0/imm32/false - 0f 84/jump-if-= $emit-output:abort/disp32 -$emit-output:emit-disp32: - # var value/eax = *address - 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax - # if (far-jump-or-call?) value -= address-of-next-instruction - 81 7/subop/compare 3/mod/direct 7/rm32/edi . . . . . 0/imm32/false # compare edi - 74/jump-if-= $emit-output:really-emit-disp32/disp8 - 29/subtract 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # subtract ebx from eax -$emit-output:really-emit-disp32: - # emit-hex(out, value, 4) - # . . push args - 68/push 4/imm32 - 50/push-eax - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call emit-hex/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # continue - e9/jump $emit-output:word-loop/disp32 -$emit-output:next-line: - # write-buffered(out, "\n") - # . . push args - 68/push Newline/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # loop - e9/jump $emit-output:line-loop/disp32 -$emit-output:end: - # . reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x214/imm32 # add to esp - # . restore registers - 5f/pop-to-edi - 5e/pop-to-esi - 5b/pop-to-ebx - 5a/pop-to-edx - 59/pop-to-ecx - 58/pop-to-eax - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -$emit-output:abort: - # print(stderr, "missing metadata in " word-slice) - # . _write(2/stderr, "missing metadata in word ") - # . . push args - 68/push "emit-output: missing metadata in "/imm32 - 68/push 2/imm32/stderr - # . . call - e8/call _write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write-slice-buffered(Stderr, word-slice) - # . . push args - 52/push-edx - 68/push Stderr/imm32 - # . . call - e8/call write-slice-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp # . flush(Stderr) # . . push args 68/push Stderr/imm32 @@ -1688,1014 +985,27 @@ $emit-output:abort: e8/call flush/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . syscall(exit, 1) - bb/copy-to-ebx 1/imm32 - e8/call syscall_exit/disp32 - # never gets here - -test-emit-output-non-far-control-flow: - # labels turn into absolute addresses if opcodes are not far jumps or calls - # - # input: - # in: - # == code - # ab cd ef gh - # ij x/disp32 - # == data - # 00 - # 34 - # labels: - # - 'x': 0x11223344 - # - # output: - # ab cd ef gh - # ij 44 33 22 11 - # 00 - # 34 - # - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) + # write-int32-hex-buffered(out, *curr) # . . push args - 68/push _test-input-stream/imm32 + ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream($_test-output-buffered-file->buffer) - # . . push args - 68/push $_test-output-buffered-file->buffer/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . var labels/edx: (stream byte 8*24) - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xc0/imm32 # subtract from esp - 68/push 0xc0/imm32/size - 68/push 0/imm32/read - 68/push 0/imm32/write - 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # . var h/ebx: (handle array byte) - 68/push 0/imm32 - 68/push 0/imm32 - 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx - # initialize input - # . write(_test-input-stream, "== code\n") - # . . push args - 68/push "== code\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 + e8/call write-int32-hex-buffered/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "ab cd ef gh\n") - # . . push args - 68/push "ab cd ef gh\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "ij x/disp32\n") - # . . push args - 68/push "ij x/disp32\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "== data\n") - # . . push args - 68/push "== data\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "00\n") - # . . push args - 68/push "00\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "34\n") - # . . push args - 68/push "34\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . stream-add2(labels, "x", 0x11223344) - 68/push 0x11223344/imm32/label-address - # . . push handle for "x" - 53/push-ebx - 68/push "x"/imm32 - 68/push Heap/imm32 - e8/call copy-array/disp32 - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - ff 6/subop/push 1/mod/*+disp8 3/rm32/ebx . . . . 4/disp8 . # push *(ebx+4) - ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx - # . . push labels - 52/push-edx - # . . call - e8/call stream-add2/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # component under test - # . emit-output(_test-input-stream, _test-output-buffered-file, labels) - # . . push args - 52/push-edx - 68/push _test-output-buffered-file/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call emit-output/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # checks - # . flush(_test-output-buffered-file) - # . . push args - 68/push _test-output-buffered-file/imm32 - # . . call - e8/call flush/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # dump output {{{ -#? # . write(2/stderr, "result: ^") -#? # . . push args -#? 68/push "result: ^"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write-stream(2/stderr, _test-output-stream) -#? # . . push args -#? 68/push _test-output-stream/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . rewind-stream(_test-output-stream) -#? # . . push args -#? 68/push _test-output-stream/imm32 -#? # . . call -#? e8/call rewind-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # }}} - # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg) - # . . push args - 68/push "F - test-emit-output-non-far-control-flow/0"/imm32 - 68/push "# 0x00007c00"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "ab cd ef gh ", msg) - # . . push args - 68/push "F - test-emit-output-non-far-control-flow/1"/imm32 - 68/push "ab cd ef gh "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "ij 44 33 22 11 ", msg) - # . . push args - 68/push "F - test-emit-output-non-far-control-flow/2"/imm32 - 68/push "ij 44 33 22 11 "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c09", msg) - # . . push args - 68/push "F - test-emit-output-non-far-control-flow/3"/imm32 - 68/push "# 0x00007c09"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "00 ", msg) - # . . push args - 68/push "F - test-emit-output-non-far-control-flow/3"/imm32 - 68/push "00 "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "34 ", msg) - # . . push args - 68/push "F - test-emit-output-non-far-control-flow/4"/imm32 - 68/push "34 "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-emit-output-with-padding: - # labels turn into absolute addresses if opcodes are not far jumps or calls - # - # input: - # in: - # == code - # ab cd ef gh - # == data 0x7c10 - # 34 - # - # output: - # ab cd ef gh - # # 0x7c04 - # 00 00 00 00 - # 00 00 00 00 00 00 00 00 - # # 0x7c10 - # 34 - # - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream($_test-output-buffered-file->buffer) - # . . push args - 68/push $_test-output-buffered-file->buffer/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . var labels/edx: (stream byte 8*24) - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xc0/imm32 # subtract from esp - 68/push 0xc0/imm32/size - 68/push 0/imm32/read - 68/push 0/imm32/write - 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # . var h/ebx: (handle array byte) - 68/push 0/imm32 - 68/push 0/imm32 - 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx - # initialize input - # . write(_test-input-stream, "== code\n") - # . . push args - 68/push "== code\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "ab cd ef gh\n") - # . . push args - 68/push "ab cd ef gh\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "== data 0x7c10\n") - # . . push args - 68/push "== data 0x7c10\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "34\n") - # . . push args - 68/push "34\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # component under test - # . emit-output(_test-input-stream, _test-output-buffered-file, labels) - # . . push args - 52/push-edx - 68/push _test-output-buffered-file/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call emit-output/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # checks - # . flush(_test-output-buffered-file) - # . . push args - 68/push _test-output-buffered-file/imm32 - # . . call - e8/call flush/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # dump output {{{ -#? # . write(2/stderr, "result: ^") -#? # . . push args -#? 68/push "result: ^"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write-stream(2/stderr, _test-output-stream) -#? # . . push args -#? 68/push _test-output-stream/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . rewind-stream(_test-output-stream) -#? # . . push args -#? 68/push _test-output-stream/imm32 -#? # . . call -#? e8/call rewind-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # }}} - # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg) - # . . push args - 68/push "F - test-emit-output-with-padding/0"/imm32 - 68/push "# 0x00007c00"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "ab cd ef gh ", msg) - # . . push args - 68/push "F - test-emit-output-with-padding/1"/imm32 - 68/push "ab cd ef gh "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c04", msg) - # . . push args - 68/push "F - test-emit-output-with-padding/0"/imm32 - 68/push "# 0x00007c04"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "00 00 00 00 ", msg) - # . . push args - 68/push "F - test-emit-output-with-padding/2"/imm32 - 68/push "00 00 00 00 "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "00 00 00 00 ", msg) - # . . push args - 68/push "F - test-emit-output-with-padding/3"/imm32 - 68/push "00 00 00 00 00 00 00 00 "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c10", msg) - # . . push args - 68/push "F - test-emit-output-with-padding/0"/imm32 - 68/push "# 0x00007c10"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "34 ", msg) - # . . push args - 68/push "F - test-emit-output-with-padding/4"/imm32 - 68/push "34 "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-emit-output-code-label: - # labels turn into PC-relative addresses if opcodes are far jumps or calls - # - # input: - # in: - # == code - # ab cd - # ef gh - # e8 l1/disp32 - # labels: - # - 'l1': 0x7c10 - # - # output: - # ab cd - # ef gh - # e8 07 00 00 00 # 0x7c10 - 0x7c09 = 7 - # - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream($_test-output-buffered-file->buffer) - # . . push args - 68/push $_test-output-buffered-file->buffer/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . var labels/edx: (stream byte 8*24) - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xc0/imm32 # subtract from esp - 68/push 0xc0/imm32/size - 68/push 0/imm32/read - 68/push 0/imm32/write - 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # . var h/ebx: (handle array byte) - 68/push 0/imm32 - 68/push 0/imm32 - 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx - # initialize input - # . write(_test-input-stream, "== code\n") - # . . push args - 68/push "== code\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "ab cd\n") - # . . push args - 68/push "ab cd\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "ef gh\n") - # . . push args - 68/push "ef gh\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "e8 l1/disp32\n") - # . . push args - 68/push "e8 l1/disp32\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . stream-add2(labels, "l1", 0x7c10) - 68/push 0x7c10/imm32/label-address - # . . push handle for "l1" - 53/push-ebx - 68/push "l1"/imm32 - 68/push Heap/imm32 - e8/call copy-array/disp32 - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - ff 6/subop/push 1/mod/*+disp8 3/rm32/ebx . . . . 4/disp8 . # push *(ebx+4) - ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx - # . . push labels - 52/push-edx - # . . call - e8/call stream-add2/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # component under test - # . emit-output(_test-input-stream, _test-output-buffered-file, labels) - # . . push args - 52/push-edx - 68/push _test-output-buffered-file/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call emit-output/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # checks - # . flush(_test-output-buffered-file) - # . . push args - 68/push _test-output-buffered-file/imm32 - # . . call - e8/call flush/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # dump output {{{ -#? # . write(2/stderr, "result: ^") -#? # . . push args -#? 68/push "result: ^"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write-stream(2/stderr, _test-output-stream) -#? # . . push args -#? 68/push _test-output-stream/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . rewind-stream(_test-output-stream) -#? # . . push args -#? 68/push _test-output-stream/imm32 -#? # . . call -#? e8/call rewind-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # }}} - # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg) - # . . push args - 68/push "F - test-emit-output-code-label/0"/imm32 - 68/push "# 0x00007c00"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "ab cd ", msg) - # . . push args - 68/push "F - test-emit-output-code-label/1"/imm32 - 68/push "ab cd "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "ef gh ", msg) - # . . push args - 68/push "F - test-emit-output-code-label/2"/imm32 - 68/push "ef gh "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "e8 07 00 00 00 ", msg) - # . . push args - 68/push "F - test-emit-output-code-label/3"/imm32 - 68/push "e8 07 00 00 00 "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-emit-output-code-label-absolute: - # labels can also convert to absolute addresses - # - # input: - # in: - # == code - # ab cd - # ef gh - # ij l1/imm32 - # labels: - # - 'l1': 0x1056 - # - # output: - # ab cd - # ef gh - # ij 56 10 00 00 - # - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream($_test-output-buffered-file->buffer) - # . . push args - 68/push $_test-output-buffered-file->buffer/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . var labels/edx: (stream byte 8*24) - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xc0/imm32 # subtract from esp - 68/push 0xc0/imm32/size - 68/push 0/imm32/read - 68/push 0/imm32/write - 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # . var h/ebx: (handle array byte) - 68/push 0/imm32 - 68/push 0/imm32 - 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx - # initialize input - # . write(_test-input-stream, "== code 0x1000\n") - # . . push args - 68/push "== code\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "ab cd\n") - # . . push args - 68/push "ab cd\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "ef gh\n") - # . . push args - 68/push "ef gh\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(_test-input-stream, "ij l1/imm32\n") - # . . push args - 68/push "ij l1/imm32\n"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . stream-add2(labels, "l1", 0x1056) - 68/push 0x1056/imm32/label-address - # . . push handle for "l1" - 53/push-ebx - 68/push "l1"/imm32 - 68/push Heap/imm32 - e8/call copy-array/disp32 - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - ff 6/subop/push 1/mod/*+disp8 3/rm32/ebx . . . . 4/disp8 . # push *(ebx+4) - ff 6/subop/push 0/mod/indirect 3/rm32/ebx . . . . . . # push *ebx - # . . push labels - 52/push-edx - # . . call - e8/call stream-add2/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # component under test - # . emit-output(_test-input-stream, _test-output-buffered-file, labels) - # . . push args - 52/push-edx - 68/push _test-output-buffered-file/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call emit-output/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # checks - # . flush(_test-output-buffered-file) - # . . push args - 68/push _test-output-buffered-file/imm32 - # . . call - e8/call flush/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # dump output {{{ -#? # . write(2/stderr, "result: ^") -#? # . . push args -#? 68/push "result: ^"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write-stream(2/stderr, _test-output-stream) -#? # . . push args -#? 68/push _test-output-stream/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . rewind-stream(_test-output-stream) -#? # . . push args -#? 68/push _test-output-stream/imm32 -#? # . . call -#? e8/call rewind-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # }}} - # . check-next-stream-line-equal(_test-output-stream, "# 0x00007c00", msg) - # . . push args - 68/push "F - test-emit-output-code-label-absolute/0"/imm32 - 68/push "# 0x00007c00"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "ab cd ", msg) - # . . push args - 68/push "F - test-emit-output-code-label-absolute/1"/imm32 - 68/push "ab cd "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "ef gh ", msg) - # . . push args - 68/push "F - test-emit-output-code-label-absolute/2"/imm32 - 68/push "ef gh "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . check-next-stream-line-equal(_test-output-stream, "ij f9 ff ff ff ", msg) - # . . push args - 68/push "F - test-emit-output-code-label-absolute/3"/imm32 - 68/push "ij 56 10 00 00 "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-next-stream-line-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -# reads line to make some checks -# don't assume the read state of line after calling this function -far-jump-or-call?: # line: (addr stream byte) -> result/edi: boolean - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # . save registers - 50/push-eax - 51/push-ecx - 52/push-edx - 53/push-ebx - # ecx = line - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx - # var word-slice/edx: slice - 68/push 0/imm32/end - 68/push 0/imm32/start - 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - # var datum-slice/ebx: slice - 68/push 0/imm32/end - 68/push 0/imm32/start - 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx - # result = false - bf/copy-to-edi 0/imm32/false -$far-jump-or-call?:check-first-word: - # next-word(line, word-slice) - # . . push args - 52/push-edx - 51/push-ecx - # . . call - e8/call next-word/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # if (slice-empty?(word-slice)) return false - # . eax = slice-empty?(word-slice) - # . . push args - 52/push-edx - # . . call - e8/call slice-empty?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) return - 3d/compare-eax-and 0/imm32/false - 0f 85/jump-if-!= $far-jump-or-call?:end/disp32 - # datum = next-token-from-slice(word-slice->start, word-slice->end, "/") - # . . push args - 53/push-ebx - 68/push 0x2f/imm32/slash - ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) - ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx - # . . call - e8/call next-token-from-slice/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # if (datum-slice == "e8") return true - # . eax = slice-equal?(datum-slice, "e8") - # . . push args - 68/push "e8"/imm32 - 53/push-ebx - # . . call - e8/call slice-equal?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return true - 3d/compare-eax-and 0/imm32/false - 75/jump-if-!= $far-jump-or-call?:return-true/disp8 - # if (datum-slice == "e9") return true - # . eax = slice-equal?(datum-slice, "e9") - # . . push args - 68/push "e9"/imm32 - 53/push-ebx - # . . call - e8/call slice-equal?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) return true - 3d/compare-eax-and 0/imm32/false - 75/jump-if-!= $far-jump-or-call?:return-true/disp8 - # if (datum-slice != "0f") return false - # . eax = slice-equal?(datum-slice, "0f") - # . . push args - 68/push "0f"/imm32 - 53/push-ebx - # . . call - e8/call slice-equal?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax == false) return - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $far-jump-or-call?:end/disp8 -$far-jump-or-call?:check-second-word: - # next-word(line, word-slice) - # . . push args - 52/push-edx - 51/push-ecx - # . . call - e8/call next-word/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # if (slice-empty?(word-slice)) return false - # . eax = slice-empty?(word-slice) - # . . push args - 52/push-edx - # . . call - e8/call slice-empty?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != 0) return - 3d/compare-eax-and 0/imm32/false - 75/jump-if-!= $far-jump-or-call?:end/disp8 - # if datum of word-slice does not start with "8", return false - # . start/eax = word-slice->start - 8b/copy 0/mod/indirect 2/rm32/edx . . . 0/r32/eax . . # copy *edx to eax - # . c/eax = *start - 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL - 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax - # . if (eax != '8') return - 3d/compare-eax-and 0x38/imm32/8 - 75/jump-if-!= $far-jump-or-call?:end/disp8 - # otherwise return true -$far-jump-or-call?:return-true: - bf/copy-to-edi 1/imm32/true -$far-jump-or-call?:end: - # . reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # . restore registers - 5b/pop-to-ebx - 5a/pop-to-edx - 59/pop-to-ecx - 58/pop-to-eax - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -# - some helpers for tests - -stream-add2: # in: (addr stream byte), key: handle, val: int - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # . save registers - 50/push-eax - 51/push-ecx - 52/push-edx - 56/push-esi - # esi = in - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi - # curr/eax = &in->data[in->write] - # . eax = in->write - 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax - # . eax = esi+eax+12 - 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 0/r32/eax 0xc/disp8 . # copy esi+eax+12 to eax - # max/edx = &in->data[in->size] - # . edx = in->size - 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 8/disp8 . # copy *(esi+8) to edx - # . edx = esi+edx+12 - 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 2/index/edx . 2/r32/edx 0xc/disp8 . # copy esi+edx+12 to edx - # if (curr >= max) abort - 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax with edx - 73/jump-if-addr>= $stream-add2:abort/disp8 - # *curr = key->alloc-id - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx - 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax # curr += 4 - 05/add-to-eax 4/imm32 - # if (curr >= max) abort - 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax with edx - 73/jump-if-addr>= $stream-add2:abort/disp8 - # *curr = key->payload - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 0x10/disp8 . # copy *(ebp+16) to ecx - 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax - # curr += 4 - 05/add-to-eax 4/imm32 - # if (curr >= max) abort - 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax with edx - 73/jump-if-addr>= $stream-add2:abort/disp8 - # *curr = val - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 0x14/disp8 . # copy *(ebp+20) to ecx - 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax - # in->write += 0xc - 81 0/subop/add 0/mod/indirect 6/rm32/esi . . . . . 0xc/imm32 # add to *esi -$stream-add2:end: + 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx + # write-buffered(out, '\n') + # . . push args + 68/push Newline/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + # . . call + e8/call write-buffered/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # loop + e9/jump $emit-labels:loop/disp32 +$emit-labels:end: # . restore registers 5e/pop-to-esi 5a/pop-to-edx @@ -2706,19 +1016,7 @@ $stream-add2:end: 5d/pop-to-ebp c3/return -$stream-add2:abort: - # . _write(2/stderr, error) - # . . push args - 68/push "overflow in stream-add2\n"/imm32 - 68/push 2/imm32/stderr - # . . call - e8/call _write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . syscall(exit, 1) - bb/copy-to-ebx 1/imm32 - e8/call syscall_exit/disp32 - # never gets here +# - some helpers for tests # some variants of 'trace' that take multiple arguments in different combinations of types: # n: int @@ -2843,543 +1141,4 @@ test-trace-slsns: 5d/pop-to-ebp c3/return -num-bytes: # line: (addr stream byte) -> eax: int - # pseudocode: - # result = 0 - # while true - # var word-slice = next-word(line) - # if slice-empty?(word-slice) # end of line - # break - # if slice-starts-with?(word-slice, "#") # comment - # break - # if label?(word-slice) # no need for label declarations anymore - # break - # if slice-equal?(word-slice, "==") - # break # no need for segment header lines - # result += compute-width(word-slice) - # return result - # - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # . save registers - 51/push-ecx - 52/push-edx - 53/push-ebx - # var result/eax = 0 - 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - # var word-slice/ecx: slice - 68/push 0/imm32/end - 68/push 0/imm32/start - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -#? # dump line {{{ -#? # . write(2/stderr, "LL: ") -#? # . . push args -#? 68/push "LL: "/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # write-stream(2/stderr, line) -#? # . . push args -#? ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # }}} - # . rewind-stream(line) - # . . push args - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call rewind-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -$num-bytes:loop: - # next-word(line, word-slice) - # . . push args - 51/push-ecx - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call next-word/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # dump word-slice {{{ -#? # . write(2/stderr, "AA: ") -#? # . . push args -#? 68/push "AA: "/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . clear-stream($Stderr->buffer) -#? # . . push args -#? 68/push $Stderr->buffer/imm32 -#? # . . call -#? e8/call clear-stream/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # . write-slice-buffered(Stderr, word-slice) -#? # . . push args -#? 51/push-ecx -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call write-slice-buffered/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # . flush(Stderr) -#? # . . push args -#? 68/push Stderr/imm32 -#? # . . call -#? e8/call flush/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -#? # . write(2/stderr, "$\n") -#? # . . push args -#? 68/push "$\n"/imm32 -#? 68/push 2/imm32/stderr -#? # . . call -#? e8/call write/disp32 -#? # . . discard args -#? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -#? # }}} -$num-bytes:check0: - # if (slice-empty?(word-slice)) break - # . save result - 50/push-eax - # . eax = slice-empty?(word-slice) - # . . push args - 51/push-ecx - # . . call - e8/call slice-empty?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax != false) break - 3d/compare-eax-and 0/imm32/false - # . restore result now that ZF is set - 58/pop-to-eax - 75/jump-if-!= $num-bytes:end/disp8 -$num-bytes:check-for-comment: - # if (slice-starts-with?(word-slice, "#")) break - # . start/edx = word-slice->start - 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx - # . c/ebx = *start - 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx - 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 3/r32/BL . . # copy byte at *edx to BL - # . if (ebx == '#') break - 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x23/imm32/hash # compare ebx - 74/jump-if-= $num-bytes:end/disp8 -$num-bytes:check-for-label: - # if (slice-ends-with?(word-slice, ":")) break - # . end/edx = word-slice->end - 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx - # . c/ebx = *(end-1) - 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx - 8a/copy-byte 1/mod/*+disp8 2/rm32/edx . . . 3/r32/BL -1/disp8 . # copy byte at *ecx to BL - # . if (ebx == ':') break - 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x3a/imm32/colon # compare ebx - 74/jump-if-= $num-bytes:end/disp8 -$num-bytes:check-for-segment-header: - # if (slice-equal?(word-slice, "==")) break - # . push result - 50/push-eax - # . eax = slice-equal?(word-slice, "==") - # . . push args - 68/push "=="/imm32 - 51/push-ecx - # . . call - e8/call slice-equal?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . if (eax != false) break - 3d/compare-eax-and 0/imm32/false - # . restore result now that ZF is set - 58/pop-to-eax - 75/jump-if-!= $num-bytes:end/disp8 -$num-bytes:loop-body: - # result += compute-width-of-slice(word-slice) - # . copy result to edx - 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx - # . eax = compute-width-of-slice(word-slice) - # . . push args - 51/push-ecx - # . . call - e8/call compute-width-of-slice/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . eax += result - 01/add 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # add edx to eax - e9/jump $num-bytes:loop/disp32 -$num-bytes:end: - # . rewind-stream(line) - # . . push args - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call rewind-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . restore registers - 5b/pop-to-ebx - 5a/pop-to-edx - 59/pop-to-ecx - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-num-bytes-handles-empty-string: - # if a line starts with '#', return 0 - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # no contents in input - # eax = num-bytes(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call num-bytes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # check-ints-equal(eax, 0, msg) - # . . push args - 68/push "F - test-num-bytes-handles-empty-string"/imm32 - 68/push 0/imm32/true - 50/push-eax - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-num-bytes-ignores-comments: - # if a line starts with '#', return 0 - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # initialize input - # . write(_test-input-stream, "# abcd") - # . . push args - 68/push "# abcd"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # eax = num-bytes(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call num-bytes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # check-ints-equal(eax, 0, msg) - # . . push args - 68/push "F - test-num-bytes-ignores-comments"/imm32 - 68/push 0/imm32/true - 50/push-eax - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-num-bytes-ignores-labels: - # if the first word ends with ':', return 0 - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # initialize input - # . write(_test-input-stream, "ab: # cd") - # . . push args - 68/push "ab: # cd"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # eax = num-bytes(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call num-bytes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # check-ints-equal(eax, 0, msg) - # . . push args - 68/push "F - test-num-bytes-ignores-labels"/imm32 - 68/push 0/imm32/true - 50/push-eax - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-num-bytes-ignores-segment-headers: - # if the first word is '==', return 0 - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # initialize input - # . write(_test-input-stream, "== ab cd") - # . . push args - 68/push "== ab cd"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # eax = num-bytes(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call num-bytes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # check-ints-equal(eax, 0, msg) - # . . push args - 68/push "F - test-num-bytes-ignores-segment-headers"/imm32 - 68/push 0/imm32/true - 50/push-eax - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-num-bytes-counts-words-by-default: - # without metadata, count words - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # initialize input - # . write(_test-input-stream, "ab cd ef") - # . . push args - 68/push "ab cd ef"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # eax = num-bytes(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call num-bytes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # check-ints-equal(eax, 3, msg) - # . . push args - 68/push "F - test-num-bytes-counts-words-by-default"/imm32 - 68/push 3/imm32/true - 50/push-eax - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-num-bytes-ignores-trailing-comment: - # trailing comments appropriately ignored - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # initialize input - # . write(_test-input-stream, "ab cd # ef") - # . . push args - 68/push "ab cd # ef"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # eax = num-bytes(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call num-bytes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # check-ints-equal(eax, 2, msg) - # . . push args - 68/push "F - test-num-bytes-ignores-trailing-comment"/imm32 - 68/push 2/imm32/true - 50/push-eax - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-num-bytes-handles-imm32: - # if a word has the /imm32 metadata, count it as 4 bytes - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . clear-stream(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . clear-stream(_test-output-stream) - # . . push args - 68/push _test-output-stream/imm32 - # . . call - e8/call clear-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # initialize input - # . write(_test-input-stream, "ab cd/imm32 ef") - # . . push args - 68/push "ab cd/imm32 ef"/imm32 - 68/push _test-input-stream/imm32 - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # eax = num-bytes(_test-input-stream) - # . . push args - 68/push _test-input-stream/imm32 - # . . call - e8/call num-bytes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # check-ints-equal(eax, 6, msg) - # . . push args - 68/push "F - test-num-bytes-handles-imm32"/imm32 - 68/push 6/imm32/true - 50/push-eax - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - # . . vim:nowrap:textwidth=0 diff --git a/linux/test_apps b/linux/test_apps index 9d8e5683..1719b5fd 100755 --- a/linux/test_apps +++ b/linux/test_apps @@ -216,7 +216,7 @@ bootstrap/bootstrap translate [01]*.subx random.subx -o random # Phases of the self-hosted SubX translator. -for phase in hex survey_elf survey_baremetal pack assort dquotes tests +for phase in hex survey_elf survey_baremetal labels_baremetal pack assort dquotes tests do echo $phase bootstrap/bootstrap translate [01]*.subx subx-params.subx $phase.subx -o $phase @@ -314,7 +314,7 @@ done # Phases of the self-hosted SubX translator. -for app in hex survey_elf survey_baremetal pack assort dquotes tests +for app in hex survey_elf survey_baremetal labels_baremetal pack assort dquotes tests do echo $app ./translate_subx [01]*.subx subx-params.subx $app.subx diff --git a/linux/test_apps_emulated b/linux/test_apps_emulated index cb74c1ae..f12ada06 100755 --- a/linux/test_apps_emulated +++ b/linux/test_apps_emulated @@ -137,7 +137,7 @@ bootstrap/bootstrap translate [01]*.subx random.subx -o random # Phases of the self-hosted SubX translator. -for phase in hex survey_elf survey_baremetal pack assort dquotes tests +for phase in hex survey_elf survey_baremetal labels_baremetal pack assort dquotes tests do echo $phase bootstrap/bootstrap translate [01]*.subx subx-params.subx $phase.subx -o $phase @@ -211,7 +211,7 @@ done # Phases of the self-hosted SubX translator. -for app in hex survey_elf survey_baremetal pack assort dquotes tests +for app in hex survey_elf survey_baremetal labels_baremetal pack assort dquotes tests do echo $app ./translate_subx_emulated [01]*.subx subx-params.subx $app.subx diff --git a/translate_subx b/translate_subx index f4c461f6..70400f45 100755 --- a/translate_subx +++ b/translate_subx @@ -12,23 +12,24 @@ set -e -cat $* |linux/braces > a.braces +cat $* |linux/braces > a.braces -cat a.braces |linux/calls > a.calls +cat a.braces |linux/calls > a.calls -cat a.calls |linux/sigils > a.sigils +cat a.calls |linux/sigils > a.sigils -cat a.sigils |linux/tests > a.tests +cat a.sigils |linux/tests > a.tests # no assort since baremetal SubX doesn't have segments yet -cat a.tests |linux/dquotes > a.dquotes +cat a.tests |linux/dquotes > a.dquotes -cat a.dquotes |linux/pack > a.pack +cat a.dquotes |linux/pack > a.pack -cat a.pack |linux/survey_baremetal > a.survey +cat a.pack |linux/survey_baremetal > labels +cat a.pack |linux/labels_baremetal labels > a.survey -cat a.survey |linux/hex > a.bin +cat a.survey |linux/hex > a.bin # Create code.img containing a.bin dd if=/dev/zero of=code.img count=20160 # 512-byte sectors, so 10MB diff --git a/translate_subx_emulated b/translate_subx_emulated index 85b56436..26dd5364 100755 --- a/translate_subx_emulated +++ b/translate_subx_emulated @@ -3,27 +3,37 @@ # # This script uses emulation, so it does not require x86 or Linux. However it # is slow. +# +# A couple of gotchas: +# * Many phases here have no error-checking. Perhaps I should use a +# version of translate_subx_debug for baremetal. +# * Don't pass in numbered .subx files without translated .mu files. Our test +# harness is in test.mu, and only Mu programs can run tests in baremetal. +# +# The top level is in general not as rigorous about avoiding dependency cycles +# as the lower-level tools in linux/ set -e set -v -cat $* |linux/bootstrap/bootstrap run linux/braces > a.braces +cat $* |linux/bootstrap/bootstrap run linux/braces > a.braces -cat a.braces |linux/bootstrap/bootstrap run linux/calls > a.calls +cat a.braces |linux/bootstrap/bootstrap run linux/calls > a.calls -cat a.calls |linux/bootstrap/bootstrap run linux/sigils > a.sigils +cat a.calls |linux/bootstrap/bootstrap run linux/sigils > a.sigils -cat a.sigils |linux/bootstrap/bootstrap run linux/tests > a.tests +cat a.sigils |linux/bootstrap/bootstrap run linux/tests > a.tests # no assort since baremetal SubX doesn't have segments yet -cat a.tests |linux/bootstrap/bootstrap run linux/dquotes > a.dquotes +cat a.tests |linux/bootstrap/bootstrap run linux/dquotes > a.dquotes -cat a.dquotes |linux/bootstrap/bootstrap run linux/pack > a.pack +cat a.dquotes |linux/bootstrap/bootstrap run linux/pack > a.pack -cat a.pack |linux/bootstrap/bootstrap run linux/survey_baremetal > a.survey +cat a.pack |linux/bootstrap/bootstrap linux/survey_baremetal > labels +cat a.pack |linux/bootstrap/bootstrap linux/labels_baremetal labels > a.survey -cat a.survey |linux/bootstrap/bootstrap run linux/hex > a.bin +cat a.survey |linux/bootstrap/bootstrap run linux/hex > a.bin # Create code.img containing a.bin dd if=/dev/zero of=code.img count=20160 # 512-byte sectors, so 10MB