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/inc-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/inc-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/inc-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/inc-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/inc-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