https://github.com/akkartik/mu/blob/master/subx/073next-token.subx

      1 == code
      2 #   instruction                     effective address                                                   register    displacement    immediate
      3 # . op          subop               mod             rm32          base        index         scale       r32
      4 # . 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
      5
      6 #? Entry:  # run a single test, while debugging
      7 #? e8/call test-next-token-from-slice/disp32
      8 #?     # syscall(exit, Num-test-failures)
      9 #?     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
     10 #?     b8/copy-to-EAX  1/imm32/exit
     11 #?     cd/syscall  0x80/imm8
     12
     13 # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary)
     14 # on reaching end of file, return an empty interval
     15 next-token:  # in : (address stream), delimiter : byte, out : (address slice)
     16     # . prolog
     17     55/push-EBP
     18     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
     19     # . save registers
     20     50/push-EAX
     21     51/push-ECX
     22     56/push-ESI
     23     57/push-EDI
     24     # ESI = in
     25     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
     26     # EDI = out
     27     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0x10/disp8      .                 # copy *(EBP+16) to EDI
     28     # skip-chars-matching(in, delimiter)
     29     # . . push args
     30     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
     31     56/push-ESI
     32     # . . call
     33     e8/call  skip-chars-matching/disp32
     34     # . . discard args
     35     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
     36     # out->start = &in->data[in->read]
     37     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
     38     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/EAX   0xc/disp8       .                 # copy ESI+ECX+12 to EAX
     39     89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy EAX to *EDI
     40     # skip-chars-not-matching(in, delimiter)
     41     # . . push args
     42     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
     43     56/push-ESI
     44     # . . call
     45     e8/call  skip-chars-not-matching/disp32
     46     # . . discard args
     47     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
     48     # out->end = &in->data[in->read]
     49     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
     50     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/EAX   0xc/disp8       .                 # copy ESI+ECX+12 to EAX
     51     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EAX to *(EDI+4)
     52     # . restore registers
     53     5f/pop-to-EDI
     54     5e/pop-to-ESI
     55     59/pop-to-ECX
     56     58/pop-to-EAX
     57     # . epilog
     58     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
     59     5d/pop-to-EBP
     60     c3/return
     61
     62 test-next-token:
     63     # . prolog
     64     55/push-EBP
     65     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
     66     # setup
     67     # . clear-stream(_test-stream)
     68     # . . push args
     69     68/push  _test-stream/imm32
     70     # . . call
     71     e8/call  clear-stream/disp32
     72     # . . discard args
     73     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
     74     # var slice/ECX = {0, 0}
     75     68/push  0/imm32/end
     76     68/push  0/imm32/start
     77     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
     78     # write(_test-stream, "  ab")
     79     # . . push args
     80     68/push  "  ab"/imm32
     81     68/push  _test-stream/imm32
     82     # . . call
     83     e8/call  write/disp32
     84     # . . discard args
     85     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
     86     # next-token(_test-stream, 0x20/space, slice)
     87     # . . push args
     88     51/push-ECX
     89     68/push  0x20/imm32
     90     68/push  _test-stream/imm32
     91     # . . call
     92     e8/call  next-token/disp32
     93     # . . discard args
     94     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     95     # check-ints-equal(slice->start - _test-stream->data, 2, msg)
     96     # . check-ints-equal(slice->start - _test-stream, 14, msg)
     97     # . . push args
     98     68/push  "F - test-next-token: start"/imm32
     99     68/push  0xe/imm32
    100     # . . push slice->start - _test-stream
    101     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
    102     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-stream/imm32 # subtract from EAX
    103     50/push-EAX
    104     # . . call
    105     e8/call  check-ints-equal/disp32
    106     # . . discard args
    107     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    108     # check-ints-equal(slice->end - _test-stream->data, 4, msg)
    109     # . check-ints-equal(slice->end - _test-stream, 16, msg)
    110     # . . push args
    111     68/push  "F - test-next-token: end"/imm32
    112     68/push  0x10/imm32
    113     # . . push slice->end - _test-stream
    114     8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ECX+4) to EAX
    115     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-stream/imm32 # subtract from EAX
    116     50/push-EAX
    117     # . . call
    118     e8/call  check-ints-equal/disp32
    119     # . . discard args
    120     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    121     # . epilog
    122     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    123     5d/pop-to-EBP
    124     c3/return
    125
    126 test-next-token-Eof:
    127     # . prolog
    128     55/push-EBP
    129     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    130     # setup
    131     # . clear-stream(_test-stream)
    132     # . . push args
    133     68/push  _test-stream/imm32
    134     # . . call
    135     e8/call  clear-stream/disp32
    136     # . . discard args
    137     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    138     # var slice/ECX = {0, 0}
    139     68/push  0/imm32/end
    140     68/push  0/imm32/start
    141     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
    142     # write nothing to _test-stream
    143     # next-token(_test-stream, 0x20/space, slice)
    144     # . . push args
    145     51/push-ECX
    146     68/push  0x20/imm32
    147     68/push  _test-stream/imm32
    148     # . . call
    149     e8/call  next-token/disp32
    150     # . . discard args
    151     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    152     # check-ints-equal(slice->end, slice->start, msg)
    153     # . . push args
    154     68/push  "F - test-next-token-Eof"/imm32
    155     ff          6/subop/push        1/mod/*+disp8   1/rm32/ECX    .           .             .           .           4/disp8         .                 # push *(ECX+4)
    156     ff          6/subop/push        0/mod/indirect  1/rm32/ECX    .           .             .           .           .               .                 # push *ECX
    157     # . . call
    158     e8/call  check-ints-equal/disp32
    159     # . . discard args
    160     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    161     # . epilog
    162     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    163     5d/pop-to-EBP
    164     c3/return
    165
    166 # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary)
    167 # on reaching end of file, return an empty interval
    168 next-token-from-slice:  # start : (address byte), end : (address byte), delimiter : byte, out : (address slice) -> <void>
    169     # . prolog
    170     55/push-EBP
    171     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    172     # . save registers
    173     50/push-EAX
    174     51/push-ECX
    175     52/push-EDX
    176     57/push-EDI
    177     # ECX = end
    178     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   0xc/disp8       .                 # copy *(EBP+12) to ECX
    179     # EDX = delimiter
    180     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0x10/disp8      .                 # copy *(EBP+16) to EDX
    181     # EDI = out
    182     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0x14/disp8      .                 # copy *(EBP+20) to EDI
    183     # EAX = skip-chars-matching-in-slice(start, end, delimiter)
    184     # . . push args
    185     52/push-EDX
    186     51/push-ECX
    187     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
    188     # . . call
    189     e8/call  skip-chars-matching-in-slice/disp32
    190     # . . discard args
    191     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    192     # out->start = EAX
    193     89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy EAX to *EDI
    194     # EAX = skip-chars-not-matching-in-slice(EAX, end, delimiter)
    195     # . . push args
    196     52/push-EDX
    197     51/push-ECX
    198     50/push-EAX
    199     # . . call
    200     e8/call  skip-chars-not-matching-in-slice/disp32
    201     # . . discard args
    202     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    203     # out->end = EAX
    204     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EAX to *(EDI+4)
    205     # . restore registers
    206     5f/pop-to-EDI
    207     5a/pop-to-EDX
    208     59/pop-to-ECX
    209     58/pop-to-EAX
    210     # . epilog
    211     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    212     5d/pop-to-EBP
    213     c3/return
    214
    215 test-next-token-from-slice:
    216     # . prolog
    217     55/push-EBP
    218     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    219     # (EAX..ECX) = "  ab"
    220     b8/copy-to-EAX  "  ab"/imm32
    221     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
    222     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   4/disp8         .                 # copy EAX+ECX+4 to ECX
    223     05/add-to-EAX  4/imm32
    224     # var out/EDI : (address slice) = {0, 0}
    225     68/push  0/imm32/end
    226     68/push  0/imm32/start
    227     89/copy                         3/mod/direct    7/rm32/EDI    .           .             .           4/r32/ESP   .               .                 # copy ESP to EDI
    228     # next-token-from-slice(EAX, ECX, 0x20/space, out)
    229     # . . push args
    230     57/push-EDI
    231     68/push  0x20/imm32
    232     51/push-ECX
    233     50/push-EAX
    234     # . . call
    235     e8/call  next-token-from-slice/disp32
    236     # . . discard args
    237     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
    238     # out->start should be at the 'a'
    239     # . check-ints-equal(out->start - in->start, 2, msg)
    240     # . . push args
    241     68/push  "F - test-next-token-from-slice: start"/imm32
    242     68/push  2/imm32
    243     # . . push out->start - in->start
    244     8b/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/ECX   .               .                 # copy *EDI to ECX
    245     2b/subtract                     3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # subtract EAX from ECX
    246     51/push-ECX
    247     # . . call
    248     e8/call  check-ints-equal/disp32
    249     # . . discard args
    250     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    251     # out->end should be after the 'b'
    252     # check-ints-equal(out->end - in->start, 4, msg)
    253     # . . push args
    254     68/push  "F - test-next-token-from-slice: end"/imm32
    255     68/push  4/imm32
    256     # . . push out->end - in->start
    257     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(EDI+4) to ECX
    258     2b/subtract                     3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # subtract EAX from ECX
    259     51/push-ECX
    260     # . . call
    261     e8/call  check-ints-equal/disp32
    262     # . . discard args
    263     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    264     # . epilog
    265     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    266     5d/pop-to-EBP
    267     c3/return
    268
    269 test-next-token-from-slice-Eof:
    270     # . prolog
    271     55/push-EBP
    272     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    273     # var out/EDI : (address slice) = {0, 0}
    274     68/push  0/imm32/end
    275     68/push  0/imm32/start
    276     89/copy                         3/mod/direct    7/rm32/EDI    .           .             .           4/r32/ESP   .               .                 # copy ESP to EDI
    277     # next-token-from-slice(0, 0, 0x20/space, out)
    278     # . . push args
    279     57/push-EDI
    280     68/push  0x20/imm32
    281     68/push  0/imm32
    282     68/push  0/imm32
    283     # . . call
    284     e8/call  next-token-from-slice/disp32
    285     # . . discard args
    286     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
    287     # out should be empty
    288     # . check-ints-equal(out->end - out->start, 0, msg)
    289     # . . push args
    290     68/push  "F - test-next-token-from-slice-Eof"/imm32
    291     68/push  0/imm32
    292     # . . push out->start - in->start
    293     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(EDI+4) to ECX
    294     2b/subtract                     0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/ECX   .               .                 # subtract *EDI from ECX
    295     51/push-ECX
    296     # . . call
    297     e8/call  check-ints-equal/disp32
    298     # . . discard args
    299     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    300     # . epilog
    301     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    302     5d/pop-to-EBP
    303     c3/return
    304
    305 test-next-token-from-slice-nothing:
    306     # . prolog
    307     55/push-EBP
    308     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    309     # (EAX..ECX) = "    "
    310     b8/copy-to-EAX  "    "/imm32
    311     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
    312     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   4/disp8         .                 # copy EAX+ECX+4 to ECX
    313     05/add-to-EAX  4/imm32
    314     # var out/EDI : (address slice) = {0, 0}
    315     68/push  0/imm32/end
    316     68/push  0/imm32/start
    317     89/copy                         3/mod/direct    7/rm32/EDI    .           .             .           4/r32/ESP   .               .                 # copy ESP to EDI
    318     # next-token-from-slice(in, 0x20/space, out)
    319     # . . push args
    320     57/push-EDI
    321     68/push  0x20/imm32
    322     51/push-ECX
    323     50/push-EAX
    324     # . . call
    325     e8/call  next-token-from-slice/disp32
    326     # . . discard args
    327     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
    328     # out should be empty
    329     # . check-ints-equal(out->end - out->start, 0, msg)
    330     # . . push args
    331     68/push  "F - test-next-token-from-slice-Eof"/imm32
    332     68/push  0/imm32
    333     # . . push out->start - in->start
    334     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(EDI+4) to ECX
    335     2b/subtract                     0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/ECX   .               .                 # subtract *EDI from ECX
    336     51/push-ECX
    337     # . . call
    338     e8/call  check-ints-equal/disp32
    339     # . . discard args
    340     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    341     # . epilog
    342     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    343     5d/pop-to-EBP
    344     c3/return
    345
    346 skip-chars-matching:  # in : (address stream), delimiter : byte
    347     # . prolog
    348     55/push-EBP
    349     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    350     # . save registers
    351     50/push-EAX
    352     51/push-ECX
    353     52/push-EDX
    354     53/push-EBX
    355     56/push-ESI
    356     # ESI = in
    357     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
    358     # ECX = in->read
    359     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
    360     # EBX = in->write
    361     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy *ESI to EBX
    362     # EDX = delimiter
    363     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
    364 $skip-chars-matching:loop:
    365     # if (in->read >= in->write) break
    366     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           3/r32/EBX   .               .                 # compare ECX with EBX
    367     7d/jump-if-greater-or-equal  $skip-chars-matching:end/disp8
    368     # EAX = in->data[in->read]
    369     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
    370     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
    371     # if (EAX != delimiter) break
    372     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # compare EAX and EDX
    373     75/jump-if-not-equal  $skip-chars-matching:end/disp8
    374     # ++in->read
    375     41/increment-ECX
    376     eb/jump  $skip-chars-matching:loop/disp8
    377 $skip-chars-matching:end:
    378     # persist in->read
    379     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
    380     # . restore registers
    381     5e/pop-to-ESI
    382     5b/pop-to-EBX
    383     5a/pop-to-EDX
    384     59/pop-to-ECX
    385     58/pop-to-EAX
    386     # . epilog
    387     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    388     5d/pop-to-EBP
    389     c3/return
    390
    391 test-skip-chars-matching:
    392     # setup
    393     # . clear-stream(_test-stream)
    394     # . . push args
    395     68/push  _test-stream/imm32
    396     # . . call
    397     e8/call  clear-stream/disp32
    398     # . . discard args
    399     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    400     # write(_test-stream, "  ab")
    401     # . . push args
    402     68/push  "  ab"/imm32
    403     68/push  _test-stream/imm32
    404     # . . call
    405     e8/call  write/disp32
    406     # . . discard args
    407     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    408     # skip-chars-matching(_test-stream, 0x20/space)
    409     # . . push args
    410     68/push  0x20/imm32
    411     68/push  _test-stream/imm32
    412     # . . call
    413     e8/call  skip-chars-matching/disp32
    414     # . . discard args
    415     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    416     # check-ints-equal(_test-stream->read, 2, msg)
    417     # . . push args
    418     68/push  "F - test-skip-chars-matching"/imm32
    419     68/push  2/imm32
    420     # . . push *_test-stream->read
    421     b8/copy-to-EAX  _test-stream/imm32
    422     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
    423     # . . call
    424     e8/call  check-ints-equal/disp32
    425     # . . discard args
    426     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    427     # end
    428     c3/return
    429
    430 test-skip-chars-matching-none:
    431     # setup
    432     # . clear-stream(_test-stream)
    433     # . . push args
    434     68/push  _test-stream/imm32
    435     # . . call
    436     e8/call  clear-stream/disp32
    437     # . . discard args
    438     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    439     # write(_test-stream, "ab")
    440     # . . push args
    441     68/push  "ab"/imm32
    442     68/push  _test-stream/imm32
    443     # . . call
    444     e8/call  write/disp32
    445     # . . discard args
    446     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    447     # skip-chars-matching(_test-stream, 0x20/space)
    448     # . . push args
    449     68/push  0x20/imm32
    450     68/push  _test-stream/imm32
    451     # . . call
    452     e8/call  skip-chars-matching/disp32
    453     # . . discard args
    454     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    455     # check-ints-equal(_test-stream->read, 0, msg)
    456     # . . push args
    457     68/push  "F - test-skip-chars-matching-none"/imm32
    458     68/push  0/imm32
    459     # . . push *_test-stream->read
    460     b8/copy-to-EAX  _test-stream/imm32
    461     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
    462     # . . call
    463     e8/call  check-ints-equal/disp32
    464     # . . discard args
    465     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    466     # end
    467     c3/return
    468
    469 # minor fork of 'skip-chars-matching'
    470 skip-chars-not-matching:  # in : (address stream), delimiter : byte
    471     # . prolog
    472     55/push-EBP
    473     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    474     # . save registers
    475     50/push-EAX
    476     51/push-ECX
    477     52/push-EDX
    478     53/push-EBX
    479     56/push-ESI
    480     # ESI = in
    481     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
    482     # ECX = in->read
    483     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
    484     # EBX = in->write
    485     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy *ESI to EBX
    486     # EDX = delimiter
    487     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EBP+12) to EDX
    488 $skip-chars-not-matching:loop:
    489     # if (in->read >= in->write) break
    490     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           3/r32/EBX   .               .                 # compare ECX with EBX
    491     7d/jump-if-greater-or-equal  $skip-chars-not-matching:end/disp8
    492     # EAX = in->data[in->read]
    493     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
    494     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
    495     # if (EAX == delimiter) break
    496     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # compare EAX and EDX
    497     74/jump-if-equal  $skip-chars-not-matching:end/disp8
    498     # ++in->read
    499     41/increment-ECX
    500     eb/jump  $skip-chars-not-matching:loop/disp8
    501 $skip-chars-not-matching:end:
    502     # persist in->read
    503     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
    504     # . restore registers
    505     5e/pop-to-ESI
    506     5b/pop-to-EBX
    507     5a/pop-to-EDX
    508     59/pop-to-ECX
    509     58/pop-to-EAX
    510     # . epilog
    511     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    512     5d/pop-to-EBP
    513     c3/return
    514
    515 test-skip-chars-not-matching:
    516     # setup
    517     # . clear-stream(_test-stream)
    518     # . . push args
    519     68/push  _test-stream/imm32
    520     # . . call
    521     e8/call  clear-stream/disp32
    522     # . . discard args
    523     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    524     # write(_test-stream, "ab ")
    525     # . . push args
    526     68/push  "ab "/imm32
    527     68/push  _test-stream/imm32
    528     # . . call
    529     e8/call  write/disp32
    530     # . . discard args
    531     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    532     # skip-chars-not-matching(_test-stream, 0x20/space)
    533     # . . push args
    534     68/push  0x20/imm32
    535     68/push  _test-stream/imm32
    536     # . . call
    537     e8/call  skip-chars-not-matching/disp32
    538     # . . discard args
    539     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    540     # check-ints-equal(_test-stream->read, 2, msg)
    541     # . . push args
    542     68/push  "F - test-skip-chars-not-matching"/imm32
    543     68/push  2/imm32
    544     # . . push *_test-stream->read
    545     b8/copy-to-EAX  _test-stream/imm32
    546     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
    547     # . . call
    548     e8/call  check-ints-equal/disp32
    549     # . . discard args
    550     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    551     # end
    552     c3/return
    553
    554 test-skip-chars-not-matching-none:
    555     # setup
    556     # . clear-stream(_test-stream)
    557     # . . push args
    558     68/push  _test-stream/imm32
    559     # . . call
    560     e8/call  clear-stream/disp32
    561     # . . discard args
    562     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    563     # write(_test-stream, " ab")
    564     # . . push args
    565     68/push  " ab"/imm32
    566     68/push  _test-stream/imm32
    567     # . . call
    568     e8/call  write/disp32
    569     # . . discard args
    570     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    571     # skip-chars-not-matching(_test-stream, 0x20/space)
    572     # . . push args
    573     68/push  0x20/imm32
    574     68/push  _test-stream/imm32
    575     # . . call
    576     e8/call  skip-chars-not-matching/disp32
    577     # . . discard args
    578     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    579     # check-ints-equal(_test-stream->read, 0, msg)
    580     # . . push args
    581     68/push  "F - test-skip-chars-not-matching-none"/imm32
    582     68/push  0/imm32
    583     # . . push *_test-stream->read
    584     b8/copy-to-EAX  _test-stream/imm32
    585     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
    586     # . . call
    587     e8/call  check-ints-equal/disp32
    588     # . . discard args
    589     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    590     # end
    591     c3/return
    592
    593 test-skip-chars-not-matching-all:
    594     # setup
    595     # . clear-stream(_test-stream)
    596     # . . push args
    597     68/push  _test-stream/imm32
    598     # . . call
    599     e8/call  clear-stream/disp32
    600     # . . discard args
    601     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
    602     # write(_test-stream, "ab")
    603     # . . push args
    604     68/push  "ab"/imm32
    605     68/push  _test-stream/imm32
    606     # . . call
    607     e8/call  write/disp32
    608     # . . discard args
    609     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    610     # skip-chars-not-matching(_test-stream, 0x20/space)
    611     # . . push args
    612     68/push  0x20/imm32
    613     68/push  _test-stream/imm32
    614     # . . call
    615     e8/call  skip-chars-not-matching/disp32
    616     # . . discard args
    617     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
    618     # check-ints-equal(_test-stream->read, 2, msg)
    619     # . . push args
    620     68/push  "F - test-skip-chars-not-matching-all"/imm32
    621     68/push  2/imm32
    622     # . . push *_test-stream->read
    623     b8/copy-to-EAX  _test-stream/imm32
    624     ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         .                 # push *(EAX+4)
    625     # . . call
    626     e8/call  check-ints-equal/disp32
    627     # . . discard args
    628     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    629     # end
    630     c3/return
    631
    632 skip-chars-not-matching-whitespace:  # in : (address stream)
    633     # . prolog
    634     55/push-EBP
    635     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    636     # . save registers
    637     50/push-EAX
    638     51/push-ECX
    639     53/push-EBX
    640     56/push-ESI
    641     # ESI = in
    642     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
    643     # ECX = in->read
    644     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
    645     # EBX = in->write
    646     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           3/r32/EBX   .               .                 # copy *ESI to EBX
    647 $skip-chars-not-matching-whitespace:loop:
    648     # if (in->read >= in->write) break
    649     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           3/r32/EBX   .               .                 # compare ECX with EBX
    650     7d/jump-if-greater-or-equal  $skip-chars-not-matching-whitespace:end/disp8
    651     # EAX = in->data[in->read]
    652     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
    653     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
    654     # if (EAX == ' ') break
    655     3d/compare-EAX-and  0x20/imm32/space
    656     74/jump-if-equal  $skip-chars-not-matching-whitespace:end/disp8
    657     # if (EAX == '\n') break
    658     3d/compare-EAX-and  0x0a/imm32/newline
    659     74/jump-if-equal  $skip-chars-not-matching-whitespace:end/disp8
    660     # if (EAX == '\t') break
    661     3d/compare-EAX-and  0x09/imm32/tab
    662     74/jump-if-equal  $skip-chars-not-matching-whitespace:end/disp8
    663     # if (EAX == '\r') break
    664     3d/compare-EAX-and  0x0d/imm32/cr
    665     74/jump-if-equal  $skip-chars-not-matching-whitespace:end/disp8
    666     # ++in->read
    667     41/increment-ECX
    668     eb/jump  $skip-chars-not-matching-whitespace:loop/disp8
    669 $skip-chars-not-matching-whitespace:end:
    670     # persist in->read
    671     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
    672     # . restore registers
    673     5e/pop-to-ESI
    674     5b/pop-to-EBX
    675     59/pop-to-ECX
    676     58/pop-to-EAX
    677     # . epilog
    678     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    679     5d/pop-to-EBP
    680     c3/return
    681
    682 skip-chars-matching-in-slice:  # curr : (address byte), end : (address byte), delimiter : byte -> curr/EAX
    683     # . prolog
    684     55/push-EBP
    685     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    686     # . save registers
    687     51/push-ECX
    688     52/push-EDX
    689     53/push-EBX
    690     # EAX = curr
    691     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   8/disp8         .                 # copy *(EBP+8) to EAX
    692     # ECX = end
    693     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   0xc/disp8       .                 # copy *(EBP+12) to ECX
    694     # EDX = delimiter
    695     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0x10/disp8       .                 # copy *(EBP+16) to EDX
    696     # EBX = 0
    697     31/xor                          3/mod/direct    3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # clear EBX
    698 $skip-chars-matching-in-slice:loop:
    699     # if (curr >= end) break
    700     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX with ECX
    701     7d/jump-if-greater-or-equal  $skip-chars-matching-in-slice:end/disp8
    702     # if (*curr != delimiter) break
    703     8a/copy-byte                    0/mod/indirect  0/rm32/EAX    .           .             .           3/r32/BL    .               .                 # copy byte at *EAX to BL
    704     39/compare                      3/mod/direct    3/rm32/EBX    .           .             .           2/r32/EDX   .               .                 # compare EBX and EDX
    705     75/jump-if-not-equal  $skip-chars-matching-in-slice:end/disp8
    706     # ++curr
    707     40/increment-EAX
    708     eb/jump  $skip-chars-matching-in-slice:loop/disp8
    709 $skip-chars-matching-in-slice:end:
    710     # . restore registers
    711     5b/pop-to-EBX
    712     5a/pop-to-EDX
    713     59/pop-to-ECX
    714     # . epilog
    715     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    716     5d/pop-to-EBP
    717     c3/return
    718
    719 test-skip-chars-matching-in-slice:
    720     # (EAX..ECX) = "  ab"
    721     b8/copy-to-EAX  "  ab"/imm32
    722     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
    723     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   4/disp8         .                 # copy EAX+ECX+4 to ECX
    724     05/add-to-EAX  4/imm32
    725     # EAX = skip-chars-matching-in-slice(EAX, ECX, 0x20/space)
    726     # . . push args
    727     68/push  0x20/imm32
    728     51/push-ECX
    729     50/push-EAX
    730     # . . call
    731     e8/call  skip-chars-matching-in-slice/disp32
    732     # . . discard args
    733     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    734     # check-ints-equal(ECX-EAX, 2, msg)
    735     # . . push args
    736     68/push  "F - test-skip-chars-matching-in-slice"/imm32
    737     68/push  2/imm32
    738     # . . push ECX-EAX
    739     29/subtract                     3/mod/direct    1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # subtract EAX from ECX
    740     51/push-ECX
    741     # . . call
    742     e8/call  check-ints-equal/disp32
    743     # . . discard args
    744     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    745     # end
    746     c3/return
    747
    748 test-skip-chars-matching-in-slice-none:
    749     # (EAX..ECX) = "ab"
    750     b8/copy-to-EAX  "ab"/imm32
    751     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
    752     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   4/disp8         .                 # copy EAX+ECX+4 to ECX
    753     05/add-to-EAX  4/imm32
    754     # EAX = skip-chars-matching-in-slice(EAX, ECX, 0x20/space)
    755     # . . push args
    756     68/push  0x20/imm32
    757     51/push-ECX
    758     50/push-EAX
    759     # . . call
    760     e8/call  skip-chars-matching-in-slice/disp32
    761     # . . discard args
    762     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    763     # check-ints-equal(ECX-EAX, 2, msg)
    764     # . . push args
    765     68/push  "F - test-skip-chars-matching-in-slice-none"/imm32
    766     68/push  2/imm32
    767     # . . push ECX-EAX
    768     29/subtract                     3/mod/direct    1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # subtract EAX from ECX
    769     51/push-ECX
    770     # . . call
    771     e8/call  check-ints-equal/disp32
    772     # . . discard args
    773     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    774     # end
    775     c3/return
    776
    777 # minor fork of 'skip-chars-matching-in-slice'
    778 skip-chars-not-matching-in-slice:  # curr : (address byte), end : (address byte), delimiter : byte -> curr/EAX
    779     # . prolog
    780     55/push-EBP
    781     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
    782     # . save registers
    783     51/push-ECX
    784     52/push-EDX
    785     53/push-EBX
    786     # EAX = curr
    787     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   8/disp8         .                 # copy *(EBP+8) to EAX
    788     # ECX = end
    789     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   0xc/disp8       .                 # copy *(EBP+12) to ECX
    790     # EDX = delimiter
    791     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           2/r32/EDX   0x10/disp8       .                 # copy *(EBP+16) to EDX
    792     # EBX = 0
    793     31/xor                          3/mod/direct    3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # clear EBX
    794 $skip-chars-not-matching-in-slice:loop:
    795     # if (curr >= end) break
    796     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX with ECX
    797     7d/jump-if-greater-or-equal  $skip-chars-not-matching-in-slice:end/disp8
    798     # if (*curr == delimiter) break
    799     8a/copy-byte                    0/mod/indirect  0/rm32/EAX    .           .             .           3/r32/BL    .               .                 # copy byte at *EAX to BL
    800     39/compare                      3/mod/direct    3/rm32/EBX    .           .             .           2/r32/EDX   .               .                 # compare EBX and EDX
    801     74/jump-if-equal  $skip-chars-not-matching-in-slice:end/disp8
    802     # ++curr
    803     40/increment-EAX
    804     eb/jump  $skip-chars-not-matching-in-slice:loop/disp8
    805 $skip-chars-not-matching-in-slice:end:
    806     # . restore registers
    807     5b/pop-to-EBX
    808     5a/pop-to-EDX
    809     59/pop-to-ECX
    810     # . epilog
    811     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
    812     5d/pop-to-EBP
    813     c3/return
    814
    815 test-skip-chars-not-matching-in-slice:
    816     # (EAX..ECX) = "ab "
    817     b8/copy-to-EAX  "ab "/imm32
    818     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
    819     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   4/disp8         .                 # copy EAX+ECX+4 to ECX
    820     05/add-to-EAX  4/imm32
    821     # EAX = skip-chars-not-matching-in-slice(EAX, ECX, 0x20/space)
    822     # . . push args
    823     68/push  0x20/imm32
    824     51/push-ECX
    825     50/push-EAX
    826     # . . call
    827     e8/call  skip-chars-not-matching-in-slice/disp32
    828     # . . discard args
    829     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    830     # check-ints-equal(ECX-EAX, 1, msg)
    831     # . . push args
    832     68/push  "F - test-skip-chars-not-matching-in-slice"/imm32
    833     68/push  1/imm32
    834     # . . push ECX-EAX
    835     29/subtract                     3/mod/direct    1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # subtract EAX from ECX
    836     51/push-ECX
    837     # . . call
    838     e8/call  check-ints-equal/disp32
    839     # . . discard args
    840     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    841     # end
    842     c3/return
    843
    844 test-skip-chars-not-matching-in-slice-none:
    845     # (EAX..ECX) = " ab"
    846     b8/copy-to-EAX  " ab"/imm32
    847     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
    848     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   4/disp8         .                 # copy EAX+ECX+4 to ECX
    849     05/add-to-EAX  4/imm32
    850     # EAX = skip-chars-not-matching-in-slice(EAX, ECX, 0x20/space)
    851     # . . push args
    852     68/push  0x20/imm32
    853     51/push-ECX
    854     50/push-EAX
    855     # . . call
    856     e8/call  skip-chars-not-matching-in-slice/disp32
    857     # . . discard args
    858     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    859     # check-ints-equal(ECX-EAX, 3, msg)
    860     # . . push args
    861     68/push  "F - test-skip-chars-not-matching-in-slice-none"/imm32
    862     68/push  3/imm32
    863     # . . push ECX-EAX
    864     29/subtract                     3/mod/direct    1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # subtract EAX from ECX
    865     51/push-ECX
    866     # . . call
    867     e8/call  check-ints-equal/disp32
    868     # . . discard args
    869     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    870     # end
    871     c3/return
    872
    873 test-skip-chars-not-matching-in-slice-all:
    874     # (EAX..ECX) = "ab"
    875     b8/copy-to-EAX  "ab"/imm32
    876     8b/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy *EAX to ECX
    877     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   4/disp8         .                 # copy EAX+ECX+4 to ECX
    878     05/add-to-EAX  4/imm32
    879     # EAX = skip-chars-not-matching-in-slice(EAX, ECX, 0x20/space)
    880     # . . push args
    881     68/push  0x20/imm32
    882     51/push-ECX
    883     50/push-EAX
    884     # . . call
    885     e8/call  skip-chars-not-matching-in-slice/disp32
    886     # . . discard args
    887     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    888     # check-ints-equal(ECX-EAX, 0, msg)
    889     # . . push args
    890     68/push  "F - test-skip-chars-not-matching-in-slice-all"/imm32
    891     68/push  0/imm32
    892     # . . push ECX-EAX
    893     29/subtract                     3/mod/direct    1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # subtract EAX from ECX
    894     51/push-ECX
    895     # . . call
    896     e8/call  check-ints-equal/disp32
    897     # . . discard args
    898     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
    899     # end
    900     c3/return
    901
    902 # . . vim:nowrap:textwidth=0