diff options
Diffstat (limited to 'subx/apps')
-rwxr-xr-x | subx/apps/crenshaw2-1 | bin | 17833 -> 17583 bytes | |||
-rwxr-xr-x | subx/apps/crenshaw2-1b | bin | 18392 -> 18142 bytes | |||
-rwxr-xr-x | subx/apps/factorial | bin | 16751 -> 16501 bytes | |||
-rwxr-xr-x | subx/apps/handle | bin | 17526 -> 17276 bytes | |||
-rwxr-xr-x | subx/apps/hex | bin | 20812 -> 20562 bytes | |||
-rwxr-xr-x | subx/apps/pack | bin | 34859 -> 35117 bytes | |||
-rw-r--r-- | subx/apps/pack.subx | 306 |
7 files changed, 266 insertions, 40 deletions
diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1 index 98669c9b..0d625f1d 100755 --- a/subx/apps/crenshaw2-1 +++ b/subx/apps/crenshaw2-1 Binary files differdiff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b index cd7739b8..f693a204 100755 --- a/subx/apps/crenshaw2-1b +++ b/subx/apps/crenshaw2-1b Binary files differdiff --git a/subx/apps/factorial b/subx/apps/factorial index 9e6f96f7..97014e36 100755 --- a/subx/apps/factorial +++ b/subx/apps/factorial Binary files differdiff --git a/subx/apps/handle b/subx/apps/handle index 1726afaa..c484fb0b 100755 --- a/subx/apps/handle +++ b/subx/apps/handle Binary files differdiff --git a/subx/apps/hex b/subx/apps/hex index 6d1e57bf..bfbdc771 100755 --- a/subx/apps/hex +++ b/subx/apps/hex Binary files differdiff --git a/subx/apps/pack b/subx/apps/pack index b3a20354..d81654aa 100755 --- a/subx/apps/pack +++ b/subx/apps/pack Binary files differdiff --git a/subx/apps/pack.subx b/subx/apps/pack.subx index 4fff835c..db0c9e7d 100644 --- a/subx/apps/pack.subx +++ b/subx/apps/pack.subx @@ -22,7 +22,7 @@ Entry: # run tests if necessary, convert stdin if not # for debugging: run a single test -#? e8/call test-convert-instruction-handles-disp8-name/disp32 +#? e8/call test-convert-data-trailing-comment/disp32 #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX #? eb/jump $main:end/disp8 @@ -101,11 +101,11 @@ convert: # in : (address buffered-file), out : (address buffered-file) -> <void # if (line->write == 0) break # end of file # var word-slice = next-word(line) # if slice-empty?(word-slice) # whitespace - # write-stream-buffered(out, line) + # write-stream-data(out, line) # else if (slice-equal?(word-slice, "==")) # word-slice = next-word(line) # in-code? = slice-equal?(word-slice, "code") - # write-stream-buffered(out, line) + # write-stream-data(out, line) # else if (in-code?) # rewind-stream(line) # convert-instruction(line, out) @@ -198,7 +198,7 @@ $convert:check0: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP $convert:check1: - # if (slice-empty?(word-slice)) write-stream-buffered(out, line) + # if (slice-empty?(word-slice)) write-stream-data(out, line) # . EAX = slice-empty?(word-slice) # . . push args 52/push-EDX @@ -206,7 +206,7 @@ $convert:check1: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # . if (EAX != 0) write-stream-buffered(out, line) + # . if (EAX != 0) write-stream-data(out, line) 3d/compare-EAX-and 0/imm32 0f 85/jump-if-not-equal $convert:pass-through/disp32 $convert:check2: @@ -263,7 +263,7 @@ $convert:check2: # if (slice-equal?(word-slice, "==")) # word-slice = next-word(line) # in-code? = slice-equal?(word-slice, "code") - # write-stream-buffered(out, line) + # write-stream-data(out, line) # . EAX = slice-equal?(word-slice, "==") # . . push args 68/push "=="/imm32 @@ -380,12 +380,12 @@ $convert:data: # . loop e9/jump $convert:loop/disp32 $convert:pass-through: - # write-stream-buffered(out, line) + # write-stream-data(out, line) # . . 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-buffered/disp32 + e8/call write-stream-data/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # . loop @@ -1043,10 +1043,10 @@ convert-data: # line : (address stream byte), out : (address buffered-file) -> # if slice-empty?(word-slice) # end of file (maybe including trailing whitespace) # break # skip emitting some whitespace # if slice-starts-with?(word-slice, "#") # comment - # write-stream-buffered(out, line) + # write-slice(out, word-slice) # break # if slice-ends-with?(word-slice, ":") # label - # write-stream-buffered(out, line) + # write-stream-data(out, line) # break # if has-metadata?(word-slice, "imm32") # emit(out, word-slice, 4) @@ -1167,30 +1167,52 @@ $convert-data:check0: e8/call slice-empty?/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # . if (EAX != 0) pass through + # . if (EAX != 0) break 3d/compare-EAX-and 0/imm32 - 75/jump-if-not-equal $convert-data:break/disp8 -$convert-data:check1: - # if (slice-starts-with?(word-slice, "#")) write-stream-buffered(out, line) + 0f 85/jump-if-not-equal $convert-data:break/disp32 +$convert-data:check-for-comment: + # if (slice-starts-with?(word-slice, "#")) # . start/EDX = word-slice->start 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX # . c/EAX = *start 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL - # . if (EAX == '#') pass through + # . if (EAX != '#') goto next check 3d/compare-EAX-and 0x23/imm32/hash - 74/jump-if-equal $convert-data:pass-line-through/disp8 -$convert-data:check2: - # if (slice-ends-with?(word-slice, ":")) write-stream-buffered(out, line) + 75/jump-if-not-equal $convert-data:check-for-label/disp8 +$convert-data:comment: + # write-slice(out, word-slice) + # . . push args + 51/push-ECX + ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + # . . call + e8/call write-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # break + 75/jump-if-not-equal $convert-data:break/disp8 +$convert-data:check-for-label: + # if (slice-ends-with?(word-slice, ":")) # . end/EDX = word-slice->end 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX # . c/EAX = *(end-1) 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX 8a/copy-byte 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/AL -1/disp8 . # copy byte at *ECX to AL - # . if (EAX == ':') pass through + # . if (EAX != ':') goto next check 3d/compare-EAX-and 0x3a/imm32/colon - 74/jump-if-equal $convert-data:pass-line-through/disp8 -$convert-data:check3: + 75/jump-if-not-equal $convert-data:check-for-imm32/disp8 +$convert-data:label: + # write-stream-data(out, line) + # . . 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 write-stream-data/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # break + 75/jump-if-not-equal $convert-data:break/disp8 +$convert-data:check-for-imm32: # if (has-metadata?(word-slice, "imm32")) # . EAX = has-metadata?(ECX, "imm32") # . . push args @@ -1225,16 +1247,6 @@ $convert-data:single-byte: # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP e9/jump $convert-data:loop/disp32 -$convert-data:pass-line-through: - # write-stream-buffered(out, line) - # . . 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 write-stream-buffered/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # break $convert-data:break: $convert-data:end: # . reclaim locals @@ -1828,6 +1840,108 @@ test-convert-data-multiple-words: 5d/pop-to-EBP c3/return +test-convert-data-trailing-comment: + # Trailing comments in data segment get appropriately ignored. + # . 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 + # initialize input + # . write(_test-input-stream, "30/imm32 # comment") + # . . push args + 68/push "30/imm32 # comment"/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 + # convert-data(_test-input-stream, _test-output-buffered-file) + # . . push args + 68/push _test-output-buffered-file/imm32 + 68/push _test-input-stream/imm32 + # . . call + e8/call convert-data/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # check output + # . 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, "^") +#? # . . push args +#? 68/push "^"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +#? # . write-stream(2/stderr, _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, "$") +#? # . . push args +#? 68/push "$"/imm32 +#? 68/push 2/imm32/stderr +#? # . . call +#? e8/call write/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +#? # . write(2/stderr, "\n") +#? # . . push args +#? 68/push Newline/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, "30 00 00 00 # comment", msg) + # . . push args + 68/push "F - test-convert-data-trailing-comment"/imm32 + 68/push "30 00 00 00 # comment"/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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + # pack an instruction, following the C++ version # # zero error handling at the moment (continuing to rely on the C++ version for that): @@ -1843,13 +1957,13 @@ convert-instruction: # line : (address stream byte), out : (address buffered-fi # # some early exits # var word-slice = next-word(line) # if slice-empty?(word-slice) - # write-stream-buffered(out, line) + # write-stream-data(out, line) # return # if slice-starts-with?(word-slice, "#") - # write-stream-buffered(out, line) + # write-stream-data(out, line) # return # if slice-ends-with?(word-slice, ":") - # write-stream-buffered(out, line) + # write-stream-data(out, line) # return # # really convert # emit-opcodes(line, out) @@ -1891,7 +2005,7 @@ $convert-instruction:check0: 3d/compare-EAX-and 0/imm32 75/jump-if-not-equal $convert-instruction:pass-through/disp8 $convert-instruction:check1: - # if (slice-starts-with?(word-slice, "#")) write-stream-buffered(out, line) + # if (slice-starts-with?(word-slice, "#")) write-stream-data(out, line) # . start/EDX = word-slice->start 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX # . c/EAX = *start @@ -1901,7 +2015,7 @@ $convert-instruction:check1: 3d/compare-EAX-and 0x23/imm32/hash 74/jump-if-equal $convert-instruction:pass-through/disp8 $convert-instruction:check2: - # if (slice-ends-with?(word-slice, ":")) write-stream-buffered(out, line) + # if (slice-ends-with?(word-slice, ":")) write-stream-data(out, line) # . end/EDX = word-slice->end 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX # . c/EAX = *(end-1) @@ -1911,12 +2025,12 @@ $convert-instruction:check2: 3d/compare-EAX-and 0x3a/imm32/colon 75/jump-if-not-equal $convert-instruction:really-convert/disp8 $convert-instruction:pass-through: - # write-stream-buffered(out, line) + # write-stream-data(out, line) # . . 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 write-stream-buffered/disp32 + e8/call write-stream-data/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # return @@ -3391,12 +3505,12 @@ emit-line-in-comment: # line : (address stream byte), out : (address buffered-f e8/call write-buffered/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # write-stream-buffered(out, line) + # write-stream-data(out, line) # . . 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 write-stream-buffered/disp32 + e8/call write-stream-data/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP $emit-line-in-comment:end: @@ -7523,6 +7637,118 @@ test-emit-hex-negative: # . end c3/return +# write an entire stream's contents to a buffered-file +# ways to do this: +# - construct a 'maximal slice' and pass it to write-slice +# - flush the buffered-file and pass the stream directly to its fd (disabling buffering) +# we'll go with the first way for now +write-stream-data: # f : (address buffered-file), s : (address stream) -> <void> + # . prolog + 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 + 56/push-ESI + # ESI = s + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI + # var slice/ECX = {s->data, s->data + s->write} + # . push s->data + s->write + 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX + 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX + 50/push-EAX + # . push s->data + 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 0xc/disp8 . # copy ESI+12 to EAX + 50/push-EAX + # . ECX = ESP + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # write-slice(f, slice) + # . . push args + 51/push-ECX + ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + # . . call + e8/call write-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +$write-stream-data:end: + # . restore locals + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . restore registers + 5e/pop-to-ESI + 59/pop-to-ECX + 58/pop-to-EAX + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-write-stream-data: + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # setup + # . clear-stream(_test-stream) + # . . push args + 68/push _test-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-buffered-file+4) + # . . push args + b8/copy-to-EAX _test-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 + # . clear-stream(_test-tmp-stream) + # . . push args + 68/push _test-tmp-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # initialize input + # . write(_test-tmp-stream, "abcd") + # . . push args + 68/push "abcd"/imm32 + 68/push _test-tmp-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-stream-data(_test-buffered-file, _test-tmp-stream) + # . . push args + 68/push _test-tmp-stream/imm32 + 68/push _test-buffered-file/imm32 + # . . call + e8/call write-stream-data/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # check that the write happened as expected + # . flush(_test-buffered-file) + # . . push args + 68/push _test-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-stream, "abcd", msg) + # . . push args + 68/push "F - test-write-stream-data"/imm32 + 68/push "abcd"/imm32 + 68/push _test-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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + # shortcut for parse-hex-int(next-token-from-slice(word->start, word->end, '/')) parse-datum-of-word: # word : (address slice) -> value/EAX # . prolog |