From c3adc0d4229b53e23d99f77eec852b1ba6077c50 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 6 Dec 2018 12:54:03 -0800 Subject: 4855 --- html/subx/apps/hex.subx.html | 2781 +++++++++++++++++++++++++----------------- 1 file changed, 1634 insertions(+), 1147 deletions(-) (limited to 'html/subx/apps/hex.subx.html') diff --git a/html/subx/apps/hex.subx.html b/html/subx/apps/hex.subx.html index ce78a35f..9d6020e1 100644 --- a/html/subx/apps/hex.subx.html +++ b/html/subx/apps/hex.subx.html @@ -64,1175 +64,1662 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/master/subx/apps/hex.subx
-   1 # Read a text file containing whitespace-separated ascii hex bytes from stdin,
-   2 # and convert them into a binary file.
-   3 #
-   4 # To run (from the subx/ directory):
-   5 #   $ ./subx translate *.subx apps/hex.subx -o apps/hex
-   6 #   $ echo '80 81 82  # comment'  |./subx run apps/hex  |xxd -
-   7 # Expected output:
-   8 #   00000000: 8081 82
-   9 #
-  10 # Only hex bytes and comments are permitted. Outside of comments all words
-  11 # must be exactly 2 characters long and contain only characters [0-9a-f]. No
-  12 # uppercase hex.
-  13 
-  14 == code
-  15 #   instruction                     effective address                                                   register    displacement    immediate
-  16 # . op          subop               mod             rm32          base        index         scale       r32
-  17 # . 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
-  18 
-  19     # for debugging: run a single test
-  20 #?     e8/call test-skip-until-newline/disp32
-  21 #?     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
-  22 #?     eb/jump  $main:end/disp8
-  23 
-  24 # main: run tests if necessary, convert stdin if not
-  25     # . prolog
-  26     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-  27     # - if argc > 1 and argv[1] == "test" then return run_tests()
-  28     # . argc > 1
-  29     81          7/subop/compare     1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0/disp8         1/imm32           # compare *EBP
-  30     7e/jump-if-lesser-or-equal  $run-main/disp8
-  31     # . argv[1] == "test"
-  32     # . . push args
-  33     68/push  "test"/imm32
-  34     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
-  35     # . . call
-  36     e8/call  kernel-string-equal/disp32
-  37     # . . discard args
-  38     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-  39     # . check result
-  40     3d/compare-EAX  1/imm32
-  41     75/jump-if-not-equal  $run-main/disp8
-  42     # . run-tests()
-  43 #?     e8/call test-hex-below-0/disp32
-  44 #?     e8/call test-scan-next-byte/disp32
-  45 #?     e8/call test-scan-next-byte-handles-eof/disp32
-  46 #?     e8/call test-scan-next-byte-skips-comment/disp32
-  47     e8/call  run-tests/disp32
-  48     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
-  49     eb/jump  $main:end/disp8
-  50 $run-main:
-  51     # - otherwise convert stdin
-  52     # var ed/EAX : exit-descriptor
-  53     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
-  54     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           0/r32/EAX   .               .                 # copy ESP to EAX
-  55     # configure ed to really exit()
-  56     # . ed->target = 0
-  57     c7/copy                         0/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # copy to *EAX
-  58     # return convert(Stdin, 1/stdout, 2/stderr, ed)
-  59     # . . push args
-  60     50/push-EAX/ed
-  61     68/push  2/imm32/stderr
-  62     68/push  1/imm32/stdout
-  63     68/push  Stdin/imm32
-  64     # . . call
-  65     e8/call  convert/disp32
-  66     # . . discard args
-  67     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
-  68     # . syscall(exit, 0)
-  69     bb/copy-to-EBX  0/imm32
-  70 $main:end:
-  71     b8/copy-to-EAX  1/imm32/exit
-  72     cd/syscall  0x80/imm8
-  73 
-  74 # the main entry point
-  75 convert:  # in : (address buffered-file), out : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> <void>
-  76     # . prolog
-  77     55/push-EBP
-  78     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-  79     # . save registers
-  80 $convert:end:
-  81     # . restore registers
-  82     # . epilog
-  83     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-  84     5d/pop-to-EBP
-  85     c3/return
-  86 
-  87 # read bytes from 'in' until a sequence of two lowercase hex characters (0-9, a-f)
-  88 # skip spaces and newlines
-  89 # on '#' skip bytes until newline
-  90 # raise an error and abort on all other unexpected bytes
-  91 # return the binary value of the two hex characters in EAX
-  92 # return 0xffffffff on end of file
-  93 convert-next-hex-byte:  # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX
-  94     # pseudocode:
-  95     #   EAX = scan-next-byte(in, err, ed)
-  96     #   if (EAX == 0xffffffff) return
-  97     #   ECX = EAX
+   1 # Read a text file containing whitespace-separated pairs of ascii hex bytes
+   2 # from stdin, and convert them into binary bytes (octets) on stdout. Ignore
+   3 # comments between '#' and newline.
+   4 #
+   5 # To run (from the subx/ directory):
+   6 #   $ ./subx translate *.subx apps/hex.subx -o apps/hex
+   7 #   $ echo '80 81 82  # comment'  |./subx run apps/hex  |xxd -
+   8 # Expected output:
+   9 #   00000000: 8081 82
+  10 #
+  11 # Only hex bytes and comments are permitted. Outside of comments all words
+  12 # must be exactly 2 characters long and contain only characters [0-9a-f]. No
+  13 # uppercase hex.
+  14 
+  15 == code
+  16 #   instruction                     effective address                                                   register    displacement    immediate
+  17 # . op          subop               mod             rm32          base        index         scale       r32
+  18 # . 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
+  19 
+  20     # for debugging: run a single test
+  21 #?     e8/call test-skip-until-newline/disp32
+  22 #?     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+  23 #?     eb/jump  $main:end/disp8
+  24 
+  25 # main: run tests if necessary, convert stdin if not
+  26     # . prolog
+  27     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  28     # - if argc > 1 and argv[1] == "test" then return run_tests()
+  29     # . argc > 1
+  30     81          7/subop/compare     1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0/disp8         1/imm32           # compare *EBP
+  31     7e/jump-if-lesser-or-equal  $run-main/disp8
+  32     # . argv[1] == "test"
+  33     # . . push args
+  34     68/push  "test"/imm32
+  35     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
+  36     # . . call
+  37     e8/call  kernel-string-equal/disp32
+  38     # . . discard args
+  39     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  40     # . check result
+  41     3d/compare-EAX  1/imm32
+  42     75/jump-if-not-equal  $run-main/disp8
+  43     # . run-tests()
+  44 #?     e8/call test-hex-below-0/disp32
+  45 #?     e8/call test-scan-next-byte/disp32
+  46 #?     e8/call test-scan-next-byte-handles-eof/disp32
+  47 #?     e8/call test-scan-next-byte-skips-comment/disp32
+  48 #?     e8/call test-scan-next-byte-aborts-on-invalid-byte/disp32
+  49 #?     e8/call test-convert-next-hex-byte/disp32
+  50     e8/call  run-tests/disp32
+  51     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+  52     eb/jump  $main:end/disp8
+  53 $run-main:
+  54     # - otherwise convert stdin
+  55     # var ed/EAX : exit-descriptor
+  56     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+  57     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           0/r32/EAX   .               .                 # copy ESP to EAX
+  58     # configure ed to really exit()
+  59     # . ed->target = 0
+  60     c7/copy                         0/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # copy to *EAX
+  61     # return convert(Stdin, 1/stdout, 2/stderr, ed)
+  62     # . . push args
+  63     50/push-EAX/ed
+  64     68/push  2/imm32/stderr
+  65     68/push  1/imm32/stdout
+  66     68/push  Stdin/imm32
+  67     # . . call
+  68     e8/call  convert/disp32
+  69     # . . discard args
+  70     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
+  71     # . syscall(exit, 0)
+  72     bb/copy-to-EBX  0/imm32
+  73 $main:end:
+  74     b8/copy-to-EAX  1/imm32/exit
+  75     cd/syscall  0x80/imm8
+  76 
+  77 # the main entry point
+  78 convert:  # in : (address buffered-file), out : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> <void>
+  79     # . prolog
+  80     55/push-EBP
+  81     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  82     # . save registers
+  83 $convert:end:
+  84     # . restore registers
+  85     # . epilog
+  86     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+  87     5d/pop-to-EBP
+  88     c3/return
+  89 
+  90 # read bytes from 'in' until a sequence of two lowercase hex (0-9, a-f) bytes
+  91 # skip spaces and newlines
+  92 # on '#' skip bytes until newline
+  93 # raise an error and abort on all other unexpected bytes
+  94 # return in EAX an _octet_ containing the binary value of the two hex characters
+  95 # return 0xffffffff on end of file
+  96 convert-next-hex-byte:  # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX
+  97     # pseudocode:
   98     #   EAX = scan-next-byte(in, err, ed)
-  99     #   if (EAX == 0xffffffff) error("partial byte found")
- 100     #   ECX = (ECX << 8) | EAX
- 101     #   return
- 102     #
- 103     # . prolog
- 104     55/push-EBP
- 105     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 106     # . save registers
- 107 $convert-next-hex-byte:end:
- 108     # . restore registers
- 109     # . epilog
- 110     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 111     5d/pop-to-EBP
- 112     c3/return
- 113 
- 114 # read whitespace until a hex byte, and return it
- 115 # return 0xffffffff if file ends without finding a hex byte
- 116 # on '#' skip all bytes until newline
- 117 # abort on any other byte
- 118 scan-next-byte:  # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX
- 119     # pseudocode:
- 120     #   repeatedly
- 121     #     EAX = read-byte(in)
- 122     #     if EAX == 0xffffffff return EAX
- 123     #     if is-hex-lowercase-byte?(EAX) return EAX
- 124     #     if EAX == 0x20 continue
- 125     #     if EAX == '#' skip-until-newline(in)
- 126     #     else error-byte(ed, err, "unexpected byte: " EAX)
- 127     #
- 128     # . prolog
- 129     55/push-EBP
- 130     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 131     # . save registers
- 132 $scan-next-byte:loop:
- 133     # EAX = read-byte(in)
- 134     # . . push args
- 135     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
- 136     # . . call
- 137     e8/call  read-byte/disp32
- 138     # . . discard args
- 139     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 140     # if (EAX == 0xffffffff) return EAX
- 141     3d/compare-with-EAX  0xffffffff/imm32
- 142     74/jump-if-equal  $scan-next-byte:end/disp8
- 143     # if is-hex-lowercase-byte?(EAX) return EAX
- 144     # . save EAX for now
- 145     50/push-EAX
- 146     # . is-hex-lowercase-byte?(EAX)
- 147     # . . push args
- 148     50/push-EAX
- 149     # . . call
- 150     e8/call  is-hex-lowercase-byte?/disp32
- 151     # . . discard args
- 152     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 153     # . compare with 'false'
- 154     3d/compare-with-EAX  0/imm32
- 155     # . restore EAX (does not affect flags)
- 156     58/pop-to-EAX
- 157     # . check whether to return
- 158     75/jump-if-not-equal  $scan-next-byte:end/disp8
- 159 $scan-next-byte:check1:
- 160     # if EAX == ' ' continue
- 161     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0x20/imm32        # compare EAX
- 162     74/jump-if-equal  $scan-next-byte:loop/disp8
- 163     # if EAX == '\t' continue
- 164     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0x9/imm32         # compare EAX
- 165     74/jump-if-equal  $scan-next-byte:loop/disp8
- 166     # if EAX == '\n' continue
- 167     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xa/imm32         # compare EAX
- 168     74/jump-if-equal  $scan-next-byte:loop/disp8
- 169 $scan-next-byte:check2:
- 170     # if EAX == '#' skip-until-newline(in)
- 171     3d/compare-with-EAX  0x23/imm32
- 172     75/jump-if-not-equal  $scan-next-byte:check3/disp8
- 173     # . skip-until-newline(in)
- 174     # . . push args
- 175     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
- 176     # . . call
- 177     e8/call  skip-until-newline/disp32
- 178     # . . discard args
- 179     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 180     eb/jump  $scan-next-byte:loop/disp8
- 181 $scan-next-byte:check3:
- 182     # otherwise error-byte(ed, err, msg, EAX)
- 183     # . . push args
- 184     50/push-EAX
- 185     68/push  "scan-next-byte: invalid byte"/imm32
- 186     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
- 187     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0x10/disp8      .                 # push *(EBP+16)
- 188     # . . call
- 189     e8/call  error-byte/disp32  # never returns
- 190 $scan-next-byte:end:
- 191     # . restore registers
- 192     # . epilog
- 193     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 194     5d/pop-to-EBP
- 195     c3/return
- 196 
- 197 test-scan-next-byte:
- 198     # - check that the first byte of the input is returned
- 199     # This test uses exit-descriptors. Use EBP for setting up local variables.
- 200     55/push-EBP
- 201     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 202     # clear all streams
- 203     # . clear-stream(_test-stream)
- 204     # . . push args
- 205     68/push  _test-stream/imm32
- 206     # . . call
- 207     e8/call  clear-stream/disp32
- 208     # . . discard args
- 209     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 210     # . clear-stream(_test-buffered-file+4)
+  99     #   if (EAX == 0xffffffff) return
+ 100     #   ECX = EAX
+ 101     #   EAX = scan-next-byte(in, err, ed)
+ 102     #   if (EAX == 0xffffffff) error("partial byte found.")
+ 103     #   ECX = (ECX << 8) | EAX
+ 104     #   return
+ 105     #
+ 106     # . prolog
+ 107     55/push-EBP
+ 108     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 109     # . save registers
+ 110     51/push-ECX
+ 111     # EAX = scan-next-byte(in, err, ed)
+ 112     # . . push args
+ 113     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0x10/disp8      .                 # push *(EBP+16)
+ 114     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+ 115     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
+ 116     # . . call
+ 117     e8/call  scan-next-byte/disp32
+ 118     # . . discard args
+ 119     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 120     # if (EAX == 0xffffffff) return
+ 121     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xffffffff/imm32  # compare EAX
+ 122     74/jump-if-equal  $convert-next-hex-byte:end/disp8
+ 123     # ECX = EAX
+ 124     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy EAX to ECX
+ 125     # EAX = scan-next-byte(in, err, ed)
+ 126     # . . push args
+ 127     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0x10/disp8      .                 # push *(EBP+16)
+ 128     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+ 129     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
+ 130     # . . call
+ 131     e8/call  scan-next-byte/disp32
+ 132     # . . discard args
+ 133     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 134     # if (EAX == 0xffffffff) error(ed, err, "partial byte found.")
+ 135     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xffffffff/imm32  # compare EAX
+ 136     75/jump-if-not-equal  $convert-next-hex-byte:convert/disp8
+ 137     # . error-byte(ed, err, msg, '.')  # reusing error-byte to avoid creating _yet_ another helper
+ 138     # . . push args
+ 139     68/push  0x2e/imm32/period/dummy
+ 140     68/push  "convert-next-hex-byte: partial byte found"/imm32
+ 141     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+ 142     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0x10/disp8      .                 # push *(EBP+16)
+ 143     # . . call
+ 144     e8/call  error-byte/disp32  # never returns
+ 145 $convert-next-hex-byte:convert:
+ 146     # EAX = (EAX << 8) | ECX
+ 147     # . EAX <<= 8
+ 148     c1/shift    4/subop/left        3/mod/direct    0/rm32/EAX    .           .             .           .           .               8/imm8            # shift EAX left by 8 bits
+ 149     # . EAX |= ECX
+ 150     09/or                           3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # EAX = bitwise OR with ECX
+ 151 $convert-next-hex-byte:end:
+ 152     # . restore registers
+ 153     59/pop-to-ECX
+ 154     # . epilog
+ 155     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 156     5d/pop-to-EBP
+ 157     c3/return
+ 158 
+ 159 test-convert-next-hex-byte:
+ 160     # - check that the first two bytes of the input are assembled into the resulting octet
+ 161     # This test uses exit-descriptors. Use EBP for setting up local variables.
+ 162     55/push-EBP
+ 163     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 164     # clear all streams
+ 165     # . clear-stream(_test-stream)
+ 166     # . . push args
+ 167     68/push  _test-stream/imm32
+ 168     # . . call
+ 169     e8/call  clear-stream/disp32
+ 170     # . . discard args
+ 171     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 172     # . clear-stream(_test-buffered-file+4)
+ 173     # . . push args
+ 174     b8/copy-to-EAX  _test-buffered-file/imm32
+ 175     05/add-to-EAX  4/imm32
+ 176     50/push-EAX
+ 177     # . . call
+ 178     e8/call  clear-stream/disp32
+ 179     # . . discard args
+ 180     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 181     # . clear-stream(_test-error-stream)
+ 182     # . . push args
+ 183     68/push  _test-error-stream/imm32
+ 184     # . . call
+ 185     e8/call  clear-stream/disp32
+ 186     # . . discard args
+ 187     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 188     # . clear-stream(_test-error-buffered-file+4)
+ 189     # . . push args
+ 190     b8/copy-to-EAX  _test-error-buffered-file/imm32
+ 191     05/add-to-EAX  4/imm32
+ 192     50/push-EAX
+ 193     # . . call
+ 194     e8/call  clear-stream/disp32
+ 195     # . . discard args
+ 196     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 197     # initialize '_test-stream' to "abc"
+ 198     # . write(_test-stream, "abc")
+ 199     # . . push args
+ 200     68/push  "abc"/imm32
+ 201     68/push  _test-stream/imm32
+ 202     # . . call
+ 203     e8/call  write/disp32
+ 204     # . . discard args
+ 205     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 206     # initialize exit-descriptor 'ed' for the call to 'convert-next-hex-byte' below
+ 207     # . var ed/ECX : exit-descriptor
+ 208     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+ 209     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+ 210     # . tailor-exit-descriptor(ed, 12)
  211     # . . push args
