diff options
Diffstat (limited to 'apps/dquotes.subx')
-rw-r--r-- | apps/dquotes.subx | 1939 |
1 files changed, 0 insertions, 1939 deletions
diff --git a/apps/dquotes.subx b/apps/dquotes.subx deleted file mode 100644 index 54349e18..00000000 --- a/apps/dquotes.subx +++ /dev/null @@ -1,1939 +0,0 @@ -# Translate literal strings within double quotes. -# Replace them with references to new variables in the data segment. -# -# To run: -# $ ./bootstrap translate init.linux [01]*.subx apps/subx-params.subx apps/dquotes.subx -o apps/dquotes -# $ cat x -# == code -# ab "cd ef"/imm32 -# $ cat x |./bootstrap run apps/dquotes -# == code -# ab __string1/imm32 -# == data -# __string1: -# 5/imm32 -# 0x63/c 0x64/d 0x20/ 0x65/e 0x66/f - -== code -# instruction effective address register displacement immediate -# . op subop mod rm32 base index scale r32 -# . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes - -Entry: # run tests if necessary, convert stdin if not - # . prologue - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - - # initialize heap - # . Heap = new-segment(Heap-size) - # . . push args - 68/push Heap/imm32 - ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size - # . . call - e8/call new-segment/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - - # - if argc > 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-dquotes-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-dquotes-main:interactive/disp8 - # run-tests() - 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-dquotes-main:end/disp8 -$subx-dquotes-main:interactive: - # - otherwise convert stdin - # var ed/eax: exit-descriptor - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp - 89/copy 3/mod/direct 0/rm32/eax . . . 4/r32/esp . . # copy esp to eax - # configure ed to really exit() - # . ed->target = 0 - c7 0/subop/copy 0/mod/direct 0/rm32/eax . . . . . 0/imm32 # copy to *eax - # subx-dquotes(Stdin, Stdout, Stderr, ed) - # . . push args - 50/push-eax/ed - 68/push Stderr/imm32 - 68/push Stdout/imm32 - 68/push Stdin/imm32 - # . . call - e8/call subx-dquotes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # syscall(exit, 0) - bb/copy-to-ebx 0/imm32 -$subx-dquotes-main:end: - e8/call syscall_exit/disp32 - -# conceptual hierarchy within a line: -# line = words separated by ' ', maybe followed by comment starting with '#' -# word = datum until '/', then 0 or more metadata separated by '/' - -subx-dquotes: # in: (addr buffered-file), out: (addr buffered-file) - # pseudocode: - # var line: (stream byte 512) - # var new-data-segment-handle: (handle stream byte) - # new-stream(Heap, Segment-size, 1, new-data-segment-handle) - # var new-data-segment: (addr stream byte) = lookup(new-data-segment-handle) - # - # write(new-data-segment, "== data\n") - # # TODO: When it was originally written dquotes ran before assort, so - # # it assumes lots of segment headers, and emits a new segment of its - # # own. We've since had to reorder the phases (see the explanation - # # for a.assort2 in translate_subx). We could clean up a.assort2 if we - # # conditionally emit the previous line. But this would require - # # teaching dquotes to parse segment headers, so maybe that's not - # # best.. - # - # while true - # clear-stream(line) - # read-line-buffered(in, line) - # if (line->write == 0) break # end of file - # while true - # var word-slice = next-word-or-string(line) - # if slice-empty?(word-slice) # end of line - # break - # if slice-starts-with?(word-slice, "#") # comment - # continue - # if slice-starts-with?(word-slice, '"') # string literal <== what we're here for - # process-string-literal(word-slice, out, new-data-segment) - # else - # write-slice-buffered(out, word-slice) - # write(out, " ") - # write(out, "\n\n") - # write-stream-data(out, new-data-segment) - # flush(out) - # - # . 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/length - 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 new-data-segment-handle/edi: (handle stream byte) - 68/push 0/imm32 - 68/push 0/imm32 - 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi - # new-stream(Heap, Segment-size, 1, new-data-segment-handle) - # . . push args - 57/push-edi - 68/push 1/imm32 - ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Segment-size/disp32 # push *Segment-size - 68/push Heap/imm32 - # . . call - e8/call new-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp - # var new-data-segment/edi: (addr stream byte) = lookup(*new-data-segment-handle) - # . eax = lookup(*new-data-segment-handle) - # . . push args - ff 6/subop/push 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 . # push *(edi+4) - ff 6/subop/push 0/mod/indirect 7/rm32/edi . . . . . . # push *edi - # . . call - e8/call lookup/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . new-data-segment = eax - 89/copy 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # copy eax to edi - # write(new-data-segment, "== data\n") - # . . push args - 68/push "== data\n"/imm32 - 57/push-edi - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -$subx-dquotes: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-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 -$subx-dquotes:check0: - # if (line->write == 0) break - 81 7/subop/compare 0/mod/indirect 1/rm32/ecx . . . . . 0/imm32 # compare *ecx - 0f 84/jump-if-= $subx-dquotes:break/disp32 -$subx-dquotes:word-loop: - # next-word-or-string(line, word-slice) - # . . push args - 52/push-edx - 51/push-ecx - # . . call - e8/call next-word-or-string/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -$subx-dquotes:check1: - # 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 != false) break - 3d/compare-eax-and 0/imm32/false - 0f 85/jump-if-!= $subx-dquotes:next-line/disp32 -$subx-dquotes:check-for-comment: - # if (slice-starts-with?(word-slice, "#")) continue - # . var start/esi: (addr byte) = word-slice->start - 8b/copy 0/mod/indirect 2/rm32/edx . . . 6/r32/esi . . # copy *edx to esi - # . var c/eax: byte = *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 (c == '#') continue - 3d/compare-eax-and 0x23/imm32/hash - 74/jump-if-= $subx-dquotes:word-loop/disp8 -$subx-dquotes:check-for-string-literal: - # if (slice-starts-with?(word-slice, '"')) continue - 3d/compare-eax-and 0x22/imm32/dquote - 75/jump-if-!= $subx-dquotes:regular-word/disp8 -$subx-dquotes:string-literal: - # process-string-literal(word-slice, out, new-data-segment) - # . . push args - 57/push-edi - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - 52/push-edx - # . . call - e8/call process-string-literal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - # continue - eb/jump $subx-dquotes:next-word/disp8 -$subx-dquotes:regular-word: - # 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 - # fall through -$subx-dquotes:next-word: - # 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 - # loop - eb/jump $subx-dquotes:word-loop/disp8 -$subx-dquotes: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 $subx-dquotes:line-loop/disp32 -$subx-dquotes:break: - # write-stream-data(out, new-data-segment) - # . . push args - 57/push-edi - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-stream-data/disp32 - # . . discard args - 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) - # . . call - e8/call flush/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -$subx-dquotes:end: - # . reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x21c/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 - -# Write out 'string-literal' in a new format to 'out-segment', assign it a new -# label, and write the new label out to 'out'. -process-string-literal: # string-literal: (addr slice), out: (addr buffered-file), out-segment: (addr stream byte) - # pseudocode: - # print(out-segment, "_string#{Next-string-literal}:\n") - # emit-string-literal-data(out-segment, string-literal) - # print(out, "_string#{Next-string-literal}") - # emit-metadata(out, string-literal) - # ++ *Next-string-literal - # - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # . save registers - 51/push-ecx - # var int32-stream/ecx: (stream byte 10) # number of decimal digits a 32-bit number can have - 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0xa/imm32 # subtract from esp - 68/push 0xa/imm32/decimal-digits-in-32bit-number - 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 - # print(out-segment, "_string#{Next-string-literal}:\n") - # . write(out-segment, "_string") - # . . push args - 68/push "_string"/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write-int32-decimal(out-segment, *Next-string-literal) - # . . push args - ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-string-literal/disp32 # push *Next-string-literal - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) - # . . call - e8/call write-int32-decimal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(out-segment, ":\n") - # . . push args - 68/push ":\n"/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # emit-string-literal-data(out-segment, string-literal) - # . . push args - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) - # . . call - e8/call emit-string-literal-data/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # write(out-segment, "\n") - # . . push args - 68/push Newline/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # print(out, "_string#{Next-string-literal}") - # . write-buffered(out, "_string") - # . . push args - 68/push "_string"/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-decimal(int32-stream, *Next-string-literal) - # . . push args - ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Next-string-literal/disp32 # push *Next-string-literal - 51/push-ecx - # . . call - e8/call write-int32-decimal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write-stream-data(out, int32-stream) - # . . push args - 51/push-ecx - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call write-stream-data/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # emit-metadata(out, string-literal) - # . . push args - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - # . . call - e8/call emit-metadata/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # ++ *Next-string-literal - ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Next-string-literal/disp32 # increment *Num-test-failures -$process-string-literal:end: - # . reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x16/imm32 # add to esp - # . restore registers - 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-subx-dquotes-is-idempotent-by-default: - # . 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-input-buffered-file->buffer) - # . . push args - 68/push $_test-input-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 - # . 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 - # initialize input (meta comments in parens) - # # comment 1 - # # comment 2 indented - # == code 0x1 (new segment) - # # comment 3 inside a segment - # 1 - # (empty line) - # 2 3 # comment 4 inline with other contents - # == data 0x2 (new segment) - # 4 5/imm32 - # . write(_test-input-stream, "# comment 1\n") - # . . push args - 68/push "# comment 1\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, " # comment 2 indented\n") - # . . push args - 68/push " # comment 2 indented\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, "== code 0x1\n") - # . . push args - 68/push "== code 0x1\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, "# comment 3 inside a segment\n") - # . . push args - 68/push "# comment 3 inside a segment\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, "1\n") - # . . push args - 68/push "1\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, "\n") # empty line - # . . push args - 68/push Newline/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, "2 3 # comment 4 inline with other contents\n") - # . . push args - 68/push "2 3 # comment 4 inline with other contents\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 0x2\n") - # . . push args - 68/push "== data 0x2\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, "4 5/imm32\n") - # . . push args - 68/push "4 5/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 - # subx-dquotes(_test-input-buffered-file, _test-output-buffered-file) - # . . push args - 68/push _test-output-buffered-file/imm32 - 68/push _test-input-buffered-file/imm32 - # . . call - e8/call subx-dquotes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . 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 - # check output - # (comment dropped for now) - # (comment dropped for now) - # == code 0x1 - # (comment dropped for now) - # 1 - # (comment dropped for now) - # 2 3 - # == data 0x2 - # 4 5/imm32 - # We don't care right now what exactly happens to comments. Trailing spaces are also minor details. -#? # 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 -#? # }}} - # . check-next-stream-line-equal(_test-output-stream, "", msg) - # . . push args - 68/push "F - test-subx-dquotes-is-idempotent-by-default/0"/imm32 - 68/push ""/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, "", msg) - # . . push args - 68/push "F - test-subx-dquotes-is-idempotent-by-default/1"/imm32 - 68/push ""/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, "== code 0x1 ", msg) - # . . push args - 68/push "F - test-subx-dquotes-is-idempotent-by-default/2"/imm32 - 68/push "== code 0x1 "/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, "", msg) - # . . push args - 68/push "F - test-subx-dquotes-is-idempotent-by-default/3"/imm32 - 68/push ""/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, "1 ", msg) - # . . push args - 68/push "F - test-subx-dquotes-is-idempotent-by-default/4"/imm32 - 68/push "1 "/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, "", msg) - # . . push args - 68/push "F - test-subx-dquotes-is-idempotent-by-default/5"/imm32 - 68/push ""/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, "2 3 ", msg) - # . . push args - 68/push "F - test-subx-dquotes-is-idempotent-by-default/6"/imm32 - 68/push "2 3 "/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, "== data 0x2 ", msg) - # . . push args - 68/push "F - test-subx-dquotes-is-idempotent-by-default/7"/imm32 - 68/push "== data 0x2 "/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, "4 5/imm32 ", msg) - # . . push args - 68/push "F - test-subx-dquotes-is-idempotent-by-default/8"/imm32 - 68/push "4 5/imm32 "/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-subx-dquotes-processes-string-literals: - # . 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-input-buffered-file->buffer) - # . . push args - 68/push $_test-input-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 - # . 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 - # initialize input (meta comments in parens) - # == code (new segment) - # 1 "a"/x - # 2 "bc"/y - 68/push "== code 0x1\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, "1 \"a\"/x\n") - # . . push args - 68/push "1 \"a\"/x\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, "2 \"bc\"/y\n") - # . . push args - 68/push "2 \"bc\"/y\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 - # subx-dquotes(_test-input-buffered-file, _test-output-buffered-file) - # . . push args - 68/push _test-output-buffered-file/imm32 - 68/push _test-input-buffered-file/imm32 - # . . call - e8/call subx-dquotes/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . 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 - # check output - # == code 0x1 - # 1 _string1/x - # 2 _string2/y - # == data - # _string1: - # 1/imm32 61/a - # _string2: - # 2/imm32 62/b 63/c - # We don't care right now what exactly happens to comments. Trailing spaces are also minor details. - # - # Open question: how to make this check more robust. - # We don't actually care what the auto-generated string variables are - # called. We just want to make sure instructions using string literals - # switch to a string variable with the right value. - # (Modifying string literals completely off the radar for now.) -#? # 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, "== code 0x1 ", msg) - # . . push args - 68/push "F - test-subx-dquotes-processes-string-literals/0"/imm32 - 68/push "== code 0x1 "/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, "1 _string1/x ", msg) - # . . push args - 68/push "F - test-subx-dquotes-processes-string-literals/1"/imm32 - 68/push "1 _string1/x "/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, "2 _string2/y ", msg) - # . . push args - 68/push "F - test-subx-dquotes-processes-string-literals/2"/imm32 - 68/push "2 _string2/y "/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, "== data", msg) - # . . push args - 68/push "F - test-subx-dquotes-processes-string-literals/3"/imm32 - 68/push "== data"/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, "_string1: ", msg) - # . . push args - 68/push "F - test-subx-dquotes-processes-string-literals/4"/imm32 - 68/push "_string1:"/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, "1/imm32 61/a ", msg) - # . . push args - 68/push "F - test-subx-dquotes-processes-string-literals/5"/imm32 - 68/push "0x00000001/imm32 61/a "/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, "_string2: ", msg) - # . . push args - 68/push "F - test-subx-dquotes-processes-string-literals/6"/imm32 - 68/push "_string2:"/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, "2/imm32 62/b 63/c ", msg) - # . . push args - 68/push "F - test-subx-dquotes-processes-string-literals/7"/imm32 - 68/push "0x00000002/imm32 62/b 63/c "/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 - -# generate the data segment contents byte by byte for a given slice -emit-string-literal-data: # out: (addr stream byte), word: (addr slice) - # pseudocode - # len = string-length-at-start-of-slice(word->start, word->end) - # print(out, "#{len}/imm32 ") - # curr = word->start - # ++curr # skip '"' - # idx = 0 - # while true - # if (curr >= word->end) break - # c = *curr - # if (c == '"') break - # if (c == '\') { - # ++curr - # c = *curr - # if (c == 'n') - # c = newline - # } - # append-byte-hex(out, c) - # if c is alphanumeric: - # write(out, "/") - # append-byte(out, c) - # write(out, " ") - # ++curr - # ++idx - # if idx >= 0x40 - # idx = 0 - # write(out, "\n") - # - # . 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 - # esi = word - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # var idx/ebx: int = 0 - 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx - # var curr/edx: (addr byte) = word->start - 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx - # var max/esi: (addr byte) = word->end - 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 6/r32/esi 4/disp8 . # copy *(esi+4) to esi -$emit-string-literal-data:emit-length: - # var len/eax: int = string-length-at-start-of-slice(word->start, word->end) - # . . push args - 56/push-esi - 52/push-edx - # . . call - e8/call string-length-at-start-of-slice/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # print(out, "#{len}/imm32 ") - # . write-int32-hex(out, len) - # . . push args - 50/push-eax - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call write-int32-hex/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . write(out, "/imm32 ") - # . . push args - 68/push "/imm32 "/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -$emit-string-literal-data:loop-init: - # ++curr # skip initial '"' - 42/increment-edx - # var c/ecx: byte = 0 - 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx -$emit-string-literal-data:loop: - # if (curr >= max) break - 39/compare 3/mod/direct 2/rm32/edx . . . 6/r32/esi . . # compare edx with esi - 0f 83/jump-if-addr>= $emit-string-literal-data:end/disp32 - # CL = *curr - 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 1/r32/CL . . # copy byte at *edx to CL - # if (c == '"') break - 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x22/imm32/dquote # compare ecx - 0f 84/jump-if-= $emit-string-literal-data:end/disp32 - # if (c != '\') goto emit - 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x5c/imm32/backslash # compare ecx - 75/jump-if-!= $emit-string-literal-data:emit/disp8 - # ++curr - 42/increment-edx - # if (curr >= max) break - 39/compare 3/mod/direct 2/rm32/edx . . . 6/r32/esi . . # compare edx with esi - 0f 83/jump-if-addr>= $emit-string-literal-data:end/disp32 - # c = *curr - 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 1/r32/CL . . # copy byte at *edx to CL - # if (c == 'n') c = newline - 81 7/subop/compare 3/mod/direct 1/rm32/ecx . . . . . 0x6e/imm32/n # compare ecx - 75/jump-if-!= $emit-string-literal-data:emit/disp8 - b9/copy-to-ecx 0x0a/imm32/newline -$emit-string-literal-data:emit: - # append-byte-hex(out, CL) - # . . push args - 51/push-ecx - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call append-byte-hex/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # if (is-alphanumeric?(*curr)) print(out, "/#{*curr}") - # . var eax: boolean = is-alphanumeric?(CL) - # . . push args - 51/push-ecx - # . . call - e8/call is-alphanumeric?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - # . if (eax == false) goto char-done - 3d/compare-eax-and 0/imm32/false - 74/jump-if-= $emit-string-literal-data:char-done/disp8 - # . write(out, "/") - # . . push args - 68/push Slash/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . append-byte(out, *curr) - # . . push args - 51/push-ecx - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call append-byte/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -$emit-string-literal-data:char-done: - # write(out, " ") - # . . push args - 68/push Space/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # ++curr - 42/increment-edx - # ++ idx - 43/increment-ebx - # if (idx < 0x40) continue - 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x40/imm32 # compare ebx - 7c/jump-if-< $emit-string-literal-data:next-char/disp8 - # idx = 0 - 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx - # write(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/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -$emit-string-literal-data:next-char: - e9/jump $emit-string-literal-data:loop/disp32 -$emit-string-literal-data:end: - # . restore registers - 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 - -is-alphanumeric?: # c: int -> eax: boolean - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # eax = c - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax - # if (c < '0') return false - 3d/compare-eax-with 0x30/imm32/0 - 7c/jump-if-< $is-alphanumeric?:false/disp8 - # if (c <= '9') return true - 3d/compare-eax-with 0x39/imm32/9 - 7e/jump-if-<= $is-alphanumeric?:true/disp8 - # if (c < 'A') return false - 3d/compare-eax-with 0x41/imm32/A - 7c/jump-if-< $is-alphanumeric?:false/disp8 - # if (c <= 'Z') return true - 3d/compare-eax-with 0x5a/imm32/Z - 7e/jump-if-<= $is-alphanumeric?:true/disp8 - # if (c < 'a') return false - 3d/compare-eax-with 0x61/imm32/a - 7c/jump-if-< $is-alphanumeric?:false/disp8 - # if (c <= 'z') return true - 3d/compare-eax-with 0x7a/imm32/z - 7e/jump-if-<= $is-alphanumeric?:true/disp8 - # return false -$is-alphanumeric?:false: - b8/copy-to-eax 0/imm32/false - eb/jump $is-alphanumeric?:end/disp8 -$is-alphanumeric?:true: - b8/copy-to-eax 1/imm32/true -$is-alphanumeric?:end: - # . epilogue - 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 5d/pop-to-ebp - c3/return - -test-emit-string-literal-data: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 - # var slice/ecx = '"abc"/d' - 68/push _test-slice-abc-limit/imm32 - 68/push _test-slice-abc/imm32 - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # emit-string-literal-data(_test-output-stream, slice) - # . . push args - 51/push-ecx - 68/push _test-output-stream/imm32 - # . . call - e8/call emit-string-literal-data/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/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 -#? # }}} - # . check-stream-equal(_test-output-stream, "3/imm32 61/a 62/b 63/c ", msg) - # . . push args - 68/push "F - test-emit-string-literal-data"/imm32 - 68/push "0x00000003/imm32 61/a 62/b 63/c "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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-string-literal-data-empty: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 - # var slice/ecx = '""' - 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 - # emit-string-literal-data(_test-output-stream, slice) - # . . push args - 51/push-ecx - 68/push _test-output-stream/imm32 - # . . call - e8/call emit-string-literal-data/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/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 -#? # }}} - # . check-stream-equal(_test-output-stream, "0/imm32 ", msg) - # . . push args - 68/push "F - test-emit-string-literal-data-empty"/imm32 - 68/push "0x00000000/imm32 "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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 - -# just to keep things simple -test-emit-string-literal-data-no-metadata-for-non-alphanumerics: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 - # var slice/ecx = '"a b"' - 68/push _test-slice-a-space-b-limit/imm32 - 68/push _test-slice-a-space-b/imm32 - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # emit-string-literal-data(_test-output-stream, slice) - # . . push args - 51/push-ecx - 68/push _test-output-stream/imm32 - # . . call - e8/call emit-string-literal-data/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/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 -#? # }}} - # . check-stream-equal(_test-output-stream, "3/imm32 61/a 20 62/b ", msg) # ideally we'd like to say '20/space' but that requires managing names for codepoints - # . . push args - 68/push "F - test-emit-string-literal-data-no-metadata-for-non-alphanumerics"/imm32 - 68/push "0x00000003/imm32 61/a 20 62/b "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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-string-literal-data-handles-escape-sequences: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 - # var slice/ecx = '"a\"b"' - 68/push _test-slice-a-dquote-b-limit/imm32 - 68/push _test-slice-a-dquote-b/imm32 - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # emit-string-literal-data(_test-output-stream, slice) - # . . push args - 51/push-ecx - 68/push _test-output-stream/imm32 - # . . call - e8/call emit-string-literal-data/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/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 -#? # }}} - # . check-stream-equal(_test-output-stream, "3/imm32 61/a 22 62/b ", msg) - # . . push args - 68/push "F - test-emit-string-literal-data-handles-escape-sequences"/imm32 - 68/push "0x00000003/imm32 61/a 22 62/b "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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-string-literal-data-handles-newline-escape: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 - # var slice/ecx = '"a\nb"' - 68/push _test-slice-a-newline-b-limit/imm32 - 68/push _test-slice-a-newline-b/imm32 - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # emit-string-literal-data(_test-output-stream, slice) - # . . push args - 51/push-ecx - 68/push _test-output-stream/imm32 - # . . call - e8/call emit-string-literal-data/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/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 -#? # }}} - # . check-stream-equal(_test-output-stream, "3/imm32 61/a 0a 62/b ", msg) - # . . push args - 68/push "F - test-emit-string-literal-data-handles-newline-escape"/imm32 - 68/push "0x00000003/imm32 61/a 0a 62/b "/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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 - -# emit everything from a word except the initial datum -emit-metadata: # out: (addr buffered-file), word: (addr slice) - # pseudocode - # var slice: slice = {0, word->end} - # curr = word->start - # if *curr == '"' - # curr = skip-string-in-slice(curr, word->end) - # else - # while true - # if curr == word->end - # return - # if *curr == '/' - # break - # ++curr - # slice->start = curr - # write-slice-buffered(out, slice) - # - # . 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 - # esi = word - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi - # var curr/ecx: (addr byte) = word->start - 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx - # var end/edx: (addr byte) = word->end - 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 4/disp8 . # copy *(esi+4) to edx - # var slice/ebx: slice = {0, end} - 52/push-edx - 68/push 0/imm32 - 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx - # eax = 0 - b8/copy-to-eax 0/imm32 -$emit-metadata:check-for-string-literal: - # - if (*curr == '"') curr = skip-string-in-slice(curr, end) - 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL - 3d/compare-eax-and 0x22/imm32/dquote - 75/jump-if-!= $emit-metadata:skip-datum-loop/disp8 -$emit-metadata:skip-string-literal: - # . eax = skip-string-in-slice(curr, end) - # . . push args - 52/push-edx - 51/push-ecx - # . . call - e8/call skip-string-in-slice/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # . curr = eax - 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx - eb/jump $emit-metadata:emit/disp8 -$emit-metadata:skip-datum-loop: - # - otherwise scan for '/' - # if (curr == end) return - 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx and edx - 74/jump-if-= $emit-metadata:end/disp8 - # if (*curr == '/') break - 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL - 3d/compare-eax-and 0x2f/imm32/slash - 74/jump-if-= $emit-metadata:emit/disp8 - # ++curr - 41/increment-ecx - eb/jump $emit-metadata:skip-datum-loop/disp8 -$emit-metadata:emit: - # slice->start = ecx - 89/copy 0/mod/indirect 3/rm32/ebx . . . 1/r32/ecx . . # copy ecx to *ebx - # write-slice-buffered(out, slice) - # . . push args - 53/push-ebx - ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - # . . call - e8/call write-slice-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . 8/imm32 . # add to esp -$emit-metadata:end: - # . reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . 8/imm32 . # add to esp - # . restore registers - 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 - -test-emit-metadata: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 - # (eax..ecx) = "abc/def" - b8/copy-to-eax "abc/def"/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 slice/ecx = {eax, ecx} - 51/push-ecx - 50/push-eax - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # emit-metadata(_test-output-buffered-file, slice) - # . . push args - 51/push-ecx - 68/push _test-output-buffered-file/imm32 - # . . call - e8/call emit-metadata/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # 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 - # check-stream-equal(_test-output-stream, "/def", msg) # important that there's no leading space - # . . push args - 68/push "F - test-emit-metadata"/imm32 - 68/push "/def"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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-metadata-none: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 - # (eax..ecx) = "abc" - b8/copy-to-eax "abc"/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 slice/ecx = {eax, ecx} - 51/push-ecx - 50/push-eax - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # emit-metadata(_test-output-buffered-file, slice) - # . . push args - 51/push-ecx - 68/push _test-output-buffered-file/imm32 - # . . call - e8/call emit-metadata/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # 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 - # check-stream-equal(_test-output-stream, "", msg) - # . . push args - 68/push "F - test-emit-metadata-none"/imm32 - 68/push ""/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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-metadata-multiple: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 - # (eax..ecx) = "abc/def/ghi" - b8/copy-to-eax "abc/def/ghi"/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 slice/ecx = {eax, ecx} - 51/push-ecx - 50/push-eax - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # emit-metadata(_test-output-buffered-file, slice) - # . . push args - 51/push-ecx - 68/push _test-output-buffered-file/imm32 - # . . call - e8/call emit-metadata/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # 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 - # check-stream-equal(_test-output-stream, "/def/ghi", msg) # important that there's no leading space - # . . push args - 68/push "F - test-emit-metadata-multiple"/imm32 - 68/push "/def/ghi"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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-metadata-when-no-datum: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 slice/ecx = "/abc" - b8/copy-to-eax "/abc"/imm32 - # . push end/ecx - 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 - 51/push-ecx - # . push curr/eax - 05/add-to-eax 4/imm32 - 50/push-eax - # . save stack pointer - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # emit-metadata(_test-output-buffered-file, slice) - # . . push args - 51/push-ecx - 68/push _test-output-buffered-file/imm32 - # . . call - e8/call emit-metadata/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # 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 - # check-stream-equal(_test-output-stream, "/abc", msg) # nothing skipped - # . . push args - 68/push "F - test-emit-metadata-when-no-datum"/imm32 - 68/push "/abc"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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-metadata-in-string-literal: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup - # . 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 slice/ecx = "\"abc/def\"/ghi" - 68/push _test-slice-literal-string-with-limit/imm32 - 68/push _test-slice-literal-string/imm32/start - 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - # emit-metadata(_test-output-buffered-file, slice) - # . . push args - 51/push-ecx - 68/push _test-output-buffered-file/imm32 - # . . call - e8/call emit-metadata/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # 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 -#? # }}} - # check-stream-equal(_test-output-stream, "/ghi", msg) # important that there's no leading space - # . . push args - 68/push "F - test-emit-metadata-in-string-literal"/imm32 - 68/push "/ghi"/imm32 - 68/push _test-output-stream/imm32 - # . . call - e8/call check-stream-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 - -string-length-at-start-of-slice: # curr: (addr byte), end: (addr byte) -> length/eax - # . 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 - # ecx = curr - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx - # edx = end - 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx - # var length/eax: int = 0 - 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - # var c/ebx: byte = 0 - 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx - # skip initial dquote - 41/increment-ecx -$string-length-at-start-of-slice:loop: - # if (curr >= end) return length - 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx - 73/jump-if-addr>= $string-length-at-start-of-slice:end/disp8 - # c = *curr - 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 3/r32/BL . . # copy byte at *ecx to BL -$string-length-at-start-of-slice:dquote: - # if (c == '"') break - 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x22/imm32/dquote # compare ebx - 74/jump-if-= $string-length-at-start-of-slice:end/disp8 -$string-length-at-start-of-slice:check-for-escape: - # if (c == '\') escape next char - 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x5c/imm32/backslash # compare ebx - 75/jump-if-!= $string-length-at-start-of-slice:continue/disp8 -$string-length-at-start-of-slice:escape: - # increment curr but not result - 41/increment-ecx -$string-length-at-start-of-slice:continue: - # ++result - 40/increment-eax - # ++curr - 41/increment-ecx - eb/jump $string-length-at-start-of-slice:loop/disp8 -$string-length-at-start-of-slice:end: - # . 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-string-length-at-start-of-slice: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup: (eax..ecx) = "\"abc\" def" - b8/copy-to-eax "\"abc\" def"/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 - # eax = string-length-at-start-of-slice(eax, ecx) - # . . push args - 51/push-ecx - 50/push-eax - # . . call - e8/call string-length-at-start-of-slice/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # check-ints-equal(eax, 3, msg) - # . . push args - 68/push "F - test-string-length-at-start-of-slice"/imm32 - 68/push 3/imm32 - 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-string-length-at-start-of-slice-escaped: - # . prologue - 55/push-ebp - 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - # setup: (eax..ecx) = "\"ab\\c\" def" - b8/copy-to-eax "\"ab\\c\" def"/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 - # eax = string-length-at-start-of-slice(eax, ecx) - # . . push args - 51/push-ecx - 50/push-eax - # . . call - e8/call string-length-at-start-of-slice/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - # check-ints-equal(eax, 3, msg) - # . . push args - 68/push "F - test-string-length-at-start-of-slice-escaped"/imm32 - 68/push 3/imm32 - 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 - -== data - -Next-string-literal: # tracks the next auto-generated variable name - 1/imm32 - -_test-slice-abc: - 22/dquote 61/a 62/b 63/c 22/dquote # "abc" - 2f/slash 64/d -_test-slice-abc-limit: - -_test-slice-a-space-b: - 22/dquote 61/a 20/space 62/b 22/dquote # "a b" -_test-slice-a-space-b-limit: - -_test-slice-a-dquote-b: - 22/dquote 61/a 5c/backslash 22/dquote 62/b 22/dquote # "a\"b" -_test-slice-a-dquote-b-limit: - -_test-slice-a-newline-b: - 22/dquote 61/a 5c/backslash 6e/n 62/b 22/dquote # "a\nb" -_test-slice-a-newline-b-limit: - -# "abc/def"/ghi -_test-slice-literal-string: - 22/dquote - 61/a 62/b 63/c # abc - 2f/slash 64/d 65/e 66/f # /def - 22/dquote - 2f/slash 67/g 68/h 69/i # /ghi -_test-slice-literal-string-with-limit: - -# . . vim:nowrap:textwidth=0 |