diff options
Diffstat (limited to 'subx/apps/crenshaw2-1.subx')
-rw-r--r-- | subx/apps/crenshaw2-1.subx | 224 |
1 files changed, 11 insertions, 213 deletions
diff --git a/subx/apps/crenshaw2-1.subx b/subx/apps/crenshaw2-1.subx index 3abf7365..62e2cb89 100644 --- a/subx/apps/crenshaw2-1.subx +++ b/subx/apps/crenshaw2-1.subx @@ -186,23 +186,18 @@ compile: # in : fd or (address stream), out : fd or (address stream), err : fd 5d/pop-to-EBP c3/return -# Read a sequence of digits into 'out'. Abort if there are none, or if there -# are too many to fit in 'out'. -# Input comes from the global variable 'Look' (first byte) and the argument -# 'in' (rest). +# Read a single digit into 'out'. Abort if there are none, or if there is no space in 'out'. +# Input comes from the global variable 'Look', and we leave the next byte from +# 'in' into it on exit. get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void> # pseudocode: # if !is-digit?(Look) expected(ed, err, "integer") - # do - # if out.write >= out.length - # write(err, "Error: too many digits in number\n") - # stop(ed, 1) - # out.data[out.write] = LSB(Look) - # ++out.write - # Look = get-char(in) - # while is-digit?(Look) - # This is complicated because I don't want to hard-code the error strategy in - # a general helper like write-byte. Maybe I should just create a local helper. + # if out.write >= out.length + # write(err, "Error: too many digits in number\n") + # stop(ed, 1) + # out.data[out.write] = LSB(Look) + # ++out.write + # Look = get-char(in) # # within the loop we'll try to keep things in registers: # ESI : in @@ -254,10 +249,9 @@ $get-num:main: 8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX # EDX = out->length 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX -$get-num:loop: # if out->write >= out->length error 3b/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare EDX with ECX - 7d/jump-if-lesser $get-num:loop-stage2/disp8 + 7d/jump-if-lesser $get-num:stage2/disp8 # error(ed, err, "get-num: too many digits in number") # TODO: show full number # push args 68/push "get-num: too many digits in number"/imm32 @@ -267,7 +261,7 @@ $get-num:loop: e8/call error/disp32 # never returns # discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -$get-num:loop-stage2: +$get-num:stage2: # out->data[out->write] = LSB(Look) 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy *Look to EAX @@ -281,16 +275,6 @@ $get-num:loop-stage2: e8/call get-char/disp32 # discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # EAX = is-digit?(Look) - # push args - ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look - # call - e8/call is-digit?/disp32 - # discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - # if EAX loop - 3d/compare-EAX 0/imm32 - 0f 85/jump-if-not-equal $get-num:loop/disp16 $get-num:loop-end: # persist necessary variables from registers 89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI @@ -486,192 +470,6 @@ test-get-num-aborts-on-non-digit-in-Look: 5d/pop-to-EBP c3/return -test-get-num-reads-multiple-digits: - ## check that get-num returns all initial digits until it encounters a non-digit - # This test uses exit-descriptors. Use EBP for setting up local variables. - 55/push-EBP - 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - ## clear all streams - # 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-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-error-stream) - # push args - 68/push _test-error-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 'in' - # write(_test-stream, "3456 x") - # push args - 68/push "3456"/imm32 - 68/push _test-stream/imm32 - # call - e8/call write/disp32 - # discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - ## initialize exit-descriptor 'ed' - # allocate on stack - # var ed/EAX : (address exit-descriptor) - 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX - # size the exit-descriptor for the call to get-num below - # tailor-exit-descriptor(ed, 16) - # push args - 68/push 0x10/imm32/nbytes-of-args-for-get-num - 50/push-EAX/ed - # call - e8/call tailor-exit-descriptor/disp32 - # discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - ## prime the pump - # get-char(_test-buffered-file) - # push args - 68/push _test-buffered-file/imm32 - # call - e8/call get-char/disp32 - # discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - ## get-num(in, out, err, ed) - # push args - 50/push-EAX/ed - 68/push _test-error-stream/imm32 - 68/push _test-output-stream/imm32 - 68/push _test-buffered-file/imm32 - # call - e8/call get-num/disp32 - ## registers except ESP may be clobbered at this point - # discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP - # check-ints-equal(*_test-output-stream.data, '3456') - # push args - 68/push "F - test-get-num-reads-multiple-digits"/imm32 - 68/push 0x36353433/imm32 - b8/copy-to-EAX _test-output-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 - # reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 5d/pop-to-EBP - c3/return - -test-get-num-reads-multiple-digits-followed-by-nondigit: - ## check that get-num returns all initial digits until it encounters a non-digit - # This test uses exit-descriptors. Use EBP for setting up local variables. - 55/push-EBP - 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - ## clear all streams - # 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-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-error-stream) - # push args - 68/push _test-error-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 'in' - # write(_test-stream, "3456 x") - # push args - 68/push "3456 x"/imm32 - 68/push _test-stream/imm32 - # call - e8/call write/disp32 - # discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - ## initialize exit-descriptor 'ed' - # allocate on stack - # var ed/EAX : (address exit-descriptor) - 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 8d/copy-address 0/mod/indirect 4/rm32/sib 4/base/ESP 4/index/none . 0/r32/EAX . . # copy ESP to EAX - # size the exit-descriptor for the call to get-num below - # tailor-exit-descriptor(ed, 16) - # push args - 68/push 0x10/imm32/nbytes-of-args-for-get-num - 50/push-EAX/ed - # call - e8/call tailor-exit-descriptor/disp32 - # discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - ## prime the pump - # get-char(_test-buffered-file) - # push args - 68/push _test-buffered-file/imm32 - # call - e8/call get-char/disp32 - # discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - ## get-num(in, out, err, ed) - # push args - 50/push-EAX/ed - 68/push _test-error-stream/imm32 - 68/push _test-output-stream/imm32 - 68/push _test-buffered-file/imm32 - # call - e8/call get-num/disp32 - ## registers except ESP may be clobbered at this point - # discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP - # check-ints-equal(*_test-output-stream.data, '3456') - # push args - 68/push "F - test-get-num-reads-multiple-digits-followed-by-nondigit"/imm32 - 68/push 0x36353433/imm32 - b8/copy-to-EAX _test-output-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 - # reclaim locals - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 5d/pop-to-EBP - c3/return - ## helpers # write(f, "Error: "+s+" expected\n") then stop(ed, 1) |