- 212     b8/copy-to-EAX  _test-buffered-file/imm32
- 213     05/add-to-EAX  4/imm32
- 214     50/push-EAX
- 215     # . . call
- 216     e8/call  clear-stream/disp32
- 217     # . . discard args
- 218     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 219     # . clear-stream(_test-error-stream)
- 220     # . . push args
- 221     68/push  _test-error-stream/imm32
- 222     # . . call
- 223     e8/call  clear-stream/disp32
- 224     # . . discard args
- 225     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 226     # initialize '_test-stream' to "abc"
- 227     # . write(_test-stream, "abc")
- 228     # . . push args
- 229     68/push  "abc"/imm32
- 230     68/push  _test-stream/imm32
- 231     # . . call
- 232     e8/call  write/disp32
- 233     # . . discard args
- 234     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 235     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
- 236     # . var ed/ECX : exit-descriptor
- 237     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
- 238     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
- 239     # . tailor-exit-descriptor(ed, 12)
- 240     # . . push args
- 241     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
- 242     51/push-ECX/ed
- 243     # . . call
- 244     e8/call  tailor-exit-descriptor/disp32
- 245     # . . discard args
- 246     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 247     # EAX = scan-next-byte(_test-buffered-file, _test-error-stream, ed)
- 248     # . . push args
- 249     51/push-ECX/ed
- 250     68/push  _test-error-stream/imm32
- 251     68/push  _test-buffered-file/imm32
- 252     # . . call
- 253     e8/call  scan-next-byte/disp32
- 254     # registers except ESP may be clobbered at this point
- 255     # pop args to scan-next-bytes
- 256     # . . discard first 2 args
+ 212     68/push  0xc/imm32/nbytes-of-args-for-convert-next-hex-byte
+ 213     51/push-ECX/ed
+ 214     # . . call
+ 215     e8/call  tailor-exit-descriptor/disp32
+ 216     # . . discard args
+ 217     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 218     # EAX = convert-next-hex-byte(_test-buffered-file, _test-error-buffered-file, ed)
+ 219     # . . push args
+ 220     51/push-ECX/ed
+ 221     68/push  _test-error-buffered-file/imm32
+ 222     68/push  _test-buffered-file/imm32
+ 223     # . . call
+ 224     e8/call  convert-next-hex-byte/disp32
+ 225     # registers except ESP may be clobbered at this point
+ 226     # pop args to convert-next-hex-bytes
+ 227     # . . discard first 2 args
+ 228     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 229     # . . restore ed
+ 230     59/pop-to-ECX
+ 231     # check that convert-next-hex-byte didn't abort
+ 232     # . check-ints-equal(ed->value, 0, msg)
+ 233     # . . push args
+ 234     68/push  "F - test-convert-next-hex-byte: unexpected abort"/imm32
+ 235     68/push  0/imm32
+ 236     # . . push ed->value
+ 237     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+ 238     # . . call
+ 239     e8/call  check-ints-equal/disp32
+ 240     # . . discard args
+ 241     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 242     # return if abort
+ 243     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
+ 244     75/jump-if-not-equal  $test-convert-next-hex-byte:end/disp8
+ 245     # check-ints-equal(EAX, 0x61/a 0x62/b, msg)
+ 246     # . . push args
+ 247     68/push  "F - test-convert-next-hex-byte"/imm32
+ 248     68/push  0x6261/imm32/ab
+ 249     50/push-EAX
+ 250     # . . call
+ 251     e8/call  check-ints-equal/disp32
+ 252     # . . discard args
+ 253     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 254 $test-convert-next-hex-byte:end:
+ 255     # . epilog
+ 256     # don't restore ESP from EBP; manually reclaim locals
  257     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 258     # . . restore ed
- 259     59/pop-to-ECX
- 260     # check that scan-next-byte didn't abort
- 261     # . check-ints-equal(ed->value, 0, msg)
- 262     # . . push args
- 263     68/push  "F - test-scan-next-byte: unexpected abort"/imm32
- 264     68/push  0/imm32
- 265     # . . push ed->value
- 266     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
- 267     # . . call
- 268     e8/call  check-ints-equal/disp32
- 269     # . . discard args
- 270     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 271     # return if abort
- 272     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
- 273     75/jump-if-not-equal  $test-scan-next-byte:end/disp8
- 274     # check-ints-equal(EAX, 0x61/a, msg)
+ 258     5d/pop-to-EBP
+ 259     c3/return
+ 260 
+ 261 test-convert-next-hex-byte-handles-eof:
+ 262     # - check that eof returns the sentinel octet
+ 263     # This test uses exit-descriptors. Use EBP for setting up local variables.
+ 264     55/push-EBP
+ 265     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 266     # clear all streams
+ 267     # . clear-stream(_test-stream)
+ 268     # . . push args
+ 269     68/push  _test-stream/imm32
+ 270     # . . call
+ 271     e8/call  clear-stream/disp32
+ 272     # . . discard args
+ 273     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 274     # . clear-stream(_test-buffered-file+4)
  275     # . . push args
- 276     68/push  "F - test-scan-next-byte"/imm32
- 277     68/push  0x61/imm32/a
+ 276     b8/copy-to-EAX  _test-buffered-file/imm32
+ 277     05/add-to-EAX  4/imm32
  278     50/push-EAX
  279     # . . call
- 280     e8/call  check-ints-equal/disp32
+ 280     e8/call  clear-stream/disp32
  281     # . . discard args
- 282     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 283 $test-scan-next-byte:end:
- 284     # . epilog
- 285     # don't restore ESP from EBP; manually reclaim locals
- 286     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 287     5d/pop-to-EBP
- 288     c3/return
- 289 
- 290 test-scan-next-byte-skips-whitespace:
- 291     # - check that the first byte after whitespace is returned
- 292     # This test uses exit-descriptors. Use EBP for setting up local variables.
- 293     55/push-EBP
- 294     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 295     # clear all streams
- 296     # . clear-stream(_test-stream)
- 297     # . . push args
- 298     68/push  _test-stream/imm32
- 299     # . . call
- 300     e8/call  clear-stream/disp32
- 301     # . . discard args
- 302     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 303     # . clear-stream(_test-buffered-file+4)
- 304     # . . push args
- 305     b8/copy-to-EAX  _test-buffered-file/imm32
- 306     05/add-to-EAX  4/imm32
- 307     50/push-EAX
+ 282     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 283     # . clear-stream(_test-error-stream)
+ 284     # . . push args
+ 285     68/push  _test-error-stream/imm32
+ 286     # . . call
+ 287     e8/call  clear-stream/disp32
+ 288     # . . discard args
+ 289     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 290     # . clear-stream(_test-error-buffered-file+4)
+ 291     # . . push args
+ 292     b8/copy-to-EAX  _test-error-buffered-file/imm32
+ 293     05/add-to-EAX  4/imm32
+ 294     50/push-EAX
+ 295     # . . call
+ 296     e8/call  clear-stream/disp32
+ 297     # . . discard args
+ 298     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 299     # don't initialize '_test-stream'
+ 300     # initialize exit-descriptor 'ed' for the call to 'convert-next-hex-byte' below
+ 301     # . var ed/ECX : exit-descriptor
+ 302     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+ 303     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+ 304     # . tailor-exit-descriptor(ed, 12)
+ 305     # . . push args
+ 306     68/push  0xc/imm32/nbytes-of-args-for-convert-next-hex-byte
+ 307     51/push-ECX/ed
  308     # . . call
- 309     e8/call  clear-stream/disp32
+ 309     e8/call  tailor-exit-descriptor/disp32
  310     # . . discard args
- 311     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 312     # . clear-stream(_test-error-stream)
+ 311     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 312     # EAX = convert-next-hex-byte(_test-buffered-file, _test-error-buffered-file, ed)
  313     # . . push args
