From 31cb01daf4c481736e151dde88d1ec55005f6347 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 19 Jul 2019 11:29:52 -0700 Subject: 5419 Bugfix fourteen: we need different address computation logic for code vs data labels. It's really about different categories of instructions having different address computation logic. This subtle distinction will make good error messages hard. But that's a problem for later. Now there's just one example program not translating. --- subx/apps/survey | Bin 41174 -> 42791 bytes subx/apps/survey.subx | 582 +++++++++++++++++++++++++++++++++++++++++++++++--- subx/test_apps | 10 +- 3 files changed, 552 insertions(+), 40 deletions(-) diff --git a/subx/apps/survey b/subx/apps/survey index 61e2f974..b7bd7dd3 100755 Binary files a/subx/apps/survey and b/subx/apps/survey differ diff --git a/subx/apps/survey.subx b/subx/apps/survey.subx index f25c62d2..79fddc53 100644 --- a/subx/apps/survey.subx +++ b/subx/apps/survey.subx @@ -31,6 +31,10 @@ # ee nn nn nn nn # some computed address # # ELF header above will specify that data segment begins at this offset # 00 +# +# The ELF format has some persnickety constraints on the starting addresses of +# segments, so input headers are treated as guidelines and adjusted in the +# output. == code # instruction effective address register displacement immediate @@ -1783,7 +1787,14 @@ emit-segments: # in : (address stream), out : (address buffered-file), segments # continue # datum = next-token-from-slice(word-slice->start, word-slice->end, "/") # info = get-slice(labels, datum) - # if has-metadata?(word-slice, "imm8") + # if !string-equal?(info->segment-name, "code") + # if has-metadata?(word-slice, "disp8") + # abort + # if has-metadata?(word-slice, "imm8") + # abort + # emit(out, info->address, 4) # global variables always translate to absolute addresses + # # code segment cases + # else if has-metadata?(word-slice, "imm8") # abort # label should never go to imm8 # else if has-metadata?(word-slice, "imm32") # emit(out, info->address, 4) @@ -1880,7 +1891,7 @@ $emit-segments:line-loop: #? # . . discard args #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP #? # }}} -$emit-segments:check0: +$emit-segments: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-equal $emit-segments:end/disp32 @@ -1936,7 +1947,7 @@ $emit-segments:word-loop: #? # . . discard args #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP #? # }}} -$emit-segments:check1: +$emit-segments:check-for-end-of-line: # if (slice-empty?(word-slice)) break # . EAX = slice-empty?(word-slice) # . . push args @@ -2066,7 +2077,84 @@ $emit-segments:check-metadata: 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP # . ESI = EAX 89/copy 3/mod/direct 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to ESI -$emit-segments:check-for-imm8: +$emit-segments:check-global-variable: +#? # dump info->segment-name {{{ +#? # . write(2/stderr, "aa: label segment: ") +#? # . . push args +#? 68/push "aa: label segment: "/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(2/stderr, info->segment-name) +#? # . . push args +#? ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +#? 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(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 +#? # }}} + # if string-equal?(info->segment-name, "code") goto code label checks + # . EAX = string-equal?(info->segment-name, "code") + # . . push args + 68/push "code"/imm32 + ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI + # . . call + e8/call string-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . if (EAX != 0) goto code label checks + 3d/compare-EAX-and 0/imm32 + 0f 85/jump-if-not-equal $emit-segments:check-code-label-for-imm8/disp32 +$emit-segments:check-global-variable-for-disp8: + # if has-metadata?(word-slice, "disp8") abort + # . EAX = has-metadata?(word-slice, "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 != 0) abort + 3d/compare-EAX-and 0/imm32 + 0f 85/jump-if-not-equal $emit-segments:global-variable-abort/disp32 +$emit-segments:check-global-variable-for-imm8: + # if has-metadata?(word-slice, "imm8") abort + # . EAX = has-metadata?(word-slice, "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 != 0) abort + 3d/compare-EAX-and 0/imm32 + 0f 85/jump-if-not-equal $emit-segments:global-variable-abort/disp32 +$emit-segments:emit-global-variable: + # emit-hex(out, info->address, 4) + # . . push args + 68/push 4/imm32 + ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 8/disp8 . # push *(ESI+8) + 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-segments:word-loop/disp32 +$emit-segments:check-code-label-for-imm8: # if (has-metadata?(word-slice, "imm8")) abort # . EAX = has-metadata?(EDX, "imm8") # . . push args @@ -2079,7 +2167,7 @@ $emit-segments:check-for-imm8: # . if (EAX != 0) abort 3d/compare-EAX-and 0/imm32 0f 85/jump-if-not-equal $emit-segments:imm8-abort/disp32 -$emit-segments:check-for-imm32: +$emit-segments:check-code-label-for-imm32: # if (!has-metadata?(word-slice, "imm32")) goto next check # . EAX = has-metadata?(EDX, "imm32") # . . push args @@ -2091,7 +2179,7 @@ $emit-segments:check-for-imm32: 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # . if (EAX == 0) goto next check 3d/compare-EAX-and 0/imm32 - 74/jump-if-equal $emit-segments:check-for-disp8/disp8 + 74/jump-if-equal $emit-segments:check-code-label-for-disp8/disp8 #? # dump info->address {{{ #? # . write(2/stderr, "info->address: ") #? # . . push args @@ -2125,6 +2213,7 @@ $emit-segments:check-for-imm32: #? # . . discard args #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP #? # }}} +$emit-segments:emit-code-label-imm32: # emit-hex(out, info->address, 4) # . . push args 68/push 4/imm32 @@ -2136,7 +2225,7 @@ $emit-segments:check-for-imm32: 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP # continue e9/jump $emit-segments:word-loop/disp32 -$emit-segments:check-for-disp8: +$emit-segments:check-code-label-for-disp8: # if (!has-metadata?(word-slice, "disp8")) goto next check # . EAX = has-metadata?(EDX, "disp8") # . . push args @@ -2148,7 +2237,8 @@ $emit-segments:check-for-disp8: 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # . if (EAX == 0) goto next check 3d/compare-EAX-and 0/imm32 - 74/jump-if-equal $emit-segments:check-for-disp32/disp8 + 74/jump-if-equal $emit-segments:check-code-label-for-disp32/disp8 +$emit-segments:emit-code-label-disp8: # emit-hex(out, info->offset - offset-of-next-instruction, 1) # . . push args 68/push 1/imm32 @@ -2162,7 +2252,7 @@ $emit-segments:check-for-disp8: 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP # continue e9/jump $emit-segments:word-loop/disp32 -$emit-segments:check-for-disp32: +$emit-segments:check-code-label-for-disp32: # if (!has-metadata?(word-slice, "disp32")) abort # . EAX = has-metadata?(EDX, "disp32") # . . push args @@ -2174,7 +2264,8 @@ $emit-segments:check-for-disp32: 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # . if (EAX == 0) abort 3d/compare-EAX-and 0/imm32 - 74/jump-if-equal $emit-segments:abort/disp8 + 0f 84/jump-if-equal $emit-segments:abort/disp32 +$emit-segments:emit-code-label-disp32: # emit-hex(out, info->offset - offset-of-next-instruction, 4) # . . push args 68/push 4/imm32 @@ -2214,10 +2305,25 @@ $emit-segments:end: 5d/pop-to-EBP c3/return +$emit-segments:global-variable-abort: + # . _write(2/stderr, error) + # . . push args + 68/push "emit-segments: must refer to global variables with /disp32 or /imm32"/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 + b8/copy-to-EAX 1/imm32/exit + cd/syscall 0x80/imm8 + # never gets here + $emit-segments:imm8-abort: # . _write(2/stderr, error) # . . push args - 68/push "emit-segments: unexpected /imm8"/imm32 + 68/push "emit-segments: cannot refer to code labels with /imm8"/imm32 68/push 2/imm32/stderr # . . call e8/call _write/disp32 @@ -2260,21 +2366,22 @@ $emit-segments:abort: cd/syscall 0x80/imm8 # never gets here -test-emit-segments: +test-emit-segments-global-variable: + # global variables always convert to absolute addresses, regardless of metadata + # # input: # in: # == code 0x1000 # ab cd ef gh - # ij x/imm32 + # ij x/disp32 # == data 0x2000 # 00 # x: # 34 # segments: - # - 'code': {0x1074, 0, 5} - # - 'data': {0x2079, 5, 1} + # - 'code': {0x1074, 0, 9} + # - 'data': {0x2079, 5, 2} # labels: - # - 'l1': {'code', 3, 0x1077} # - 'x': {'data', 1, 0x207a} # # output: @@ -2339,9 +2446,9 @@ test-emit-segments: 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/imm32\n") + # . write(_test-input-stream, "ij x/disp32\n") # . . push args - 68/push "ij x/imm32\n"/imm32 + 68/push "ij x/disp32\n"/imm32 68/push _test-input-stream/imm32 # . . call e8/call write/disp32 @@ -2379,8 +2486,8 @@ test-emit-segments: e8/call write/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # . stream-add4(segments, "code", 0x1074, 0, 5) - 68/push 5/imm32/segment-size + # . stream-add4(segments, "code", 0x1074, 0, 9) + 68/push 9/imm32/segment-size 68/push 0/imm32/file-offset 68/push 0x1074/imm32/start-address 68/push "code"/imm32/segment-name @@ -2389,7 +2496,7 @@ test-emit-segments: e8/call stream-add4/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP - # . stream-add4(segments, "data", 0x2079, 5, 1) + # . stream-add4(segments, "data", 0x2079, 5, 2) 68/push 1/imm32/segment-size 68/push 5/imm32/file-offset 68/push 0x2079/imm32/start-address @@ -2399,16 +2506,6 @@ test-emit-segments: e8/call stream-add4/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP - # . stream-add4(labels, "l1", "code", 3, 0x1077) - 68/push 0x1077/imm32/label-address - 68/push 3/imm32/segment-offset - 68/push "code"/imm32/segment-name - 68/push "l1"/imm32/label-name - 52/push-EDX - # . . call - e8/call stream-add4/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP # . stream-add4(labels, "x", "data", 1, 0x207a) 68/push 0x207a/imm32/label-address 68/push 1/imm32/segment-offset @@ -2431,6 +2528,13 @@ test-emit-segments: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/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 @@ -2466,7 +2570,7 @@ test-emit-segments: #? # }}} # . check-next-stream-line-equal(_test-output-stream, "ab cd ef gh ", msg) # . . push args - 68/push "F - test-emit-segments/0"/imm32 + 68/push "F - test-emit-segments-global-variable/0"/imm32 68/push "ab cd ef gh "/imm32 68/push _test-output-stream/imm32 # . . call @@ -2475,7 +2579,7 @@ test-emit-segments: 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP # . check-next-stream-line-equal(_test-output-stream, "ij 7a 20 00 00 ", msg) # . . push args - 68/push "F - test-emit-segments/1"/imm32 + 68/push "F - test-emit-segments-global-variable/1"/imm32 68/push "ij 7a 20 00 00 "/imm32 68/push _test-output-stream/imm32 # . . call @@ -2484,7 +2588,7 @@ test-emit-segments: 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-segments/2"/imm32 + 68/push "F - test-emit-segments-global-variable/2"/imm32 68/push "00 "/imm32 68/push _test-output-stream/imm32 # . . call @@ -2493,7 +2597,7 @@ test-emit-segments: 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-segments/3"/imm32 + 68/push "F - test-emit-segments-global-variable/3"/imm32 68/push "34 "/imm32 68/push _test-output-stream/imm32 # . . call @@ -2505,6 +2609,414 @@ test-emit-segments: 5d/pop-to-EBP c3/return +test-emit-segments-code-label: + # labels usually convert to displacements + # + # input: + # in: + # == code 0x1000 + # ab cd + # l1: + # ef gh + # ij l1/disp32 + # segments: + # - 'code': {0x1054, 0, 9} + # labels: + # - 'l1': {'code', 2, 0x1056} + # + # output: + # ab cd + # ef gh + # ij f9 ff ff ff # -7 + # + # . prolog + 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+4) + # . . push args + b8/copy-to-EAX _test-output-buffered-file/imm32 + 05/add-to-EAX 4/imm32 + 50/push-EAX + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # . var segments/ECX = stream(10 * 16) + 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0xa0/imm32 # subtract from ESP + 68/push 0xa0/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 labels/EDX = stream(512 * 16) + 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x2000/imm32 # subtract from ESP + 68/push 0x2000/imm32/length + 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 + # initialize input + # . write(_test-input-stream, "== code 0x1000\n") + # . . push args + 68/push "== code 0x1000\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, "l1:\n") + # . . push args + 68/push "l1:\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/disp32\n") + # . . push args + 68/push " ij 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-add4(segments, "code", 0x1054, 0, 9) + 68/push 9/imm32/segment-size + 68/push 0/imm32/file-offset + 68/push 0x1054/imm32/start-address + 68/push "code"/imm32/segment-name + 51/push-ECX + # . . call + e8/call stream-add4/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP + # . stream-add4(labels, "l1", "code", 2, 0x1056) + 68/push 0x1056/imm32/label-address + 68/push 2/imm32/segment-offset + 68/push "code"/imm32/segment-name + 68/push "l1"/imm32/label-name + 52/push-EDX + # . . call + e8/call stream-add4/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP + # component under test + # . emit-segments(_test-input-stream, _test-output-buffered-file, segments, labels) + # . . push args + 52/push-EDX + 51/push-ECX + 68/push _test-output-buffered-file/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call emit-segments/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/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, "ab cd ", msg) + # . . push args + 68/push "F - test-emit-segments-code-label/0"/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-segments-code-label/1"/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-segments-code-label/2"/imm32 + 68/push "ij f9 ff ff ff "/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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-emit-segments-code-label-absolute: + # labels can also convert to absolute addresses + # + # input: + # in: + # == code 0x1000 + # ab cd + # l1: + # ef gh + # ij l1/imm32 + # segments: + # - 'code': {0x1054, 0, 9} + # labels: + # - 'l1': {'code', 2, 0x1056} + # + # output: + # ab cd + # ef gh + # ij 56 10 00 00 + # + # . prolog + 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+4) + # . . push args + b8/copy-to-EAX _test-output-buffered-file/imm32 + 05/add-to-EAX 4/imm32 + 50/push-EAX + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # . var segments/ECX = stream(10 * 16) + 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0xa0/imm32 # subtract from ESP + 68/push 0xa0/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 labels/EDX = stream(512 * 16) + 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x2000/imm32 # subtract from ESP + 68/push 0x2000/imm32/length + 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 + # initialize input + # . write(_test-input-stream, "== code 0x1000\n") + # . . push args + 68/push "== code 0x1000\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, "l1:\n") + # . . push args + 68/push "l1:\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-add4(segments, "code", 0x1054, 0, 9) + 68/push 9/imm32/segment-size + 68/push 0/imm32/file-offset + 68/push 0x1054/imm32/start-address + 68/push "code"/imm32/segment-name + 51/push-ECX + # . . call + e8/call stream-add4/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP + # . stream-add4(labels, "l1", "code", 2, 0x1056) + 68/push 0x1056/imm32/label-address + 68/push 2/imm32/segment-offset + 68/push "code"/imm32/segment-name + 68/push "l1"/imm32/label-name + 52/push-EDX + # . . call + e8/call stream-add4/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP + # component under test + # . emit-segments(_test-input-stream, _test-output-buffered-file, segments, labels) + # . . push args + 52/push-EDX + 51/push-ECX + 68/push _test-output-buffered-file/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call emit-segments/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/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, "ab cd ", msg) + # . . push args + 68/push "F - test-emit-segments-code-label-absolute/0"/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-segments-code-label-absolute/1"/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-segments-code-label-absolute/2"/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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + emit-headers: # out : (address buffered-file), segments : (address stream {string, segment-info}), labels : (address stream {string, label-info}) # pseudocode: # emit-elf-header(out, segments, labels) diff --git a/subx/test_apps b/subx/test_apps index cc0f301f..e9d75364 100755 --- a/subx/test_apps +++ b/subx/test_apps @@ -258,11 +258,11 @@ test `uname` = 'Linux' && { cat examples/ex5.subx |apps/dquotes |apps/assort |apps/pack |apps/survey |apps/hex |diff examples/ex5 - } -#? echo ex6 -#? cat examples/ex6.subx |./subx_bin run apps/dquotes |./subx_bin run apps/assort |./subx_bin run apps/pack |./subx_bin run apps/survey |./subx_bin run apps/hex |diff examples/ex6 - -#? test `uname` = 'Linux' && { -#? cat examples/ex6.subx |apps/dquotes |apps/assort |apps/pack |apps/survey |apps/hex |diff examples/ex6 - -#? } +echo ex6 +cat examples/ex6.subx |./subx_bin run apps/dquotes |./subx_bin run apps/assort |./subx_bin run apps/pack |./subx_bin run apps/survey |./subx_bin run apps/hex |diff examples/ex6 - +test `uname` = 'Linux' && { + cat examples/ex6.subx |apps/dquotes |apps/assort |apps/pack |apps/survey |apps/hex |diff examples/ex6 - +} echo ex7 cat examples/ex7.subx |./subx_bin run apps/dquotes |./subx_bin run apps/assort |./subx_bin run apps/pack |./subx_bin run apps/survey |./subx_bin run apps/hex |diff examples/ex7 - -- cgit 1.4.1-2-gfad0