From 195d62f167d51b43ef7dc564899427ee63328c97 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sun, 7 Jul 2019 23:56:23 -0700 Subject: [PATCH] build `num-bytes` --- subx/apps/subx-common.subx | 64 ++++- subx/apps/survey | Bin 32117 -> 34421 bytes subx/apps/survey.subx | 503 +++++++++++++++++++++++++++++++++++++ 3 files changed, 565 insertions(+), 2 deletions(-) diff --git a/subx/apps/subx-common.subx b/subx/apps/subx-common.subx index d9f4e34c..ef1a6f93 100644 --- a/subx/apps/subx-common.subx +++ b/subx/apps/subx-common.subx @@ -1136,7 +1136,7 @@ test-has-metadata-multiple-false: 5d/pop-to-EBP c3/return -compute-width: # word : (address array byte) +compute-width: # word : (address array byte) -> EAX : int # . prolog 55/push-EBP 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP @@ -1198,7 +1198,7 @@ compute-width: # word : (address array byte) # else: return 1 b8/copy-to-EAX 1/imm32 $compute-width:end: - # . discard locals + # . reclaim locals 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # . restore registers 59/pop-to-ECX @@ -1322,6 +1322,66 @@ $test-compute-width:no-metadata: 5d/pop-to-EBP c3/return +compute-width-of-slice: # s : (address slice) -> EAX : int + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # . save registers + 51/push-ECX + # ECX = s + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX + # if has-metadata?(word, "imm32") or has-metadata?(word, "disp32"): return 4 + # . EAX = has-metadata?(word, "imm32") + 68/push "imm32"/imm32 + 51/push-ECX + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . if EAX: return 4 + 3d/compare-EAX-and 1/imm32 + b8/copy-to-EAX 4/imm32 # ZF is set, so we can overwrite EAX now + 74/jump-if-equal $compute-width-of-slice:end/disp8 + # . has-metadata?(word, "disp32") + 68/push "disp32"/imm32 + 51/push-ECX + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . if EAX: return 4 + 3d/compare-EAX-and 1/imm32 + b8/copy-to-EAX 4/imm32 # ZF is set, so we can overwrite EAX now + 74/jump-if-equal $compute-width-of-slice:end/disp8 + # if has-metadata?(word, "imm16") or has-metadata?(word, "disp16"): return 2 + # . has-metadata?(word, "imm16") + 68/push "imm16"/imm32 + 51/push-ECX + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . if EAX: return 2 + 3d/compare-EAX-and 1/imm32 + b8/copy-to-EAX 2/imm32 # ZF is set, so we can overwrite EAX now + 74/jump-if-equal $compute-width-of-slice:end/disp8 + # . has-metadata?(word, "disp16") + 68/push "disp16"/imm32 + 51/push-ECX + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . if EAX: return 2 + 3d/compare-EAX-and 1/imm32 + b8/copy-to-EAX 2/imm32 # ZF is set, so we can overwrite EAX now + 74/jump-if-equal $compute-width-of-slice:end/disp8 + # else: return 1 + b8/copy-to-EAX 1/imm32 +$compute-width-of-slice:end: + # . restore registers + 59/pop-to-ECX + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + is-label?: # word : (address slice) -> EAX : boolean # . prolog 55/push-EBP diff --git a/subx/apps/survey b/subx/apps/survey index 03dcb50e410110402d22ceb7207c5a1fef5e22da..1794174b70f8a62909f35f3aa1a125d082124b21 100755 GIT binary patch literal 34421 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 diff --git a/subx/apps/survey.subx b/subx/apps/survey.subx index 5af21261..6f109a08 100644 --- a/subx/apps/survey.subx +++ b/subx/apps/survey.subx @@ -2118,9 +2118,512 @@ num-bytes: # line : (address stream) -> EAX : int 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 + # var result/EAX = 0 + 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + # var word-slice/ECX = {0, 0} + 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 +#? # dump line {{{ +#? # . write(2/stderr, "LL: ") +#? # . . push args +#? 68/push "LL: "/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, line) +#? # . . push args +#? ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +#? 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 +#? # }}} +$num-bytes:loop: + # next-word(line, word-slice) + # . . push args + 51/push-ECX + ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + # . . call + e8/call next-word/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +#? # dump word-slice {{{ +#? # . write(2/stderr, "AA: ") +#? # . . push args +#? 68/push "AA: "/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 +#? # . clear-stream(Stderr+4) +#? # . . save EAX +#? 50/push-EAX +#? # . . push args +#? b8/copy-to-EAX Stderr/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 +#? # . . restore EAX +#? 58/pop-to-EAX +#? # . write-slice-buffered(Stderr, word-slice) +#? # . . push args +#? 51/push-ECX +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call write-slice-buffered/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +#? # . flush(Stderr) +#? # . . push args +#? 68/push Stderr/imm32 +#? # . . call +#? e8/call flush/disp32 +#? # . . discard args +#? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/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 +#? # }}} +$num-bytes:check0: + # if (slice-empty?(word-slice)) break + # . save result + 50/push-EAX + # . EAX = slice-empty?(word-slice) + # . . push args + 51/push-ECX + # . . 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 != 0) break + 3d/compare-EAX-and 0/imm32 + # . restore result now that ZF is set + 58/pop-into-EAX + 75/jump-if-not-equal $num-bytes:end/disp8 +$num-bytes:check-for-comment: + # if (slice-starts-with?(word-slice, "#")) break + # . start/EDX = word-slice->start + 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX + # . c/EBX = *start + 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX + 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 3/r32/BL . . # copy byte at *EDX to BL + # . if (EBX == '#') break + 81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0x23/imm32/hash # compare EBX + 74/jump-if-equal $num-bytes:end/disp8 +$num-bytes:check-for-label: + # if (slice-ends-with?(word-slice, ":")) break + # . end/EDX = word-slice->end + 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX + # . c/EBX = *(end-1) + 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX + 8a/copy-byte 1/mod/*+disp8 2/rm32/EDX . . . 3/r32/BL -1/disp8 . # copy byte at *ECX to BL + # . if (EBX == ':') break + 81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0x3a/imm32/colon # compare EBX + 74/jump-if-equal $num-bytes:end/disp8 +$num-bytes:check-for-segment-header: + # if (slice-equal?(word-slice, "==")) break + # . push result + 50/push-EAX + # . EAX = slice-equal?(word-slice, "==") + # . . push args + 68/push "=="/imm32 + 51/push-ECX + # . . call + e8/call slice-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . if (EAX != 0) break + 3d/compare-EAX-and 0/imm32 + # . restore result now that ZF is set + 58/pop-into-EAX + 75/jump-if-not-equal $num-bytes:end/disp8 +$num-bytes:loop-body: + # result += compute-width-of-slice(word-slice) + # . copy result to EDX + 89/copy 3/mod/direct 2/rm32/EDX . . . 0/r32/EAX . . # copy EAX to EDX + # . EAX = compute-width-of-slice(word-slice) + # . . push args + 51/push-ECX + # . . call + e8/call compute-width-of-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # . EAX += result + 01/add 3/mod/direct 0/rm32/EAX . . . 2/r32/EDX . . # add EDX to EAX + e9/jump $num-bytes:loop/disp32 $num-bytes:end: # . reclaim locals + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP # . restore registers + 5b/pop-into-EBX + 5a/pop-into-EDX + 59/pop-into-ECX + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-num-bytes-handles-empty-string: + # if a line starts with '#', return 0 + # . 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 + # no contents in input + # EAX = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # check-ints-equal(EAX, 0, msg) + # . . push args + 68/push "F - test-num-bytes-handles-empty-string"/imm32 + 68/push 0/imm32/true + 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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-num-bytes-ignores-comments: + # if a line starts with '#', return 0 + # . 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 + # initialize input + # . write(_test-input-stream, "# abcd") + # . . push args + 68/push "# abcd"/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 + # EAX = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # check-ints-equal(EAX, 0, msg) + # . . push args + 68/push "F - test-num-bytes-ignores-comments"/imm32 + 68/push 0/imm32/true + 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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-num-bytes-ignores-labels: + # if the first word ends with ':', return 0 + # . 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 + # initialize input + # . write(_test-input-stream, "ab: # cd") + # . . push args + 68/push "ab: # cd"/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 + # EAX = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # check-ints-equal(EAX, 0, msg) + # . . push args + 68/push "F - test-num-bytes-ignores-labels"/imm32 + 68/push 0/imm32/true + 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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-num-bytes-ignores-segment-headers: + # if the first word is '==', return 0 + # . 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 + # initialize input + # . write(_test-input-stream, "== ab cd") + # . . push args + 68/push "== ab cd"/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 + # EAX = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # check-ints-equal(EAX, 0, msg) + # . . push args + 68/push "F - test-num-bytes-ignores-segment-headers"/imm32 + 68/push 0/imm32/true + 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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-num-bytes-counts-words-by-default: + # without metadata, count words + # . 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 + # initialize input + # . write(_test-input-stream, "ab cd ef") + # . . push args + 68/push "ab cd ef"/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 + # EAX = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # check-ints-equal(EAX, 3, msg) + # . . push args + 68/push "F - test-num-bytes-counts-words-by-default"/imm32 + 68/push 3/imm32/true + 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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-num-bytes-ignores-trailing-comment: + # trailing comments 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 + # initialize input + # . write(_test-input-stream, "ab cd # ef") + # . . push args + 68/push "ab cd # ef"/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 + # EAX = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # check-ints-equal(EAX, 2, msg) + # . . push args + 68/push "F - test-num-bytes-ignores-trailing-comment"/imm32 + 68/push 2/imm32/true + 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 + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-num-bytes-handles-imm32: + # if a word has the /imm32 metadata, count it as 4 bytes + # . 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 + # initialize input + # . write(_test-input-stream, "ab cd/imm32 ef") + # . . push args + 68/push "ab cd/imm32 ef"/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 + # EAX = num-bytes(_test-input-stream) + # . . push args + 68/push _test-input-stream/imm32 + # . . call + e8/call num-bytes/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # check-ints-equal(EAX, 6, msg) + # . . push args + 68/push "F - test-num-bytes-handles-imm32"/imm32 + 68/push 6/imm32/true + 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 # . epilog 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 5d/pop-to-EBP