- 314     68/push  _test-error-stream/imm32
- 315     # . . call
- 316     e8/call  clear-stream/disp32
- 317     # . . discard args
- 318     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 319     # initialize '_test-stream' to input with leading whitespace
- 320     # . write(_test-stream, text)
- 321     # . . push args
- 322     68/push  "  abc"/imm32
- 323     68/push  _test-stream/imm32
- 324     # . . call
- 325     e8/call  write/disp32
- 326     # . . discard args
- 327     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 328     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
- 329     # . var ed/ECX : exit-descriptor
- 330     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
- 331     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
- 332     # . tailor-exit-descriptor(ed, 12)
- 333     # . . push args
- 334     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
- 335     51/push-ECX/ed
- 336     # . . call
- 337     e8/call  tailor-exit-descriptor/disp32
- 338     # . . discard args
- 339     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 340     # EAX = scan-next-byte(_test-buffered-file, _test-error-stream, ed)
- 341     # . . push args
- 342     51/push-ECX/ed
- 343     68/push  _test-error-stream/imm32
- 344     68/push  _test-buffered-file/imm32
- 345     # . . call
- 346     e8/call  scan-next-byte/disp32
- 347     # registers except ESP may be clobbered at this point
- 348     # pop args to scan-next-bytes
- 349     # . . discard first 2 args
- 350     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 351     # . . restore ed
- 352     59/pop-to-ECX
- 353     # check that scan-next-byte didn't abort
- 354     # . check-ints-equal(ed->value, 0, msg)
- 355     # . . push args
- 356     68/push  "F - test-scan-next-byte-skips-whitespace: unexpected abort"/imm32
- 357     68/push  0/imm32
- 358     # . . push ed->value
- 359     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
- 360     # . . call
- 361     e8/call  check-ints-equal/disp32
- 362     # . . discard args
- 363     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 364     # return if abort
- 365     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
- 366     75/jump-if-not-equal  $test-scan-next-byte-skips-whitespace:end/disp8
- 367     # check-ints-equal(EAX, 0x61/a, msg)
- 368     # . . push args
- 369     68/push  "F - test-scan-next-byte-skips-whitespace"/imm32
- 370     68/push  0x61/imm32/a
- 371     50/push-EAX
- 372     # . . call
- 373     e8/call  check-ints-equal/disp32
- 374     # . . discard args
- 375     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 376 $test-scan-next-byte-skips-whitespace:end:
- 377     # . epilog
- 378     # don't restore ESP from EBP; manually reclaim locals
- 379     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 380     5d/pop-to-EBP
- 381     c3/return
- 382 
- 383 test-scan-next-byte-skips-comment:
- 384     # - check that the first byte after a comment (and newline) is returned
- 385     # This test uses exit-descriptors. Use EBP for setting up local variables.
- 386     55/push-EBP
- 387     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 388     # clear all streams
- 389     # . clear-stream(_test-stream)
- 390     # . . push args
- 391     68/push  _test-stream/imm32
- 392     # . . call
- 393     e8/call  clear-stream/disp32
- 394     # . . discard args
- 395     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 396     # . clear-stream(_test-buffered-file+4)
- 397     # . . push args
- 398     b8/copy-to-EAX  _test-buffered-file/imm32
- 399     05/add-to-EAX  4/imm32
- 400     50/push-EAX
- 401     # . . call
- 402     e8/call  clear-stream/disp32
- 403     # . . discard args
- 404     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 405     # . clear-stream(_test-error-stream)
- 406     # . . push args
- 407     68/push  _test-error-stream/imm32
- 408     # . . call
- 409     e8/call  clear-stream/disp32
- 410     # . . discard args
- 411     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 412     # initialize '_test-stream' to input with leading comment
- 413     # . write(_test-stream, comment)
- 414     # . . push args
- 415     68/push  "#x"/imm32
- 416     68/push  _test-stream/imm32
- 417     # . . call
- 418     e8/call  write/disp32
- 419     # . . discard args
- 420     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 421     # . write(_test-stream, Newline)
- 422     # . . push args
- 423     68/push  Newline/imm32
- 424     68/push  _test-stream/imm32
- 425     # . . call
- 426     e8/call  write/disp32
- 427     # . . discard args
- 428     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 429     # . write(_test-stream, real text)
- 430     # . . push args
- 431     68/push  "ab"/imm32
- 432     68/push  _test-stream/imm32
- 433     # . . call
- 434     e8/call  write/disp32
- 435     # . . discard args
- 436     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 437     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
- 438     # . var ed/ECX : exit-descriptor
- 439     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
- 440     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
- 441     # . tailor-exit-descriptor(ed, 12)
- 442     # . . push args
- 443     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
- 444     51/push-ECX/ed
- 445     # . . call
- 446     e8/call  tailor-exit-descriptor/disp32
- 447     # . . discard args
- 448     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 449     # EAX = scan-next-byte(_test-buffered-file, _test-error-stream, ed)
- 450     # . . push args
- 451     51/push-ECX/ed
- 452     68/push  _test-error-stream/imm32
- 453     68/push  _test-buffered-file/imm32
- 454     # . . call
- 455     e8/call  scan-next-byte/disp32
- 456     # registers except ESP may be clobbered at this point
- 457     # pop args to scan-next-bytes
- 458     # . . discard first 2 args
- 459     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 460     # . . restore ed
- 461     59/pop-to-ECX
- 462     # check that scan-next-byte didn't abort
- 463     # . check-ints-equal(ed->value, 0, msg)
- 464     # . . push args
- 465     68/push  "F - test-scan-next-byte-skips-comment: unexpected abort"/imm32
- 466     68/push  0/imm32
- 467     # . . push ed->value
- 468     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
- 469     # . . call
- 470     e8/call  check-ints-equal/disp32
- 471     # . . discard args
- 472     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 473     # return if abort
- 474     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
- 475     75/jump-if-not-equal  $test-scan-next-byte-skips-comment:end/disp8
- 476     # check-ints-equal(EAX, 0x61/a, msg)
- 477     # . . push args
- 478     68/push  "F - test-scan-next-byte-skips-comment"/imm32
- 479     68/push  0x61/imm32/a
- 480     50/push-EAX
- 481     # . . call
- 482     e8/call  check-ints-equal/disp32
- 483     # . . discard args
- 484     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 485 $test-scan-next-byte-skips-comment:end:
- 486     # . epilog
- 487     # don't restore ESP from EBP; manually reclaim locals
- 488     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 489     5d/pop-to-EBP
- 490     c3/return
- 491 
- 492 test-scan-next-byte-skips-comment-and-whitespace:
- 493     # - check that the first byte after a comment and any further whitespace is returned
- 494     # This test uses exit-descriptors. Use EBP for setting up local variables.
- 495     55/push-EBP
- 496     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 497     # clear all streams
- 498     # . clear-stream(_test-stream)
- 499     # . . push args
- 500     68/push  _test-stream/imm32
- 501     # . . call
- 502     e8/call  clear-stream/disp32
- 503     # . . discard args
- 504     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 505     # . clear-stream(_test-buffered-file+4)
- 506     # . . push args
- 507     b8/copy-to-EAX  _test-buffered-file/imm32
- 508     05/add-to-EAX  4/imm32
- 509     50/push-EAX
- 510     # . . call
- 511     e8/call  clear-stream/disp32
- 512     # . . discard args
- 513     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 514     # . clear-stream(_test-error-stream)
- 515     # . . push args
- 516     68/push  _test-error-stream/imm32
- 517     # . . call
- 518     e8/call  clear-stream/disp32
- 519     # . . discard args
- 520     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 521     # initialize '_test-stream' to input with leading comment and more whitespace after newline
- 522     # . write(_test-stream, comment)
- 523     # . . push args
- 524     68/push  "#x"/imm32
- 525     68/push  _test-stream/imm32
- 526     # . . call
- 527     e8/call  write/disp32
- 528     # . . discard args
- 529     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 530     # . write(_test-stream, Newline)
- 531     # . . push args
- 532     68/push  Newline/imm32
- 533     68/push  _test-stream/imm32
- 534     # . . call
- 535     e8/call  write/disp32
- 536     # . . discard args
- 537     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 538     # . write(_test-stream, real text)
- 539     # . . push args
- 540     68/push  " ab"/imm32
- 541     68/push  _test-stream/imm32
- 542     # . . call
- 543     e8/call  write/disp32
- 544     # . . discard args
- 545     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 546     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
- 547     # . var ed/ECX : exit-descriptor
- 548     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
- 549     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
- 550     # . tailor-exit-descriptor(ed, 12)
+ 314     51/push-ECX/ed
+ 315     68/push  _test-error-buffered-file/imm32
+ 316     68/push  _test-buffered-file/imm32
+ 317     # . . call
+ 318     e8/call  convert-next-hex-byte/disp32
+ 319     # registers except ESP may be clobbered at this point
+ 320     # pop args to convert-next-hex-bytes
+ 321     # . . discard first 2 args
+ 322     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 323     # . . restore ed
+ 324     59/pop-to-ECX
+ 325     # check that convert-next-hex-byte didn't abort
+ 326     # . check-ints-equal(ed->value, 0, msg)
+ 327     # . . push args
+ 328     68/push  "F - test-convert-next-hex-byte: unexpected abort"/imm32
+ 329     68/push  0/imm32
+ 330     # . . push ed->value
+ 331     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+ 332     # . . call
+ 333     e8/call  check-ints-equal/disp32
+ 334     # . . discard args
+ 335     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 336     # return if abort
+ 337     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
+ 338     75/jump-if-not-equal  $test-convert-next-hex-byte-handles-eof:end/disp8
+ 339     # check-ints-equal(EAX, 0xffffffff, msg)
+ 340     # . . push args
+ 341     68/push  "F - test-convert-next-hex-byte-handles-eof"/imm32
+ 342     68/push  0xffffffff/imm32/eof
+ 343     50/push-EAX
+ 344     # . . call
+ 345     e8/call  check-ints-equal/disp32
+ 346     # . . discard args
+ 347     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 348 $test-convert-next-hex-byte-handles-eof:end:
+ 349     # . epilog
+ 350     # don't restore ESP from EBP; manually reclaim locals
+ 351     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 352     5d/pop-to-EBP
+ 353     c3/return
+ 354 
+ 355 test-convert-next-hex-byte-aborts-on-single-hex-byte:
+ 356     # - check that a single unaccompanied hex byte aborts
+ 357     # This test uses exit-descriptors. Use EBP for setting up local variables.
+ 358     55/push-EBP
+ 359     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 360     # clear all streams
+ 361     # . clear-stream(_test-stream)
+ 362     # . . push args
+ 363     68/push  _test-stream/imm32
+ 364     # . . call
+ 365     e8/call  clear-stream/disp32
+ 366     # . . discard args
+ 367     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 368     # . clear-stream(_test-buffered-file+4)
+ 369     # . . push args
+ 370     b8/copy-to-EAX  _test-buffered-file/imm32
+ 371     05/add-to-EAX  4/imm32
+ 372     50/push-EAX
+ 373     # . . call
+ 374     e8/call  clear-stream/disp32
+ 375     # . . discard args
+ 376     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 377     # . clear-stream(_test-error-stream)
+ 378     # . . push args
+ 379     68/push  _test-error-stream/imm32
+ 380     # . . call
+ 381     e8/call  clear-stream/disp32
+ 382     # . . discard args
+ 383     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 384     # . clear-stream(_test-error-buffered-file+4)
+ 385     # . . push args
+ 386     b8/copy-to-EAX  _test-error-buffered-file/imm32
+ 387     05/add-to-EAX  4/imm32
+ 388     50/push-EAX
+ 389     # . . call
+ 390     e8/call  clear-stream/disp32
+ 391     # . . discard args
+ 392     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 393     # initialize '_test-stream' to "a"
+ 394     # . write(_test-stream, "a")
+ 395     # . . push args
+ 396     68/push  "a"/imm32
+ 397     68/push  _test-stream/imm32
+ 398     # . . call
+ 399     e8/call  write/disp32
+ 400     # . . discard args
+ 401     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 402     # initialize exit-descriptor 'ed' for the call to 'convert-next-hex-byte' below
+ 403     # . var ed/ECX : exit-descriptor
+ 404     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+ 405     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+ 406     # . tailor-exit-descriptor(ed, 12)
+ 407     # . . push args
+ 408     68/push  0xc/imm32/nbytes-of-args-for-convert-next-hex-byte
+ 409     51/push-ECX/ed
+ 410     # . . call
+ 411     e8/call  tailor-exit-descriptor/disp32
+ 412     # . . discard args
+ 413     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 414     # EAX = convert-next-hex-byte(_test-buffered-file, _test-error-buffered-file, ed)
+ 415     # . . push args
+ 416     51/push-ECX/ed
+ 417     68/push  _test-error-buffered-file/imm32
+ 418     68/push  _test-buffered-file/imm32
+ 419     # . . call
+ 420     e8/call  convert-next-hex-byte/disp32
+ 421     # registers except ESP may be clobbered at this point
+ 422     # pop args to convert-next-hex-bytes
+ 423     # . . discard first 2 args
+ 424     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 425     # . . restore ed
+ 426     59/pop-to-ECX
+ 427     # check that convert-next-hex-byte aborted
+ 428     # . check-ints-equal(ed->value, 2, msg)
+ 429     # . . push args
+ 430     68/push  "F - test-convert-next-hex-byte-aborts-on-single-hex-byte: unexpected abort"/imm32
+ 431     68/push  2/imm32
+ 432     # . . push ed->value
+ 433     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+ 434     # . . call
+ 435     e8/call  check-ints-equal/disp32
+ 436     # . . discard args
+ 437     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 438 $test-convert-next-hex-byte-aborts-on-single-hex-byte:end:
+ 439     # . epilog
+ 440     # don't restore ESP from EBP; manually reclaim locals
+ 441     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 442     5d/pop-to-EBP
+ 443     c3/return
+ 444 
+ 445 # read whitespace until a hex byte, and return it
+ 446 # return 0xffffffff if file ends without finding a hex byte
+ 447 # on '#' skip all bytes until newline
+ 448 # abort on any other byte
+ 449 scan-next-byte:  # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX
+ 450     # pseudocode:
+ 451     #   repeatedly
+ 452     #     EAX = read-byte(in)
+ 453     #     if EAX == 0xffffffff return EAX
+ 454     #     if is-hex-lowercase-byte?(EAX) return EAX
+ 455     #     if EAX == 0x20 continue
+ 456     #     if EAX == '#' skip-until-newline(in)
+ 457     #     else error-byte(ed, err, "unexpected byte: " EAX)
+ 458     #
+ 459     # . prolog
+ 460     55/push-EBP
+ 461     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 462     # . save registers
+ 463 $scan-next-byte:loop:
+ 464     # EAX = read-byte(in)
+ 465     # . . push args
+ 466     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
+ 467     # . . call
+ 468     e8/call  read-byte/disp32
+ 469     # . . discard args
+ 470     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 471     # if (EAX == 0xffffffff) return EAX
+ 472     3d/compare-with-EAX  0xffffffff/imm32
+ 473     74/jump-if-equal  $scan-next-byte:end/disp8
+ 474     # if is-hex-lowercase-byte?(EAX) return EAX
+ 475     # . save EAX for now
+ 476     50/push-EAX
+ 477     # . is-hex-lowercase-byte?(EAX)
+ 478     # . . push args
+ 479     50/push-EAX
+ 480     # . . call
+ 481     e8/call  is-hex-lowercase-byte?/disp32
+ 482     # . . discard args
+ 483     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 484     # . compare with 'false'
+ 485     3d/compare-with-EAX  0/imm32
+ 486     # . restore EAX (does not affect flags)
+ 487     58/pop-to-EAX
+ 488     # . check whether to return
+ 489     75/jump-if-not-equal  $scan-next-byte:end/disp8
+ 490 $scan-next-byte:check1:
+ 491     # if EAX == ' ' continue
+ 492     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0x20/imm32        # compare EAX
+ 493     74/jump-if-equal  $scan-next-byte:loop/disp8
+ 494     # if EAX == '\t' continue
+ 495     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0x9/imm32         # compare EAX
+ 496     74/jump-if-equal  $scan-next-byte:loop/disp8
+ 497     # if EAX == '\n' continue
+ 498     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xa/imm32         # compare EAX
+ 499     74/jump-if-equal  $scan-next-byte:loop/disp8
+ 500 $scan-next-byte:check2:
+ 501     # if EAX == '#' skip-until-newline(in)
+ 502     3d/compare-with-EAX  0x23/imm32
+ 503     75/jump-if-not-equal  $scan-next-byte:check3/disp8
+ 504     # . skip-until-newline(in)
+ 505     # . . push args
+ 506     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
+ 507     # . . call
+ 508     e8/call  skip-until-newline/disp32
+ 509     # . . discard args
+ 510     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 511     eb/jump  $scan-next-byte:loop/disp8
+ 512 $scan-next-byte:check3:
+ 513     # otherwise error-byte(ed, err, msg, EAX)
+ 514     # . . push args
+ 515     50/push-EAX
+ 516     68/push  "scan-next-byte: invalid byte"/imm32
+ 517     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
+ 518     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0x10/disp8      .                 # push *(EBP+16)
+ 519     # . . call
+ 520     e8/call  error-byte/disp32  # never returns
+ 521 $scan-next-byte:end:
+ 522     # . restore registers
+ 523     # . epilog
+ 524     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 525     5d/pop-to-EBP
+ 526     c3/return
+ 527 
+ 528 test-scan-next-byte:
+ 529     # - check that the first byte of the input is returned
+ 530     # This test uses exit-descriptors. Use EBP for setting up local variables.
+ 531     55/push-EBP
+ 532     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 533     # clear all streams
+ 534     # . clear-stream(_test-stream)
+ 535     # . . push args
+ 536     68/push  _test-stream/imm32
+ 537     # . . call
+ 538     e8/call  clear-stream/disp32
+ 539     # . . discard args
+ 540     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 541     # . clear-stream(_test-buffered-file+4)
+ 542     # . . push args
+ 543     b8/copy-to-EAX  _test-buffered-file/imm32
+ 544     05/add-to-EAX  4/imm32
+ 545     50/push-EAX
+ 546     # . . call
+ 547     e8/call  clear-stream/disp32
+ 548     # . . discard args
+ 549     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 550     # . clear-stream(_test-error-stream)
  551     # . . push args
