From cb82bd2364c302acbb96dd6900779e189b36efac Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 2 Feb 2019 15:21:48 -0800 Subject: 4948 This seems like the final helper we need for Phase 2. Now to build the business logic itself. --- subx/apps/pack | Bin 16518 -> 17425 bytes subx/apps/pack.subx | 347 +++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 341 insertions(+), 6 deletions(-) (limited to 'subx/apps') diff --git a/subx/apps/pack b/subx/apps/pack index 54c40efc..4d10e9bd 100755 Binary files a/subx/apps/pack and b/subx/apps/pack differ diff --git a/subx/apps/pack.subx b/subx/apps/pack.subx index 9ad17b7d..e35e8e20 100644 --- a/subx/apps/pack.subx +++ b/subx/apps/pack.subx @@ -21,7 +21,7 @@ # . 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 # for debugging: run a single test -#? e8/call test-has-metadata-true/disp32 +#? e8/call test-emit-non-number-with-metadata/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 @@ -134,11 +134,6 @@ $main:end: # next-token(stream, slice, delim char) -> slice' # slice-equal?(slice, string) -# helpers: -# emit(out : &buffered-file, word : &slice, width : int) -# if slice is all hex digits, parse and print appropriate digits -# otherwise just write-slice - convert: # in : (address buffered-file), out : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> # pseudocode: # line = new-stream(512, 1) @@ -618,6 +613,338 @@ test-has-metadata-multiple-false: 5d/pop-to-EBP c3/return +# if the name of 'word' is all hex digits, parse and emit it in 'width' bytes +# of hex otherwise just write-slice +emit: # out : (address buffered-file), word : (address slice), width : int + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # . save registers + 50/push-EAX + 56/push-ESI + 57/push-EDI + # ESI = word + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI + # var name/EDI : (address slice) = {0, 0} + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI + # name = next-token-from-slice(word->start, word->end, '/') + # . . push args + 57/push-EDI + 68/push 0x2f/imm32/slash + ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) + ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI + # . . call + e8/call next-token-from-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP + # if !is-hex-int?(name) write-slice(out, word) and return + # . is-hex-int?(name) + # . . push args + 57/push-EDI + # . . call + e8/call is-hex-int?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # . if EAX == 0 + 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX + 75/jump-if-not-equal $emit:hex-int/disp8 + # . write-slice(out, word) + # . . push args + 56/push-ESI + 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 + # . return + eb/jump $emit:end/disp8 + # otherwise emit-hex(out, parse-hex-int(name), width) +$emit:hex-int: + # . n/EAX = parse-hex-int(name) + # . . push args + 57/push-EDI + # . . call + e8/call parse-hex-int/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # . emit-hex(out, n, width) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 50/push-EAX + ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + # . . call + e8/call emit-hex/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +$emit:end: + # . reclaim locals + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . restore registers + 5f/pop-to-EDI + 5e/pop-to-ESI + 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-emit-number: + # . 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 + # var slice/ECX = "-2" + 68/push _test-slice-negative-two-end/imm32/end + 68/push _test-slice-negative-two/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # emit(_test-buffered-file, slice, 2) + # . . push args + 68/push 2/imm32 + 51/push-ECX + 68/push _test-buffered-file/imm32 + # . . call + e8/call emit/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # 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(_test-stream->data == 'fe ff ') + # . check-ints-equal(_test-stream->data[0..3], 'fe f', msg) + # . . push args + 68/push "F - test-emit-number/1"/imm32 + 68/push 0x66206566/imm32 + # . . push *_test-stream->data + b8/copy-to-EAX _test-stream/imm32 + ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # . check-ints-equal(_test-stream->data[4..7], 'f ', msg) + # . . push args + 68/push "F - test-emit-number/2"/imm32 + 68/push 0x2066/imm32 + # . . push *_test-stream->data + b8/copy-to-EAX _test-stream/imm32 + ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16) + # . . call + e8/call check-ints-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-number-with-metadata: + # . 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 + # var slice/ECX = "-2/foo" + 68/push _test-slice-negative-two-metadata-end/imm32/end + 68/push _test-slice-negative-two/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # emit(_test-buffered-file, slice, 2) + # . . push args + 68/push 2/imm32 + 51/push-ECX + 68/push _test-buffered-file/imm32 + # . . call + e8/call emit/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # 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 + # the '/foo' will have no impact on the output + # check(_test-stream->data == 'fe ff ') + # . check-ints-equal(_test-stream->data[0..3], 'fe f', msg) + # . . push args + 68/push "F - test-emit-number-with-metadata/1"/imm32 + 68/push 0x66206566/imm32 + # . . push *_test-stream->data + b8/copy-to-EAX _test-stream/imm32 + ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # . check-ints-equal(_test-stream->data[4..7], 'f ', msg) + # . . push args + 68/push "F - test-emit-number-with-metadata/2"/imm32 + 68/push 0x2066/imm32 + # . . push *_test-stream->data + b8/copy-to-EAX _test-stream/imm32 + ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16) + # . . call + e8/call check-ints-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-non-number: + # . 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 + # var slice/ECX = "xyz" + 68/push _test-slice-non-number-word-end/imm32/end + 68/push _test-slice-non-number-word/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # emit(_test-buffered-file, slice, 2) + # . . push args + 68/push 2/imm32 + 51/push-ECX + 68/push _test-buffered-file/imm32 + # . . call + e8/call emit/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # 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(_test-stream->data == 'xyz') + # . check-ints-equal(_test-stream->data[0..3], 'xyz', msg) + # . . push args + 68/push "F - test-emit-non-number"/imm32 + 68/push 0x7a7978/imm32 + # . . push *_test-stream->data + b8/copy-to-EAX _test-stream/imm32 + ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) + # . . call + e8/call check-ints-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-non-number-with-metadata: + # . 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 + # var slice/ECX = "xyz/" + 68/push _test-slice-non-number-word-metadata-end/imm32/end + 68/push _test-slice-non-number-word/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # emit(_test-buffered-file, slice, 2) + # . . push args + 68/push 2/imm32 + 51/push-ECX + 68/push _test-buffered-file/imm32 + # . . call + e8/call emit/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # 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(_test-stream->data == 'xyz/') + # . check-ints-equal(_test-stream->data[0..3], 'xyz/', msg) + # . . push args + 68/push "F - test-emit-non-number-with-metadata"/imm32 + 68/push 0x2f7a7978/imm32 + # . . push *_test-stream->data + b8/copy-to-EAX _test-stream/imm32 + ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) + # . . call + e8/call check-ints-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 + # print 'n' in hex in 'width' bytes in lower-endian order, with a space after every byte emit-hex: # out : (address buffered-file), n : int, width : int # . prolog @@ -907,5 +1234,13 @@ test-emit-hex-negative: _test-slice-negative-two: 2d/- 32/2 _test-slice-negative-two-end: + 2f/slash 66/f 6f/o 6f/o +_test-slice-negative-two-metadata-end: + +_test-slice-non-number-word: + 78/x 79/y 7a/z +_test-slice-non-number-word-end: + 2f/slash +_test-slice-non-number-word-metadata-end: # . . vim:nowrap:textwidth=0 -- cgit 1.4.1-2-gfad0