- 552     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
- 553     51/push-ECX/ed
- 554     # . . call
- 555     e8/call  tailor-exit-descriptor/disp32
- 556     # . . discard args
- 557     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 558     # EAX = scan-next-byte(_test-buffered-file, _test-error-stream, ed)
- 559     # . . push args
- 560     51/push-ECX/ed
- 561     68/push  _test-error-stream/imm32
- 562     68/push  _test-buffered-file/imm32
- 563     # . . call
- 564     e8/call  scan-next-byte/disp32
- 565     # registers except ESP may be clobbered at this point
- 566     # pop args to scan-next-bytes
- 567     # . . discard first 2 args
- 568     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 569     # . . restore ed
- 570     59/pop-to-ECX
- 571     # check that scan-next-byte didn't abort
- 572     # . check-ints-equal(ed->value, 0, msg)
- 573     # . . push args
- 574     68/push  "F - test-scan-next-byte-skips-comment-and-whitespace: unexpected abort"/imm32
- 575     68/push  0/imm32
- 576     # . . push ed->value
- 577     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
- 578     # . . call
- 579     e8/call  check-ints-equal/disp32
- 580     # . . discard args
- 581     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 582     # return if abort
- 583     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
- 584     75/jump-if-not-equal  $test-scan-next-byte-skips-comment-and-whitespace:end/disp8
- 585     # check-ints-equal(EAX, 0x61/a, msg)
- 586     # . . push args
- 587     68/push  "F - test-scan-next-byte-skips-comment-and-whitespace"/imm32
- 588     68/push  0x61/imm32/a
- 589     50/push-EAX
- 590     # . . call
- 591     e8/call  check-ints-equal/disp32
- 592     # . . discard args
- 593     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 594 $test-scan-next-byte-skips-comment-and-whitespace:end:
- 595     # . epilog
- 596     # don't restore ESP from EBP; manually reclaim locals
+ 552     68/push  _test-error-stream/imm32
+ 553     # . . call
+ 554     e8/call  clear-stream/disp32
+ 555     # . . discard args
+ 556     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 557     # . clear-stream(_test-error-buffered-file+4)
+ 558     # . . push args
+ 559     b8/copy-to-EAX  _test-error-buffered-file/imm32
+ 560     05/add-to-EAX  4/imm32
+ 561     50/push-EAX
+ 562     # . . call
+ 563     e8/call  clear-stream/disp32
+ 564     # . . discard args
+ 565     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 566     # initialize '_test-stream' to "abc"
+ 567     # . write(_test-stream, "abc")
+ 568     # . . push args
+ 569     68/push  "abc"/imm32
+ 570     68/push  _test-stream/imm32
+ 571     # . . call
+ 572     e8/call  write/disp32
+ 573     # . . discard args
+ 574     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 575     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
+ 576     # . var ed/ECX : exit-descriptor
+ 577     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+ 578     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+ 579     # . tailor-exit-descriptor(ed, 12)
+ 580     # . . push args
+ 581     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
+ 582     51/push-ECX/ed
+ 583     # . . call
+ 584     e8/call  tailor-exit-descriptor/disp32
+ 585     # . . discard args
+ 586     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 587     # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
+ 588     # . . push args
+ 589     51/push-ECX/ed
+ 590     68/push  _test-error-buffered-file/imm32
+ 591     68/push  _test-buffered-file/imm32
+ 592     # . . call
+ 593     e8/call  scan-next-byte/disp32
+ 594     # registers except ESP may be clobbered at this point
+ 595     # pop args to scan-next-bytes
+ 596     # . . discard first 2 args
  597     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 598     5d/pop-to-EBP
- 599     c3/return
- 600 
- 601 test-scan-next-byte-skips-whitespace-and-comment:
- 602     # - check that the first byte after any whitespace and comments is returned
- 603     # This test uses exit-descriptors. Use EBP for setting up local variables.
- 604     55/push-EBP
- 605     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 606     # clear all streams
- 607     # . clear-stream(_test-stream)
- 608     # . . push args
- 609     68/push  _test-stream/imm32
- 610     # . . call
- 611     e8/call  clear-stream/disp32
- 612     # . . discard args
- 613     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 614     # . clear-stream(_test-buffered-file+4)
+ 598     # . . restore ed
+ 599     59/pop-to-ECX
+ 600     # check that scan-next-byte didn't abort
+ 601     # . check-ints-equal(ed->value, 0, msg)
+ 602     # . . push args
+ 603     68/push  "F - test-scan-next-byte: unexpected abort"/imm32
+ 604     68/push  0/imm32
+ 605     # . . push ed->value
+ 606     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+ 607     # . . call
+ 608     e8/call  check-ints-equal/disp32
+ 609     # . . discard args
+ 610     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 611     # return if abort
+ 612     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
+ 613     75/jump-if-not-equal  $test-scan-next-byte:end/disp8
+ 614     # check-ints-equal(EAX, 0x61/a, msg)
  615     # . . push args
- 616     b8/copy-to-EAX  _test-buffered-file/imm32
- 617     05/add-to-EAX  4/imm32
+ 616     68/push  "F - test-scan-next-byte"/imm32
+ 617     68/push  0x61/imm32/a
  618     50/push-EAX
  619     # . . call
- 620     e8/call  clear-stream/disp32
+ 620     e8/call  check-ints-equal/disp32
  621     # . . discard args
- 622     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 623     # . clear-stream(_test-error-stream)
- 624     # . . push args
- 625     68/push  _test-error-stream/imm32
- 626     # . . call
- 627     e8/call  clear-stream/disp32
- 628     # . . discard args
- 629     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 630     # initialize '_test-stream' to input with leading whitespace and comment
- 631     # . write(_test-stream, comment)
- 632     # . . push args
- 633     68/push  " #x"/imm32
- 634     68/push  _test-stream/imm32
- 635     # . . call
- 636     e8/call  write/disp32
- 637     # . . discard args
- 638     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 639     # . write(_test-stream, Newline)
- 640     # . . push args
- 641     68/push  Newline/imm32
- 642     68/push  _test-stream/imm32
- 643     # . . call
- 644     e8/call  write/disp32
- 645     # . . discard args
- 646     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 647     # . write(_test-stream, real text)
- 648     # . . push args
- 649     68/push  "ab"/imm32
- 650     68/push  _test-stream/imm32
- 651     # . . call
- 652     e8/call  write/disp32
- 653     # . . discard args
- 654     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 655     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
- 656     # . var ed/ECX : exit-descriptor
- 657     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
- 658     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
- 659     # . tailor-exit-descriptor(ed, 12)
+ 622     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 623 $test-scan-next-byte:end:
+ 624     # . epilog
+ 625     # don't restore ESP from EBP; manually reclaim locals
+ 626     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 627     5d/pop-to-EBP
+ 628     c3/return
+ 629 
+ 630 test-scan-next-byte-skips-whitespace:
+ 631     # - check that the first byte after whitespace is returned
+ 632     # This test uses exit-descriptors. Use EBP for setting up local variables.
+ 633     55/push-EBP
+ 634     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 635     # clear all streams
+ 636     # . clear-stream(_test-stream)
+ 637     # . . push args
+ 638     68/push  _test-stream/imm32
+ 639     # . . call
+ 640     e8/call  clear-stream/disp32
+ 641     # . . discard args
+ 642     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 643     # . clear-stream(_test-buffered-file+4)
+ 644     # . . push args
+ 645     b8/copy-to-EAX  _test-buffered-file/imm32
+ 646     05/add-to-EAX  4/imm32
+ 647     50/push-EAX
+ 648     # . . call
+ 649     e8/call  clear-stream/disp32
+ 650     # . . discard args
+ 651     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 652     # . clear-stream(_test-error-stream)
+ 653     # . . push args
+ 654     68/push  _test-error-stream/imm32
+ 655     # . . call
+ 656     e8/call  clear-stream/disp32
+ 657     # . . discard args
+ 658     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 659     # . clear-stream(_test-error-buffered-file+4)
  660     # . . push args
- 661     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
- 662     51/push-ECX/ed
- 663     # . . call
- 664     e8/call  tailor-exit-descriptor/disp32
- 665     # . . discard args
- 666     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 667     # EAX = scan-next-byte(_test-buffered-file, _test-error-stream, ed)
- 668     # . . push args
- 669     51/push-ECX/ed
- 670     68/push  _test-error-stream/imm32
- 671     68/push  _test-buffered-file/imm32
- 672     # . . call
- 673     e8/call  scan-next-byte/disp32
- 674     # registers except ESP may be clobbered at this point
- 675     # pop args to scan-next-bytes
- 676     # . . discard first 2 args
- 677     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 678     # . . restore ed
- 679     59/pop-to-ECX
- 680     # check that scan-next-byte didn't abort
- 681     # . check-ints-equal(ed->value, 0, msg)
+ 661     b8/copy-to-EAX  _test-error-buffered-file/imm32
+ 662     05/add-to-EAX  4/imm32
+ 663     50/push-EAX
+ 664     # . . call
+ 665     e8/call  clear-stream/disp32
+ 666     # . . discard args
+ 667     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 668     # initialize '_test-stream' to input with leading whitespace
+ 669     # . write(_test-stream, text)
+ 670     # . . push args
+ 671     68/push  "  abc"/imm32
+ 672     68/push  _test-stream/imm32
+ 673     # . . call
+ 674     e8/call  write/disp32
+ 675     # . . discard args
+ 676     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 677     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
+ 678     # . var ed/ECX : exit-descriptor
+ 679     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+ 680     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+ 681     # . tailor-exit-descriptor(ed, 12)
  682     # . . push args
- 683     68/push  "F - test-scan-next-byte-skips-whitespace-and-comment: unexpected abort"/imm32
- 684     68/push  0/imm32
- 685     # . . push ed->value
- 686     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
- 687     # . . call
- 688     e8/call  check-ints-equal/disp32
- 689     # . . discard args
- 690     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 691     # return if abort
- 692     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
- 693     75/jump-if-not-equal  $test-scan-next-byte-skips-whitespace-and-comment:end/disp8
- 694     # check-ints-equal(EAX, 0x61/a, msg)
- 695     # . . push args
- 696     68/push  "F - test-scan-next-byte-skips-whitespace-and-comment"/imm32
- 697     68/push  0x61/imm32/a
- 698     50/push-EAX
- 699     # . . call
- 700     e8/call  check-ints-equal/disp32
- 701     # . . discard args
- 702     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 703 $test-scan-next-byte-skips-whitespace-and-comment:end:
- 704     # . epilog
- 705     # don't restore ESP from EBP; manually reclaim locals
- 706     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 707     5d/pop-to-EBP
- 708     c3/return
- 709 
- 710 test-scan-next-byte-reads-final-byte:
- 711     # - check that the final byte in input is returned
- 712     # This test uses exit-descriptors. Use EBP for setting up local variables.
- 713     55/push-EBP
- 714     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 715     # clear all streams
- 716     # . clear-stream(_test-stream)
+ 683     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
+ 684     51/push-ECX/ed
+ 685     # . . call
+ 686     e8/call  tailor-exit-descriptor/disp32
+ 687     # . . discard args
+ 688     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 689     # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
+ 690     # . . push args
+ 691     51/push-ECX/ed
+ 692     68/push  _test-error-buffered-file/imm32
+ 693     68/push  _test-buffered-file/imm32
+ 694     # . . call
+ 695     e8/call  scan-next-byte/disp32
+ 696     # registers except ESP may be clobbered at this point
+ 697     # pop args to scan-next-bytes
+ 698     # . . discard first 2 args
+ 699     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 700     # . . restore ed
+ 701     59/pop-to-ECX
+ 702     # check that scan-next-byte didn't abort
+ 703     # . check-ints-equal(ed->value, 0, msg)
+ 704     # . . push args
+ 705     68/push  "F - test-scan-next-byte-skips-whitespace: unexpected abort"/imm32
+ 706     68/push  0/imm32
+ 707     # . . push ed->value
+ 708     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+ 709     # . . call
+ 710     e8/call  check-ints-equal/disp32
+ 711     # . . discard args
+ 712     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 713     # return if abort
+ 714     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
+ 715     75/jump-if-not-equal  $test-scan-next-byte-skips-whitespace:end/disp8
+ 716     # check-ints-equal(EAX, 0x61/a, msg)
  717     # . . push args
- 718     68/push  _test-stream/imm32
- 719     # . . call
- 720     e8/call  clear-stream/disp32
- 721     # . . discard args
- 722     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 723     # . clear-stream(_test-buffered-file+4)
- 724     # . . push args
- 725     b8/copy-to-EAX  _test-buffered-file/imm32
- 726     05/add-to-EAX  4/imm32
- 727     50/push-EAX
- 728     # . . call
- 729     e8/call  clear-stream/disp32
- 730     # . . discard args
- 731     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 732     # . clear-stream(_test-error-stream)
- 733     # . . push args
- 734     68/push  _test-error-stream/imm32
- 735     # . . call
- 736     e8/call  clear-stream/disp32
- 737     # . . discard args
- 738     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 739     # initialize '_test-stream' to input with single character
- 740     # . write(_test-stream, character)
- 741     # . . push args
- 742     68/push  "a"/imm32
- 743     68/push  _test-stream/imm32
- 744     # . . call
- 745     e8/call  write/disp32
- 746     # . . discard args
- 747     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 748     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
- 749     # . var ed/ECX : exit-descriptor
- 750     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
- 751     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
- 752     # . tailor-exit-descriptor(ed, 12)
- 753     # . . push args
- 754     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
- 755     51/push-ECX/ed
- 756     # . . call
- 757     e8/call  tailor-exit-descriptor/disp32
- 758     # . . discard args
- 759     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 760     # EAX = scan-next-byte(_test-buffered-file, _test-error-stream, ed)
- 761     # . . push args
- 762     51/push-ECX/ed
- 763     68/push  _test-error-stream/imm32
- 764     68/push  _test-buffered-file/imm32
- 765     # . . call
- 766     e8/call  scan-next-byte/disp32
- 767     # registers except ESP may be clobbered at this point
- 768     # pop args to scan-next-bytes
- 769     # . . discard first 2 args
- 770     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 771     # . . restore ed
- 772     59/pop-to-ECX
- 773     # check that scan-next-byte didn't abort
- 774     # . check-ints-equal(ed->value, 0, msg)
- 775     # . . push args
- 776     68/push  "F - test-scan-next-byte-reads-final-byte: unexpected abort"/imm32
- 777     68/push  0/imm32
- 778     # . . push ed->value
- 779     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
- 780     # . . call
- 781     e8/call  check-ints-equal/disp32
- 782     # . . discard args
- 783     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 784     # return if abort
- 785     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
- 786     75/jump-if-not-equal  $test-scan-next-byte-reads-final-byte:end/disp8
- 787     # check-ints-equal(EAX, 0x61/a, msg)
+ 718     68/push  "F - test-scan-next-byte-skips-whitespace"/imm32
+ 719     68/push  0x61/imm32/a
+ 720     50/push-EAX
+ 721     # . . call
+ 722     e8/call  check-ints-equal/disp32
+ 723     # . . discard args
+ 724     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 725 $test-scan-next-byte-skips-whitespace:end:
+ 726     # . epilog
+ 727     # don't restore ESP from EBP; manually reclaim locals
+ 728     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 729     5d/pop-to-EBP
+ 730     c3/return
+ 731 
+ 732 test-scan-next-byte-skips-comment:
+ 733     # - check that the first byte after a comment (and newline) is returned
+ 734     # This test uses exit-descriptors. Use EBP for setting up local variables.
+ 735     55/push-EBP
+ 736     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 737     # clear all streams
+ 738     # . clear-stream(_test-stream)
+ 739     # . . push args
+ 740     68/push  _test-stream/imm32
+ 741     # . . call
+ 742     e8/call  clear-stream/disp32
+ 743     # . . discard args
+ 744     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 745     # . clear-stream(_test-buffered-file+4)
+ 746     # . . push args
+ 747     b8/copy-to-EAX  _test-buffered-file/imm32
+ 748     05/add-to-EAX  4/imm32
+ 749     50/push-EAX
+ 750     # . . call
+ 751     e8/call  clear-stream/disp32
+ 752     # . . discard args
+ 753     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 754     # . clear-stream(_test-error-stream)
+ 755     # . . push args
+ 756     68/push  _test-error-stream/imm32
+ 757     # . . call
+ 758     e8/call  clear-stream/disp32
+ 759     # . . discard args
+ 760     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 761     # . clear-stream(_test-error-buffered-file+4)
+ 762     # . . push args
+ 763     b8/copy-to-EAX  _test-error-buffered-file/imm32
+ 764     05/add-to-EAX  4/imm32
+ 765     50/push-EAX
+ 766     # . . call
+ 767     e8/call  clear-stream/disp32
+ 768     # . . discard args
+ 769     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 770     # initialize '_test-stream' to input with leading comment
+ 771     # . write(_test-stream, comment)
+ 772     # . . push args
+ 773     68/push  "#x"/imm32
+ 774     68/push  _test-stream/imm32
+ 775     # . . call
+ 776     e8/call  write/disp32
+ 777     # . . discard args
+ 778     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 779     # . write(_test-stream, Newline)
+ 780     # . . push args
+ 781     68/push  Newline/imm32
+ 782     68/push  _test-stream/imm32
+ 783     # . . call
+ 784     e8/call  write/disp32
+ 785     # . . discard args
+ 786     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 787     # . write(_test-stream, real text)
  788     # . . push args
- 789     68/push  "F - test-scan-next-byte-reads-final-byte"/imm32
- 790     68/push  0x61/imm32/a
- 791     50/push-EAX
- 792     # . . call
- 793     e8/call  check-ints-equal/disp32
- 794     # . . discard args
- 795     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 796 $test-scan-next-byte-reads-final-byte:end:
- 797     # . epilog
- 798     # don't restore ESP from EBP; manually reclaim locals
- 799     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 800     5d/pop-to-EBP
- 801     c3/return
- 802 
- 803 test-scan-next-byte-handles-eof:
- 804     # - check that the right sentinel value is returned when there's no data remaining to be read
- 805     # This test uses exit-descriptors. Use EBP for setting up local variables.
- 806     55/push-EBP
- 807     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 808     # clear all streams
- 809     # . clear-stream(_test-stream)
- 810     # . . push args
- 811     68/push  _test-stream/imm32
+ 789     68/push  "ab"/imm32
+ 790     68/push  _test-stream/imm32
+ 791     # . . call
+ 792     e8/call  write/disp32
+ 793     # . . discard args
+ 794     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 795     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
+ 796     # . var ed/ECX : exit-descriptor
+ 797     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+ 798     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+ 799     # . tailor-exit-descriptor(ed, 12)
+ 800     # . . push args
+ 801     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
+ 802     51/push-ECX/ed
+ 803     # . . call
+ 804     e8/call  tailor-exit-descriptor/disp32
+ 805     # . . discard args
+ 806     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 807     # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
+ 808     # . . push args
+ 809     51/push-ECX/ed
+ 810     68/push  _test-error-buffered-file/imm32
+ 811     68/push  _test-buffered-file/imm32
  812     # . . call
- 813     e8/call  clear-stream/disp32
- 814     # . . discard args
- 815     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 816     # . clear-stream(_test-buffered-file+4)
- 817     # . . push args
- 818     b8/copy-to-EAX  _test-buffered-file/imm32
- 819     05/add-to-EAX  4/imm32
- 820     50/push-EAX
- 821     # . . call
- 822     e8/call  clear-stream/disp32
- 823     # . . discard args
- 824     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 825     # . clear-stream(_test-error-stream)
- 826     # . . push args
- 827     68/push  _test-error-stream/imm32
- 828     # . . call
- 829     e8/call  clear-stream/disp32
- 830     # . . discard args
- 831     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 832     # leave '_test-stream' empty
- 833     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
- 834     # . var ed/ECX : exit-descriptor
- 835     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
- 836     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
- 837     # . tailor-exit-descriptor(ed, 12)
- 838     # . . push args
- 839     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
- 840     51/push-ECX/ed
- 841     # . . call
- 842     e8/call  tailor-exit-descriptor/disp32
- 843     # . . discard args
- 844     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 845     # EAX = scan-next-byte(_test-buffered-file, _test-error-stream, ed)
- 846     # . . push args
- 847     51/push-ECX/ed
- 848     68/push  _test-error-stream/imm32
- 849     68/push  _test-buffered-file/imm32
- 850     # . . call
- 851     e8/call  scan-next-byte/disp32
- 852     # registers except ESP may be clobbered at this point
- 853     # pop args to scan-next-bytes
- 854     # . . discard first 2 args
- 855     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 856     # . . restore ed
- 857     59/pop-to-ECX
- 858     # check that scan-next-byte didn't abort
- 859     # . check-ints-equal(ed->value, 0, msg)
- 860     # . . push args
- 861     68/push  "F - test-scan-next-byte-handles-eof: unexpected abort"/imm32
- 862     68/push  0/imm32
- 863     # . . push ed->value
- 864     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
- 865     # . . call
- 866     e8/call  check-ints-equal/disp32
- 867     # . . discard args
- 868     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 869     # return if abort
- 870     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
- 871     75/jump-if-not-equal  $test-scan-next-byte-handles-eof:end/disp8
- 872     # check-ints-equal(EAX, 0xffffffff/eof, msg)
+ 813     e8/call  scan-next-byte/disp32
+ 814     # registers except ESP may be clobbered at this point
+ 815     # pop args to scan-next-bytes
+ 816     # . . discard first 2 args
+ 817     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 818     # . . restore ed
+ 819     59/pop-to-ECX
+ 820     # check that scan-next-byte didn't abort
+ 821     # . check-ints-equal(ed->value, 0, msg)
+ 822     # . . push args
+ 823     68/push  "F - test-scan-next-byte-skips-comment: unexpected abort"/imm32
+ 824     68/push  0/imm32
+ 825     # . . push ed->value
+ 826     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+ 827     # . . call
+ 828     e8/call  check-ints-equal/disp32
+ 829     # . . discard args
+ 830     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 831     # return if abort
+ 832     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
+ 833     75/jump-if-not-equal  $test-scan-next-byte-skips-comment:end/disp8
+ 834     # check-ints-equal(EAX, 0x61/a, msg)
+ 835     # . . push args
+ 836     68/push  "F - test-scan-next-byte-skips-comment"/imm32
+ 837     68/push  0x61/imm32/a
+ 838     50/push-EAX
+ 839     # . . call
+ 840     e8/call  check-ints-equal/disp32
+ 841     # . . discard args
+ 842     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 843 $test-scan-next-byte-skips-comment:end:
+ 844     # . epilog
+ 845     # don't restore ESP from EBP; manually reclaim locals
+ 846     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 847     5d/pop-to-EBP
+ 848     c3/return
+ 849 
+ 850 test-scan-next-byte-skips-comment-and-whitespace:
+ 851     # - check that the first byte after a comment and any further whitespace is returned
+ 852     # This test uses exit-descriptors. Use EBP for setting up local variables.
+ 853     55/push-EBP
+ 854     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 855     # clear all streams
+ 856     # . clear-stream(_test-stream)
+ 857     # . . push args
+ 858     68/push  _test-stream/imm32
+ 859     # . . call
+ 860     e8/call  clear-stream/disp32
+ 861     # . . discard args
+ 862     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 863     # . clear-stream(_test-buffered-file+4)
+ 864     # . . push args
+ 865     b8/copy-to-EAX  _test-buffered-file/imm32
+ 866     05/add-to-EAX  4/imm32
+ 867     50/push-EAX
+ 868     # . . call
+ 869     e8/call  clear-stream/disp32
+ 870     # . . discard args
+ 871     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 872     # . clear-stream(_test-error-stream)
  873     # . . push args
- 874     68/push  "F - test-scan-next-byte-handles-eof"/imm32
- 875     68/push  0xffffffff/imm32/eof
- 876     50/push-EAX
- 877     # . . call
- 878     e8/call  check-ints-equal/disp32
- 879     # . . discard args
- 880     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 881 $test-scan-next-byte-handles-eof:end:
- 882     # . epilog
- 883     # don't restore ESP from EBP; manually reclaim locals
- 884     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 885     5d/pop-to-EBP
- 886     c3/return
- 887 
- 888 is-hex-lowercase-byte?:  # c : byte -> bool/EAX
- 889     # . prolog
- 890     55/push-EBP
- 891     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 892     # . save registers
- 893     51/push-ECX
- 894     # ECX = c
- 895     8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
- 896     # return false if c < '0'
- 897     b8/copy-to-EAX  0/imm32/false
- 898     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0x30/imm32        # compare ECX
- 899     7c/jump-if-lesser  $is-hex-lowercase-byte?:end/disp8
- 900     # return false if c > 'f'
- 901     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0x66/imm32        # compare ECX
- 902     7f/jump-if-greater  $is-hex-lowercase-byte?:end/disp8
- 903     # return true if c <= '9'
- 904     b8/copy-to-EAX  1/imm32/true
- 905     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0x39/imm32        # compare ECX
- 906     7e/jump-if-lesser-or-equal  $is-hex-lowercase-byte?:end/disp8
- 907     # return true if c >= 'a'
- 908     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0x61/imm32        # compare ECX
- 909     7d/jump-if-greater-or-equal  $is-hex-lowercase-byte?:end/disp8
- 910     # otherwise return false
- 911     b8/copy-to-EAX  0/imm32/false
- 912 $is-hex-lowercase-byte?:end:
- 913     # . restore registers
- 914     59/pop-to-ECX
- 915     # . epilog
- 916     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 917     5d/pop-to-EBP
- 918     c3/return
- 919 
- 920 test-hex-below-0:
- 921     # is-hex-lowercase-byte?(0x2f)
- 922     # . . push args
- 923     68/push  0x2f/imm32
- 924     # . . call
- 925     e8/call  is-hex-lowercase-byte?/disp32
- 926     # . . discard args
- 927     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 928     # check-ints-equal(EAX, 0, msg)
- 929     # . . push args
- 930     68/push  "F - test-hex-below-0"/imm32
- 931     68/push  0/imm32/false
- 932     50/push-EAX
- 933     # . . call
- 934     e8/call  check-ints-equal/disp32
- 935     # . . discard args
- 936     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 937     c3/return
- 938 
- 939 test-hex-0-to-9:
- 940     # is-hex-lowercase-byte?(0x30)
- 941     # . . push args
- 942     68/push  0x30/imm32
- 943     # . . call
- 944     e8/call  is-hex-lowercase-byte?/disp32
- 945     # . . discard args
- 946     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 947     # check-ints-equal(EAX, 1, msg)
- 948     # . . push args
- 949     68/push  "F - test-hex-at-0"/imm32
- 950     68/push  1/imm32/true
- 951     50/push-EAX
- 952     # . . call
- 953     e8/call  check-ints-equal/disp32
- 954     # . . discard args
- 955     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 956     # is-hex-lowercase-byte?(0x39)
- 957     # . . push args
- 958     68/push  0x39/imm32
- 959     # . . call
- 960     e8/call  is-hex-lowercase-byte?/disp32
- 961     # . . discard args
- 962     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 963     # check-ints-equal(EAX, 1, msg)
- 964     # . . push args
- 965     68/push  "F - test-hex-at-9"/imm32
- 966     68/push  1/imm32/true
- 967     50/push-EAX
- 968     # . . call
- 969     e8/call  check-ints-equal/disp32
- 970     # . . discard args
- 971     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 972     c3/return
- 973 
- 974 test-hex-above-9-to-a:
- 975     # is-hex-lowercase-byte?(0x3a)
- 976     # . . push args
- 977     68/push  0x3a/imm32
- 978     # . . call
- 979     e8/call  is-hex-lowercase-byte?/disp32
- 980     # . . discard args
- 981     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 982     # check-ints-equal(EAX, 0, msg)
- 983     # . . push args
- 984     68/push  "F - test-hex-above-9-to-a"/imm32
- 985     68/push  0/imm32/false
- 986     50/push-EAX
- 987     # . . call
- 988     e8/call  check-ints-equal/disp32
- 989     # . . discard args
- 990     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 991     c3/return
- 992 
- 993 test-hex-a-to-f:
- 994     # is-hex-lowercase-byte?(0x61)
- 995     # . . push args
- 996     68/push  0x61/imm32
- 997     # . . call
- 998     e8/call  is-hex-lowercase-byte?/disp32
- 999     # . . discard args
-1000     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-1001     # check-ints-equal(EAX, 1, msg)
-1002     # . . push args
-1003     68/push  "F - test-hex-at-a"/imm32
-1004     68/push  1/imm32/true
-1005     50/push-EAX
-1006     # . . call
-1007     e8/call  check-ints-equal/disp32
-1008     # . . discard args
-1009     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-1010     # is-hex-lowercase-byte?(0x66)
-1011     # . . push args
-1012     68/push  0x66/imm32
-1013     # . . call
-1014     e8/call  is-hex-lowercase-byte?/disp32
-1015     # . . discard args
-1016     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-1017     # check-ints-equal(EAX, 1, msg)
-1018     # . . push args
-1019     68/push  "F - test-hex-at-f"/imm32
-1020     68/push  1/imm32/true
-1021     50/push-EAX
-1022     # . . call
-1023     e8/call  check-ints-equal/disp32
-1024     # . . discard args
-1025     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-1026     c3/return
-1027 
-1028 test-hex-above-f:
-1029     # is-hex-lowercase-byte?(0x67)
-1030     # . . push args
-1031     68/push  0x67/imm32
-1032     # . . call
-1033     e8/call  is-hex-lowercase-byte?/disp32
-1034     # . . discard args
-1035     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-1036     # check-ints-equal(EAX, 0, msg)
-1037     # . . push args
-1038     68/push  "F - test-hex-above-f"/imm32
-1039     68/push  0/imm32/false
-1040     50/push-EAX
-1041     # . . call
-1042     e8/call  check-ints-equal/disp32
-1043     # . . discard args
-1044     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-1045     c3/return
-1046 
-1047 skip-until-newline:  # in : (address buffered-file) -> <void>
-1048     # pseudocode:
-1049     #   push EAX
-1050     #   repeatedly:
-1051     #     EAX = read-byte(in)
-1052     #     if EAX == 0xffffffff break
-1053     #     if EAX == 0x0a break
-1054     #   pop EAX
-1055     # . prolog
-1056     55/push-EBP
-1057     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-1058     # . save registers
-1059     50/push-EAX
-1060 $skip-until-newline:loop:
-1061     # . EAX = read-byte(in)
-1062     # . . push args
-1063     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
-1064     # . . call
-1065     e8/call  read-byte/disp32
-1066     # . . discard args
-1067     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-1068     # . if EAX == 0xffffffff break
-1069     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xffffffff/imm32  # compare EAX
-1070     74/jump-if-equal  $skip-until-newline:end/disp8
-1071 $aa:
-1072     # . if EAX != 0xa/newline loop
-1073     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xa/imm32         # compare EAX
-1074     75/jump-if-not-equal  $skip-until-newline:loop/disp8
-1075 $skip-until-newline:end:
-1076     # . restore registers
-1077     58/pop-to-EAX
-1078     # . epilog
-1079     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-1080     5d/pop-to-EBP
-1081     c3/return
-1082 
-1083 test-skip-until-newline:
-1084     # - check that the read pointer points after the newline
-1085     # setup
-1086     # . clear-stream(_test-stream)
-1087     # . . push args
-1088     68/push  _test-stream/imm32
-1089     # . . call
-1090     e8/call  clear-stream/disp32
-1091     # . . discard args
-1092     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-1093     # . clear-stream(_test-buffered-file+4)
-1094     # . . push args
-1095     b8/copy-to-EAX  _test-buffered-file/imm32
-1096     05/add-to-EAX  4/imm32
-1097     50/push-EAX
-1098     # . . call
-1099     e8/call  clear-stream/disp32
-1100     # . . discard args
-1101     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-1102     # initialize '_test-stream' to "abc\nde"
-1103     # . write(_test-stream, "abc")
-1104     # . . push args
-1105     68/push  "abc"/imm32
-1106     68/push  _test-stream/imm32
-1107     # . . call
-1108     e8/call  write/disp32
-1109     # . . discard args
-1110     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-1111     # . write(_test-stream, Newline)
-1112     # . . push args
-1113     68/push  Newline/imm32
-1114     68/push  _test-stream/imm32
-1115     # . . call
-1116     e8/call  write/disp32
-1117     # . . discard args
-1118     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-1119     # . write(_test-stream, "de")
-1120     # . . push args
-1121     68/push  "de"/imm32
-1122     68/push  _test-stream/imm32
-1123     # . . call
-1124     e8/call  write/disp32
-1125     # . . discard args
-1126     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-1127     # skip-until-newline(_test-buffered-file)
-1128     # . . push args
-1129     68/push  _test-buffered-file/imm32
-1130     # . . call
-1131     e8/call  skip-until-newline/disp32
-1132     # . . discard args
-1133     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-1134     # check-ints-equal(_test-buffered-file->read, 4, msg)
-1135     # . . push args
-1136     68/push  "F - test-skip-until-newline"/imm32
-1137     68/push  4/imm32
-1138     b8/copy-to-EAX  _test-buffered-file/imm32
-1139     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           8/disp8         .                 # push *(EAX+8)
-1140     # . . call
-1141     e8/call  check-ints-equal/disp32
-1142     # . . discard args
-1143     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-1144     # . end
-1145     c3/return
-1146 
-1147 == data
-1148 
-1149 _test-output-stream:
-1150     # current write index
-1151     00 00 00 00
-1152     # current read index
-1153     00 00 00 00
-1154     # length (= 8)
-1155     08 00 00 00
-1156     # data
-1157     00 00 00 00 00 00 00 00  # 8 bytes
-1158 
-1159 _test-error-stream:
-1160     # current write index
-1161     00 00 00 00
-1162     # current read index
-1163     00 00 00 00
-1164     # length (= 8)
-1165     08 00 00 00
-1166     # data
-1167     00 00 00 00 00 00 00 00  # 8 bytes
-1168 
-1169 # . . vim:nowrap:textwidth=0
+ 874     68/push  _test-error-stream/imm32
+ 875     # . . call
+ 876     e8/call  clear-stream/disp32
+ 877     # . . discard args
+ 878     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 879     # . clear-stream(_test-error-buffered-file+4)
+ 880     # . . push args
+ 881     b8/copy-to-EAX  _test-error-buffered-file/imm32
+ 882     05/add-to-EAX  4/imm32
+ 883     50/push-EAX
+ 884     # . . call
+ 885     e8/call  clear-stream/disp32
+ 886     # . . discard args
+ 887     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 888     # initialize '_test-stream' to input with leading comment and more whitespace after newline
+ 889     # . write(_test-stream, comment)
+ 890     # . . push args
+ 891     68/push  "#x"/imm32
+ 892     68/push  _test-stream/imm32
+ 893     # . . call
+ 894     e8/call  write/disp32
+ 895     # . . discard args
+ 896     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 897     # . write(_test-stream, Newline)
+ 898     # . . push args
+ 899     68/push  Newline/imm32
+ 900     68/push  _test-stream/imm32
+ 901     # . . call
+ 902     e8/call  write/disp32
+ 903     # . . discard args
+ 904     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 905     # . write(_test-stream, real text)
+ 906     # . . push args
+ 907     68/push  " ab"/imm32
+ 908     68/push  _test-stream/imm32
+ 909     # . . call
+ 910     e8/call  write/disp32
+ 911     # . . discard args
+ 912     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 913     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
+ 914     # . var ed/ECX : exit-descriptor
+ 915     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+ 916     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+ 917     # . tailor-exit-descriptor(ed, 12)
+ 918     # . . push args
+ 919     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
+ 920     51/push-ECX/ed
+ 921     # . . call
+ 922     e8/call  tailor-exit-descriptor/disp32
+ 923     # . . discard args
+ 924     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 925     # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
+ 926     # . . push args
+ 927     51/push-ECX/ed
+ 928     68/push  _test-error-buffered-file/imm32
+ 929     68/push  _test-buffered-file/imm32
+ 930     # . . call
+ 931     e8/call  scan-next-byte/disp32
+ 932     # registers except ESP may be clobbered at this point
+ 933     # pop args to scan-next-bytes
+ 934     # . . discard first 2 args
+ 935     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 936     # . . restore ed
+ 937     59/pop-to-ECX
+ 938     # check that scan-next-byte didn't abort
+ 939     # . check-ints-equal(ed->value, 0, msg)
+ 940     # . . push args
+ 941     68/push  "F - test-scan-next-byte-skips-comment-and-whitespace: unexpected abort"/imm32
+ 942     68/push  0/imm32
+ 943     # . . push ed->value
+ 944     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+ 945     # . . call
+ 946     e8/call  check-ints-equal/disp32
+ 947     # . . discard args
+ 948     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 949     # return if abort
+ 950     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
+ 951     75/jump-if-not-equal  $test-scan-next-byte-skips-comment-and-whitespace:end/disp8
+ 952     # check-ints-equal(EAX, 0x61/a, msg)
+ 953     # . . push args
+ 954     68/push  "F - test-scan-next-byte-skips-comment-and-whitespace"/imm32
+ 955     68/push  0x61/imm32/a
+ 956     50/push-EAX
+ 957     # . . call
+ 958     e8/call  check-ints-equal/disp32
+ 959     # . . discard args
+ 960     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 961 $test-scan-next-byte-skips-comment-and-whitespace:end:
+ 962     # . epilog
+ 963     # don't restore ESP from EBP; manually reclaim locals
+ 964     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 965     5d/pop-to-EBP
+ 966     c3/return
+ 967 
+ 968 test-scan-next-byte-skips-whitespace-and-comment:
+ 969     # - check that the first byte after any whitespace and comments is returned
+ 970     # This test uses exit-descriptors. Use EBP for setting up local variables.
+ 971     55/push-EBP
+ 972     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 973     # clear all streams
+ 974     # . clear-stream(_test-stream)
+ 975     # . . push args
+ 976     68/push  _test-stream/imm32
+ 977     # . . call
+ 978     e8/call  clear-stream/disp32
+ 979     # . . discard args
+ 980     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 981     # . clear-stream(_test-buffered-file+4)
+ 982     # . . push args
+ 983     b8/copy-to-EAX  _test-buffered-file/imm32
+ 984     05/add-to-EAX  4/imm32
+ 985     50/push-EAX
+ 986     # . . call
+ 987     e8/call  clear-stream/disp32
+ 988     # . . discard args
+ 989     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 990     # . clear-stream(_test-error-stream)
+ 991     # . . push args
+ 992     68/push  _test-error-stream/imm32
+ 993     # . . call
+ 994     e8/call  clear-stream/disp32
+ 995     # . . discard args
+ 996     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 997     # . clear-stream(_test-error-buffered-file+4)
+ 998     # . . push args
+ 999     b8/copy-to-EAX  _test-error-buffered-file/imm32
+1000     05/add-to-EAX  4/imm32
+1001     50/push-EAX
+1002     # . . call
+1003     e8/call  clear-stream/disp32
+1004     # . . discard args
+1005     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1006     # initialize '_test-stream' to input with leading whitespace and comment
+1007     # . write(_test-stream, comment)
+1008     # . . push args
+1009     68/push  " #x"/imm32
+1010     68/push  _test-stream/imm32
+1011     # . . call
+1012     e8/call  write/disp32
+1013     # . . discard args
+1014     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1015     # . write(_test-stream, Newline)
+1016     # . . push args
+1017     68/push  Newline/imm32
+1018     68/push  _test-stream/imm32
+1019     # . . call
+1020     e8/call  write/disp32
+1021     # . . discard args
+1022     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1023     # . write(_test-stream, real text)
+1024     # . . push args
+1025     68/push  "ab"/imm32
+1026     68/push  _test-stream/imm32
+1027     # . . call
+1028     e8/call  write/disp32
+1029     # . . discard args
+1030     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1031     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
+1032     # . var ed/ECX : exit-descriptor
+1033     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+1034     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+1035     # . tailor-exit-descriptor(ed, 12)
+1036     # . . push args
+1037     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
+1038     51/push-ECX/ed
+1039     # . . call
+1040     e8/call  tailor-exit-descriptor/disp32
+1041     # . . discard args
+1042     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1043     # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
+1044     # . . push args
+1045     51/push-ECX/ed
+1046     68/push  _test-error-buffered-file/imm32
+1047     68/push  _test-buffered-file/imm32
+1048     # . . call
+1049     e8/call  scan-next-byte/disp32
+1050     # registers except ESP may be clobbered at this point
+1051     # pop args to scan-next-bytes
+1052     # . . discard first 2 args
+1053     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1054     # . . restore ed
+1055     59/pop-to-ECX
+1056     # check that scan-next-byte didn't abort
+1057     # . check-ints-equal(ed->value, 0, msg)
+1058     # . . push args
+1059     68/push  "F - test-scan-next-byte-skips-whitespace-and-comment: unexpected abort"/imm32
+1060     68/push  0/imm32
+1061     # . . push ed->value
+1062     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+1063     # . . call
+1064     e8/call  check-ints-equal/disp32
+1065     # . . discard args
+1066     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1067     # return if abort
+1068     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
+1069     75/jump-if-not-equal  $test-scan-next-byte-skips-whitespace-and-comment:end/disp8
+1070     # check-ints-equal(EAX, 0x61/a, msg)
+1071     # . . push args
+1072     68/push  "F - test-scan-next-byte-skips-whitespace-and-comment"/imm32
+1073     68/push  0x61/imm32/a
+1074     50/push-EAX
+1075     # . . call
+1076     e8/call  check-ints-equal/disp32
+1077     # . . discard args
+1078     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1079 $test-scan-next-byte-skips-whitespace-and-comment:end:
+1080     # . epilog
+1081     # don't restore ESP from EBP; manually reclaim locals
+1082     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1083     5d/pop-to-EBP
+1084     c3/return
+1085 
+1086 test-scan-next-byte-reads-final-byte:
+1087     # - check that the final byte in input is returned
+1088     # This test uses exit-descriptors. Use EBP for setting up local variables.
+1089     55/push-EBP
+1090     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+1091     # clear all streams
+1092     # . clear-stream(_test-stream)
+1093     # . . push args
+1094     68/push  _test-stream/imm32
+1095     # . . call
+1096     e8/call  clear-stream/disp32
+1097     # . . discard args
+1098     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1099     # . clear-stream(_test-buffered-file+4)
+1100     # . . push args
+1101     b8/copy-to-EAX  _test-buffered-file/imm32
+1102     05/add-to-EAX  4/imm32
+1103     50/push-EAX
+1104     # . . call
+1105     e8/call  clear-stream/disp32
+1106     # . . discard args
+1107     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1108     # . clear-stream(_test-error-stream)
+1109     # . . push args
+1110     68/push  _test-error-stream/imm32
+1111     # . . call
+1112     e8/call  clear-stream/disp32
+1113     # . . discard args
+1114     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1115     # . clear-stream(_test-error-buffered-file+4)
+1116     # . . push args
+1117     b8/copy-to-EAX  _test-error-buffered-file/imm32
+1118     05/add-to-EAX  4/imm32
+1119     50/push-EAX
+1120     # . . call
+1121     e8/call  clear-stream/disp32
+1122     # . . discard args
+1123     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1124     # initialize '_test-stream' to input with single character
+1125     # . write(_test-stream, character)
+1126     # . . push args
+1127     68/push  "a"/imm32
+1128     68/push  _test-stream/imm32
+1129     # . . call
+1130     e8/call  write/disp32
+1131     # . . discard args
+1132     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1133     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
+1134     # . var ed/ECX : exit-descriptor
+1135     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+1136     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+1137     # . tailor-exit-descriptor(ed, 12)
+1138     # . . push args
+1139     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
+1140     51/push-ECX/ed
+1141     # . . call
+1142     e8/call  tailor-exit-descriptor/disp32
+1143     # . . discard args
+1144     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1145     # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
+1146     # . . push args
+1147     51/push-ECX/ed
+1148     68/push  _test-error-buffered-file/imm32
+1149     68/push  _test-buffered-file/imm32
+1150     # . . call
+1151     e8/call  scan-next-byte/disp32
+1152     # registers except ESP may be clobbered at this point
+1153     # pop args to scan-next-bytes
+1154     # . . discard first 2 args
+1155     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1156     # . . restore ed
+1157     59/pop-to-ECX
+1158     # check that scan-next-byte didn't abort
+1159     # . check-ints-equal(ed->value, 0, msg)
+1160     # . . push args
+1161     68/push  "F - test-scan-next-byte-reads-final-byte: unexpected abort"/imm32
+1162     68/push  0/imm32
+1163     # . . push ed->value
+1164     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+1165     # . . call
+1166     e8/call  check-ints-equal/disp32
+1167     # . . discard args
+1168     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1169     # return if abort
+1170     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
+1171     75/jump-if-not-equal  $test-scan-next-byte-reads-final-byte:end/disp8
+1172     # check-ints-equal(EAX, 0x61/a, msg)
+1173     # . . push args
+1174     68/push  "F - test-scan-next-byte-reads-final-byte"/imm32
+1175     68/push  0x61/imm32/a
+1176     50/push-EAX
+1177     # . . call
+1178     e8/call  check-ints-equal/disp32
+1179     # . . discard args
+1180     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1181 $test-scan-next-byte-reads-final-byte:end:
+1182     # . epilog
+1183     # don't restore ESP from EBP; manually reclaim locals
+1184     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1185     5d/pop-to-EBP
+1186     c3/return
+1187 
+1188 test-scan-next-byte-handles-eof:
+1189     # - check that the right sentinel value is returned when there's no data remaining to be read
+1190     # This test uses exit-descriptors. Use EBP for setting up local variables.
+1191     55/push-EBP
+1192     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+1193     # clear all streams
+1194     # . clear-stream(_test-stream)
+1195     # . . push args
+1196     68/push  _test-stream/imm32
+1197     # . . call
+1198     e8/call  clear-stream/disp32
+1199     # . . discard args
+1200     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1201     # . clear-stream(_test-buffered-file+4)
+1202     # . . push args
+1203     b8/copy-to-EAX  _test-buffered-file/imm32
+1204     05/add-to-EAX  4/imm32
+1205     50/push-EAX
+1206     # . . call
+1207     e8/call  clear-stream/disp32
+1208     # . . discard args
+1209     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1210     # . clear-stream(_test-error-stream)
+1211     # . . push args
+1212     68/push  _test-error-stream/imm32
+1213     # . . call
+1214     e8/call  clear-stream/disp32
+1215     # . . discard args
+1216     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1217     # . clear-stream(_test-error-buffered-file+4)
+1218     # . . push args
+1219     b8/copy-to-EAX  _test-error-buffered-file/imm32
+1220     05/add-to-EAX  4/imm32
+1221     50/push-EAX
+1222     # . . call
+1223     e8/call  clear-stream/disp32
+1224     # . . discard args
+1225     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1226     # leave '_test-stream' empty
+1227     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
+1228     # . var ed/ECX : exit-descriptor
+1229     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+1230     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+1231     # . tailor-exit-descriptor(ed, 12)
+1232     # . . push args
+1233     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
+1234     51/push-ECX/ed
+1235     # . . call
+1236     e8/call  tailor-exit-descriptor/disp32
+1237     # . . discard args
+1238     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1239     # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
+1240     # . . push args
+1241     51/push-ECX/ed
+1242     68/push  _test-error-buffered-file/imm32
+1243     68/push  _test-buffered-file/imm32
+1244     # . . call
+1245     e8/call  scan-next-byte/disp32
+1246     # registers except ESP may be clobbered at this point
+1247     # pop args to scan-next-bytes
+1248     # . . discard first 2 args
+1249     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1250     # . . restore ed
+1251     59/pop-to-ECX
+1252     # check that scan-next-byte didn't abort
+1253     # . check-ints-equal(ed->value, 0, msg)
+1254     # . . push args
+1255     68/push  "F - test-scan-next-byte-handles-eof: unexpected abort"/imm32
+1256     68/push  0/imm32
+1257     # . . push ed->value
+1258     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+1259     # . . call
+1260     e8/call  check-ints-equal/disp32
+1261     # . . discard args
+1262     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1263     # return if abort
+1264     81          7/subop/compare     1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         0/imm32           # compare *(ECX+4)
+1265     75/jump-if-not-equal  $test-scan-next-byte-handles-eof:end/disp8
+1266     # check-ints-equal(EAX, 0xffffffff/eof, msg)
+1267     # . . push args
+1268     68/push  "F - test-scan-next-byte-handles-eof"/imm32
+1269     68/push  0xffffffff/imm32/eof
+1270     50/push-EAX
+1271     # . . call
+1272     e8/call  check-ints-equal/disp32
+1273     # . . discard args
+1274     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1275 $test-scan-next-byte-handles-eof:end:
+1276     # . epilog
+1277     # don't restore ESP from EBP; manually reclaim locals
+1278     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1279     5d/pop-to-EBP
+1280     c3/return
+1281 
+1282 test-scan-next-byte-aborts-on-invalid-byte:
+1283     # - check that the a bad byte immediately aborts
+1284     # This test uses exit-descriptors. Use EBP for setting up local variables.
+1285     55/push-EBP
+1286     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+1287     # clear all streams
+1288     # . clear-stream(_test-stream)
+1289     # . . push args
+1290     68/push  _test-stream/imm32
+1291     # . . call
+1292     e8/call  clear-stream/disp32
+1293     # . . discard args
+1294     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1295     # . clear-stream(_test-buffered-file+4)
+1296     # . . push args
+1297     b8/copy-to-EAX  _test-buffered-file/imm32
+1298     05/add-to-EAX  4/imm32
+1299     50/push-EAX
+1300     # . . call
+1301     e8/call  clear-stream/disp32
+1302     # . . discard args
+1303     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1304     # . clear-stream(_test-error-stream)
+1305     # . . push args
+1306     68/push  _test-error-stream/imm32
+1307     # . . call
+1308     e8/call  clear-stream/disp32
+1309     # . . discard args
+1310     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1311     # . clear-stream(_test-error-buffered-file+4)
+1312     # . . push args
+1313     b8/copy-to-EAX  _test-error-buffered-file/imm32
+1314     05/add-to-EAX  4/imm32
+1315     50/push-EAX
+1316     # . . call
+1317     e8/call  clear-stream/disp32
+1318     # . . discard args
+1319     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1320     # initialize '_test-stream' to "x"
+1321     # . write(_test-stream, "x")
+1322     # . . push args
+1323     68/push  "x"/imm32
+1324     68/push  _test-stream/imm32
+1325     # . . call
+1326     e8/call  write/disp32
+1327     # . . discard args
+1328     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1329     # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below
+1330     # . var ed/ECX : exit-descriptor
+1331     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+1332     8d/copy-address                 0/mod/indirect  4/rm32/sib    4/base/ESP  4/index/none  .           1/r32/ECX   .               .                 # copy ESP to ECX
+1333     # . tailor-exit-descriptor(ed, 12)
+1334     # . . push args
+1335     68/push  0xc/imm32/nbytes-of-args-for-scan-next-byte
+1336     51/push-ECX/ed
+1337     # . . call
+1338     e8/call  tailor-exit-descriptor/disp32
+1339     # . . discard args
+1340     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1341     # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed)
+1342     # . . push args
+1343     51/push-ECX/ed
+1344     68/push  _test-error-buffered-file/imm32
+1345     68/push  _test-buffered-file/imm32
+1346     # . . call
+1347     e8/call  scan-next-byte/disp32
+1348     # registers except ESP may be clobbered at this point
+1349     # pop args to scan-next-bytes
+1350     # . . discard first 2 args
+1351     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1352     # . . restore ed
+1353     59/pop-to-ECX
+1354     # check that scan-next-byte aborted
+1355     # . check-ints-equal(ed->value, 2, msg)
+1356     # . . push args
+1357     68/push  "F - test-scan-next-byte-aborts-on-invalid-byte"/imm32
+1358     68/push  2/imm32
+1359     # . . push ed->value
+1360     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
+1361     # . . call
+1362     e8/call  check-ints-equal/disp32
+1363     # . . discard args
+1364     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1365 $test-scan-next-byte-aborts-on-invalid-byte:end:
+1366     # . epilog
+1367     # don't restore ESP from EBP; manually reclaim locals
+1368     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1369     5d/pop-to-EBP
+1370     c3/return
+1371 
+1372 is-hex-lowercase-byte?:  # c : byte -> bool/EAX
+1373     # . prolog
+1374     55/push-EBP
+1375     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+1376     # . save registers
+1377     51/push-ECX
+1378     # ECX = c
+1379     8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
+1380     # return false if c < '0'
+1381     b8/copy-to-EAX  0/imm32/false
+1382     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0x30/imm32        # compare ECX
+1383     7c/jump-if-lesser  $is-hex-lowercase-byte?:end/disp8
+1384     # return false if c > 'f'
+1385     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0x66/imm32        # compare ECX
+1386     7f/jump-if-greater  $is-hex-lowercase-byte?:end/disp8
+1387     # return true if c <= '9'
+1388     b8/copy-to-EAX  1/imm32/true
+1389     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0x39/imm32        # compare ECX
+1390     7e/jump-if-lesser-or-equal  $is-hex-lowercase-byte?:end/disp8
+1391     # return true if c >= 'a'
+1392     81          7/subop/compare     3/mod/direct    1/rm32/ECX    .           .             .           .           .               0x61/imm32        # compare ECX
+1393     7d/jump-if-greater-or-equal  $is-hex-lowercase-byte?:end/disp8
+1394     # otherwise return false
+1395     b8/copy-to-EAX  0/imm32/false
+1396 $is-hex-lowercase-byte?:end:
+1397     # . restore registers
+1398     59/pop-to-ECX
+1399     # . epilog
+1400     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+1401     5d/pop-to-EBP
+1402     c3/return
+1403 
+1404 test-hex-below-0:
+1405     # is-hex-lowercase-byte?(0x2f)
+1406     # . . push args
+1407     68/push  0x2f/imm32
+1408     # . . call
+1409     e8/call  is-hex-lowercase-byte?/disp32
+1410     # . . discard args
+1411     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1412     # check-ints-equal(EAX, 0, msg)
+1413     # . . push args
+1414     68/push  "F - test-hex-below-0"/imm32
+1415     68/push  0/imm32/false
+1416     50/push-EAX
+1417     # . . call
+1418     e8/call  check-ints-equal/disp32
+1419     # . . discard args
+1420     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1421     c3/return
+1422 
+1423 test-hex-0-to-9:
+1424     # is-hex-lowercase-byte?(0x30)
+1425     # . . push args
+1426     68/push  0x30/imm32
+1427     # . . call
+1428     e8/call  is-hex-lowercase-byte?/disp32
+1429     # . . discard args
+1430     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1431     # check-ints-equal(EAX, 1, msg)
+1432     # . . push args
+1433     68/push  "F - test-hex-at-0"/imm32
+1434     68/push  1/imm32/true
+1435     50/push-EAX
+1436     # . . call
+1437     e8/call  check-ints-equal/disp32
+1438     # . . discard args
+1439     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1440     # is-hex-lowercase-byte?(0x39)
+1441     # . . push args
+1442     68/push  0x39/imm32
+1443     # . . call
+1444     e8/call  is-hex-lowercase-byte?/disp32
+1445     # . . discard args
+1446     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1447     # check-ints-equal(EAX, 1, msg)
+1448     # . . push args
+1449     68/push  "F - test-hex-at-9"/imm32
+1450     68/push  1/imm32/true
+1451     50/push-EAX
+1452     # . . call
+1453     e8/call  check-ints-equal/disp32
+1454     # . . discard args
+1455     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1456     c3/return
+1457 
+1458 test-hex-above-9-to-a:
+1459     # is-hex-lowercase-byte?(0x3a)
+1460     # . . push args
+1461     68/push  0x3a/imm32
+1462     # . . call
+1463     e8/call  is-hex-lowercase-byte?/disp32
+1464     # . . discard args
+1465     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1466     # check-ints-equal(EAX, 0, msg)
+1467     # . . push args
+1468     68/push  "F - test-hex-above-9-to-a"/imm32
+1469     68/push  0/imm32/false
+1470     50/push-EAX
+1471     # . . call
+1472     e8/call  check-ints-equal/disp32
+1473     # . . discard args
+1474     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1475     c3/return
+1476 
+1477 test-hex-a-to-f:
+1478     # is-hex-lowercase-byte?(0x61)
+1479     # . . push args
+1480     68/push  0x61/imm32
+1481     # . . call
+1482     e8/call  is-hex-lowercase-byte?/disp32
+1483     # . . discard args
+1484     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1485     # check-ints-equal(EAX, 1, msg)
+1486     # . . push args
+1487     68/push  "F - test-hex-at-a"/imm32
+1488     68/push  1/imm32/true
+1489     50/push-EAX
+1490     # . . call
+1491     e8/call  check-ints-equal/disp32
+1492     # . . discard args
+1493     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1494     # is-hex-lowercase-byte?(0x66)
+1495     # . . push args
+1496     68/push  0x66/imm32
+1497     # . . call
+1498     e8/call  is-hex-lowercase-byte?/disp32
+1499     # . . discard args
+1500     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1501     # check-ints-equal(EAX, 1, msg)
+1502     # . . push args
+1503     68/push  "F - test-hex-at-f"/imm32
+1504     68/push  1/imm32/true
+1505     50/push-EAX
+1506     # . . call
+1507     e8/call  check-ints-equal/disp32
+1508     # . . discard args
+1509     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1510     c3/return
+1511 
+1512 test-hex-above-f:
+1513     # is-hex-lowercase-byte?(0x67)
+1514     # . . push args
+1515     68/push  0x67/imm32
+1516     # . . call
+1517     e8/call  is-hex-lowercase-byte?/disp32
+1518     # . . discard args
+1519     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1520     # check-ints-equal(EAX, 0, msg)
+1521     # . . push args
+1522     68/push  "F - test-hex-above-f"/imm32
+1523     68/push  0/imm32/false
+1524     50/push-EAX
+1525     # . . call
+1526     e8/call  check-ints-equal/disp32
+1527     # . . discard args
+1528     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1529     c3/return
+1530 
+1531 skip-until-newline:  # in : (address buffered-file) -> <void>
+1532     # pseudocode:
+1533     #   push EAX
+1534     #   repeatedly:
+1535     #     EAX = read-byte(in)
+1536     #     if EAX == 0xffffffff break
+1537     #     if EAX == 0x0a break
+1538     #   pop EAX
+1539     # . prolog
+1540     55/push-EBP
+1541     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+1542     # . save registers
+1543     50/push-EAX
+1544 $skip-until-newline:loop:
+1545     # . EAX = read-byte(in)
+1546     # . . push args
+1547     ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           8/disp8         .                 # push *(EBP+8)
+1548     # . . call
+1549     e8/call  read-byte/disp32
+1550     # . . discard args
+1551     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1552     # . if EAX == 0xffffffff break
+1553     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xffffffff/imm32  # compare EAX
+1554     74/jump-if-equal  $skip-until-newline:end/disp8
+1555 $aa:
+1556     # . if EAX != 0xa/newline loop
+1557     81          7/subop/compare     3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xa/imm32         # compare EAX
+1558     75/jump-if-not-equal  $skip-until-newline:loop/disp8
+1559 $skip-until-newline:end:
+1560     # . restore registers
+1561     58/pop-to-EAX
+1562     # . epilog
+1563     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+1564     5d/pop-to-EBP
+1565     c3/return
+1566 
+1567 test-skip-until-newline:
+1568     # - check that the read pointer points after the newline
+1569     # setup
+1570     # . clear-stream(_test-stream)
+1571     # . . push args
+1572     68/push  _test-stream/imm32
+1573     # . . call
+1574     e8/call  clear-stream/disp32
+1575     # . . discard args
+1576     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1577     # . clear-stream(_test-buffered-file+4)
+1578     # . . push args
+1579     b8/copy-to-EAX  _test-buffered-file/imm32
+1580     05/add-to-EAX  4/imm32
+1581     50/push-EAX
+1582     # . . call
+1583     e8/call  clear-stream/disp32
+1584     # . . discard args
+1585     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1586     # initialize '_test-stream' to "abc\nde"
+1587     # . write(_test-stream, "abc")
+1588     # . . push args
+1589     68/push  "abc"/imm32
+1590     68/push  _test-stream/imm32
+1591     # . . call
+1592     e8/call  write/disp32
+1593     # . . discard args
+1594     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1595     # . write(_test-stream, Newline)
+1596     # . . push args
+1597     68/push  Newline/imm32
+1598     68/push  _test-stream/imm32
+1599     # . . call
+1600     e8/call  write/disp32
+1601     # . . discard args
+1602     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1603     # . write(_test-stream, "de")
+1604     # . . push args
+1605     68/push  "de"/imm32
+1606     68/push  _test-stream/imm32
+1607     # . . call
+1608     e8/call  write/disp32
+1609     # . . discard args
+1610     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1611     # skip-until-newline(_test-buffered-file)
+1612     # . . push args
+1613     68/push  _test-buffered-file/imm32
+1614     # . . call
+1615     e8/call  skip-until-newline/disp32
+1616     # . . discard args
+1617     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1618     # check-ints-equal(_test-buffered-file->read, 4, msg)
+1619     # . . push args
+1620     68/push  "F - test-skip-until-newline"/imm32
+1621     68/push  4/imm32
+1622     b8/copy-to-EAX  _test-buffered-file/imm32
+1623     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           8/disp8         .                 # push *(EAX+8)
+1624     # . . call
+1625     e8/call  check-ints-equal/disp32
+1626     # . . discard args
+1627     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1628     # . end
+1629     c3/return
+1630 
+1631 == data
+1632 
+1633 _test-error-stream:
+1634     # current write index
+1635     00 00 00 00
+1636     # current read index
+1637     00 00 00 00
+1638     # length (= 8)
+1639     08 00 00 00
+1640     # data
+1641     00 00 00 00 00 00 00 00  # 8 bytes
+1642 
+1643 # a test buffered file for _test-stream
+1644 _test-error-buffered-file:
+1645     # file descriptor or (address stream)
+1646     _test-error-stream/imm32
+1647     # current write index
+1648     00 00 00 00
+1649     # current read index
+1650     00 00 00 00
+1651     # length (6)
+1652     06 00 00 00
+1653     # data
+1654     00 00 00 00 00 00  # 6 bytes
+1655 
+1656 # . . vim:nowrap:textwidth=0
 
-- cgit 1.4.1-2-gfad0