1 # Some tokenization primitives.
4 # instruction effective address register displacement immediate
5 # . op subop mod rm32 base index scale r32
6 # . 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
8 # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary)
9 # on reaching end of file, return an empty interval
10 next-token: # in: (addr stream byte), delimiter: byte, out: (addr slice)
13 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
20 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
22 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0x10/disp8 . # copy *(ebp+16) to edi
23 # skip-chars-matching(in, delimiter)
25 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
28 e8/call skip-chars-matching/disp32
30 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
31 # out->start = &in->data[in->read]
32 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx
33 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
34 89/copy 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # copy eax to *edi
35 # skip-chars-not-matching(in, delimiter)
37 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
40 e8/call skip-chars-not-matching/disp32
42 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
43 # out->end = &in->data[in->read]
44 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx
45 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
46 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4)
53 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
60 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
62 # . clear-stream(_test-stream)
64 68/push _test-stream/imm32
66 e8/call clear-stream/disp32
68 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
69 # var slice/ecx: slice
72 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
73 # write(_test-stream, " ab")
76 68/push _test-stream/imm32
80 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
81 # next-token(_test-stream, 0x20/space, slice)
85 68/push _test-stream/imm32
87 e8/call next-token/disp32
89 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
90 # check-ints-equal(slice->start - _test-stream->data, 2, msg)
91 # . check-ints-equal(slice->start - _test-stream, 14, msg)
93 68/push "F - test-next-token: start"/imm32
95 # . . push slice->start - _test-stream
96 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax
97 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-stream/imm32 # subtract from eax
100 e8/call check-ints-equal/disp32
102 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
103 # check-ints-equal(slice->end - _test-stream->data, 4, msg)
104 # . check-ints-equal(slice->end - _test-stream, 16, msg)
106 68/push "F - test-next-token: end"/imm32
108 # . . push slice->end - _test-stream
109 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax
110 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-stream/imm32 # subtract from eax
113 e8/call check-ints-equal/disp32
115 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
117 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
124 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
126 # . clear-stream(_test-stream)
128 68/push _test-stream/imm32
130 e8/call clear-stream/disp32
132 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
133 # var slice/ecx: slice
135 68/push 0/imm32/start
136 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
137 # write nothing to _test-stream
138 # next-token(_test-stream, 0x20/space, slice)
142 68/push _test-stream/imm32
144 e8/call next-token/disp32
146 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
147 # check-ints-equal(slice->end, slice->start, msg)
149 68/push "F - test-next-token-Eof"/imm32
150 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4)
151 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx
153 e8/call check-ints-equal/disp32
155 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
157 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
161 # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary)
162 # on reaching end of file, return an empty interval
163 next-token-from-slice: # start: (addr byte), end: (addr byte), delimiter: byte, out: (addr slice)
166 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
173 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx
175 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx
177 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0x14/disp8 . # copy *(ebp+20) to edi
178 # eax = skip-chars-matching-in-slice(start, end, delimiter)
182 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
184 e8/call skip-chars-matching-in-slice/disp32
186 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
188 89/copy 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # copy eax to *edi
189 # eax = skip-chars-not-matching-in-slice(eax, end, delimiter)
195 e8/call skip-chars-not-matching-in-slice/disp32
197 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
199 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4)
200 # . restore registers
206 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
210 test-next-token-from-slice:
213 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
215 b8/copy-to-eax " ab"/imm32
216 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
217 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
218 05/add-to-eax 4/imm32
221 68/push 0/imm32/start
222 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi
223 # next-token-from-slice(eax, ecx, 0x20/space, out)
230 e8/call next-token-from-slice/disp32
232 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
233 # out->start should be at the 'a'
234 # . check-ints-equal(out->start - in->start, 2, msg)
236 68/push "F - test-next-token-from-slice: start"/imm32
238 # . . push out->start - in->start
239 8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
240 2b/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract eax from ecx
243 e8/call check-ints-equal/disp32
245 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
246 # out->end should be after the 'b'
247 # check-ints-equal(out->end - in->start, 4, msg)
249 68/push "F - test-next-token-from-slice: end"/imm32
251 # . . push out->end - in->start
252 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx
253 2b/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract eax from ecx
256 e8/call check-ints-equal/disp32
258 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
260 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
264 test-next-token-from-slice-Eof:
267 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
270 68/push 0/imm32/start
271 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi
272 # next-token-from-slice(0, 0, 0x20/space, out)
279 e8/call next-token-from-slice/disp32
281 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
282 # out should be empty
283 # . check-ints-equal(out->end - out->start, 0, msg)
285 68/push "F - test-next-token-from-slice-Eof"/imm32
287 # . . push out->start - in->start
288 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx
289 2b/subtract 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # subtract *edi from ecx
292 e8/call check-ints-equal/disp32
294 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
296 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
300 test-next-token-from-slice-nothing:
303 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
305 b8/copy-to-eax " "/imm32
306 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
307 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
308 05/add-to-eax 4/imm32
311 68/push 0/imm32/start
312 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi
313 # next-token-from-slice(in, 0x20/space, out)
320 e8/call next-token-from-slice/disp32
322 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
323 # out should be empty
324 # . check-ints-equal(out->end - out->start, 0, msg)
326 68/push "F - test-next-token-from-slice-Eof"/imm32
328 # . . push out->start - in->start
329 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx
330 2b/subtract 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # subtract *edi from ecx
333 e8/call check-ints-equal/disp32
335 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
337 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
341 skip-chars-matching: # in: (addr stream byte), delimiter: byte
344 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
352 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
354 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx
356 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx
358 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx
359 $skip-chars-matching:loop:
360 # if (in->read >= in->write) break
361 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx
362 7d/jump-if->= $skip-chars-matching:end/disp8
363 # eax = in->data[in->read]
364 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
365 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
366 # if (eax != delimiter) break
367 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax and edx
368 75/jump-if-!= $skip-chars-matching:end/disp8
371 eb/jump $skip-chars-matching:loop/disp8
372 $skip-chars-matching:end:
374 89/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy ecx to *(esi+4)
375 # . restore registers
382 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
386 test-skip-chars-matching:
388 # . clear-stream(_test-stream)
390 68/push _test-stream/imm32
392 e8/call clear-stream/disp32
394 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
395 # write(_test-stream, " ab")
398 68/push _test-stream/imm32
402 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
403 # skip-chars-matching(_test-stream, 0x20/space)
406 68/push _test-stream/imm32
408 e8/call skip-chars-matching/disp32
410 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
411 # check-ints-equal(_test-stream->read, 2, msg)
413 68/push "F - test-skip-chars-matching"/imm32
415 # . . push *_test-stream->read
416 b8/copy-to-eax _test-stream/imm32
417 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
419 e8/call check-ints-equal/disp32
421 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
425 test-skip-chars-matching-none:
427 # . clear-stream(_test-stream)
429 68/push _test-stream/imm32
431 e8/call clear-stream/disp32
433 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
434 # write(_test-stream, "ab")
437 68/push _test-stream/imm32
441 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
442 # skip-chars-matching(_test-stream, 0x20/space)
445 68/push _test-stream/imm32
447 e8/call skip-chars-matching/disp32
449 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
450 # check-ints-equal(_test-stream->read, 0, msg)
452 68/push "F - test-skip-chars-matching-none"/imm32
454 # . . push *_test-stream->read
455 b8/copy-to-eax _test-stream/imm32
456 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
458 e8/call check-ints-equal/disp32
460 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
464 skip-chars-matching-whitespace: # in: (addr stream byte)
467 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
474 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
476 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx
478 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx
479 $skip-chars-matching-whitespace:loop:
480 # if (in->read >= in->write) break
481 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx
482 7d/jump-if->= $skip-chars-matching-whitespace:end/disp8
483 # eax = in->data[in->read]
484 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
485 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
486 # if (eax == ' ') goto body
487 3d/compare-eax-and 0x20/imm32/space
488 74/jump-if-= $skip-chars-matching-whitespace:body/disp8
489 # if (eax == '\n') goto body
490 3d/compare-eax-and 0x0a/imm32/newline
491 74/jump-if-= $skip-chars-matching-whitespace:body/disp8
492 # if (eax == '\t') goto body
493 3d/compare-eax-and 0x09/imm32/tab
494 74/jump-if-= $skip-chars-matching-whitespace:body/disp8
495 # if (eax != '\r') break
496 3d/compare-eax-and 0x0d/imm32/cr
497 75/jump-if-!= $skip-chars-matching-whitespace:end/disp8
498 $skip-chars-matching-whitespace:body:
501 eb/jump $skip-chars-matching-whitespace:loop/disp8
502 $skip-chars-matching-whitespace:end:
504 89/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy ecx to *(esi+4)
505 # . restore registers
511 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
515 test-skip-chars-matching-whitespace:
517 # . clear-stream(_test-stream)
519 68/push _test-stream/imm32
521 e8/call clear-stream/disp32
523 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
524 # write(_test-stream, " \nab")
526 68/push " \nab"/imm32
527 68/push _test-stream/imm32
531 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
532 # skip-chars-matching-whitespace(_test-stream)
534 68/push _test-stream/imm32
536 e8/call skip-chars-matching-whitespace/disp32
538 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
539 # check-ints-equal(_test-stream->read, 2, msg)
541 68/push "F - test-skip-chars-matching-whitespace"/imm32
543 # . . push *_test-stream->read
544 b8/copy-to-eax _test-stream/imm32
545 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
547 e8/call check-ints-equal/disp32
549 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
553 # minor fork of 'skip-chars-matching'
554 skip-chars-not-matching: # in: (addr stream byte), delimiter: byte
557 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
565 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
567 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx
569 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx
571 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx
572 $skip-chars-not-matching:loop:
573 # if (in->read >= in->write) break
574 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx
575 7d/jump-if->= $skip-chars-not-matching:end/disp8
576 # eax = in->data[in->read]
577 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
578 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
579 # if (eax == delimiter) break
580 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax and edx
581 74/jump-if-= $skip-chars-not-matching:end/disp8
584 eb/jump $skip-chars-not-matching:loop/disp8
585 $skip-chars-not-matching:end:
587 89/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy ecx to *(esi+4)
588 # . restore registers
595 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
599 test-skip-chars-not-matching:
601 # . clear-stream(_test-stream)
603 68/push _test-stream/imm32
605 e8/call clear-stream/disp32
607 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
608 # write(_test-stream, "ab ")
611 68/push _test-stream/imm32
615 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
616 # skip-chars-not-matching(_test-stream, 0x20/space)
619 68/push _test-stream/imm32
621 e8/call skip-chars-not-matching/disp32
623 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
624 # check-ints-equal(_test-stream->read, 2, msg)
626 68/push "F - test-skip-chars-not-matching"/imm32
628 # . . push *_test-stream->read
629 b8/copy-to-eax _test-stream/imm32
630 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
632 e8/call check-ints-equal/disp32
634 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
638 test-skip-chars-not-matching-none:
640 # . clear-stream(_test-stream)
642 68/push _test-stream/imm32
644 e8/call clear-stream/disp32
646 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
647 # write(_test-stream, " ab")
650 68/push _test-stream/imm32
654 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
655 # skip-chars-not-matching(_test-stream, 0x20/space)
658 68/push _test-stream/imm32
660 e8/call skip-chars-not-matching/disp32
662 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
663 # check-ints-equal(_test-stream->read, 0, msg)
665 68/push "F - test-skip-chars-not-matching-none"/imm32
667 # . . push *_test-stream->read
668 b8/copy-to-eax _test-stream/imm32
669 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
671 e8/call check-ints-equal/disp32
673 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
677 test-skip-chars-not-matching-all:
679 # . clear-stream(_test-stream)
681 68/push _test-stream/imm32
683 e8/call clear-stream/disp32
685 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
686 # write(_test-stream, "ab")
689 68/push _test-stream/imm32
693 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
694 # skip-chars-not-matching(_test-stream, 0x20/space)
697 68/push _test-stream/imm32
699 e8/call skip-chars-not-matching/disp32
701 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
702 # check-ints-equal(_test-stream->read, 2, msg)
704 68/push "F - test-skip-chars-not-matching-all"/imm32
706 # . . push *_test-stream->read
707 b8/copy-to-eax _test-stream/imm32
708 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
710 e8/call check-ints-equal/disp32
712 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
716 skip-chars-not-matching-whitespace: # in: (addr stream byte)
719 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
726 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
728 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx
730 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx
731 $skip-chars-not-matching-whitespace:loop:
732 # if (in->read >= in->write) break
733 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx
734 7d/jump-if->= $skip-chars-not-matching-whitespace:end/disp8
735 # eax = in->data[in->read]
736 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
737 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
738 # if (eax == ' ') break
739 3d/compare-eax-and 0x20/imm32/space
740 74/jump-if-= $skip-chars-not-matching-whitespace:end/disp8
741 # if (eax == '\n') break
742 3d/compare-eax-and 0x0a/imm32/newline
743 74/jump-if-= $skip-chars-not-matching-whitespace:end/disp8
744 # if (eax == '\t') break
745 3d/compare-eax-and 0x09/imm32/tab
746 74/jump-if-= $skip-chars-not-matching-whitespace:end/disp8
747 # if (eax == '\r') break
748 3d/compare-eax-and 0x0d/imm32/cr
749 74/jump-if-= $skip-chars-not-matching-whitespace:end/disp8
752 eb/jump $skip-chars-not-matching-whitespace:loop/disp8
753 $skip-chars-not-matching-whitespace:end:
755 89/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy ecx to *(esi+4)
756 # . restore registers
762 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
766 test-skip-chars-not-matching-whitespace:
768 # . clear-stream(_test-stream)
770 68/push _test-stream/imm32
772 e8/call clear-stream/disp32
774 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
775 # write(_test-stream, "ab\n")
778 68/push _test-stream/imm32
782 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
783 # skip-chars-not-matching-whitespace(_test-stream)
785 68/push _test-stream/imm32
787 e8/call skip-chars-not-matching-whitespace/disp32
789 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
790 # check-ints-equal(_test-stream->read, 2, msg)
792 68/push "F - test-skip-chars-not-matching-whitespace"/imm32
794 # . . push *_test-stream->read
795 b8/copy-to-eax _test-stream/imm32
796 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
798 e8/call check-ints-equal/disp32
800 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
804 skip-chars-matching-in-slice: # curr: (addr byte), end: (addr byte), delimiter: byte -> curr/eax: (addr byte)
807 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
813 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
815 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx
817 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx
818 # var c/ebx: byte = 0
819 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
820 $skip-chars-matching-in-slice:loop:
821 # if (curr >= end) break
822 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx
823 73/jump-if-addr>= $skip-chars-matching-in-slice:end/disp8
825 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL
826 # if (c != delimiter) break
827 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx and edx
828 75/jump-if-!= $skip-chars-matching-in-slice:end/disp8
831 eb/jump $skip-chars-matching-in-slice:loop/disp8
832 $skip-chars-matching-in-slice:end:
833 # . restore registers
838 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
842 test-skip-chars-matching-in-slice:
844 b8/copy-to-eax " ab"/imm32
845 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
846 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
847 05/add-to-eax 4/imm32
848 # eax = skip-chars-matching-in-slice(eax, ecx, 0x20/space)
850 68/push 0x20/imm32/space
854 e8/call skip-chars-matching-in-slice/disp32
856 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
857 # check-ints-equal(ecx-eax, 2, msg)
859 68/push "F - test-skip-chars-matching-in-slice"/imm32
862 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
865 e8/call check-ints-equal/disp32
867 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
871 test-skip-chars-matching-in-slice-none:
873 b8/copy-to-eax "ab"/imm32
874 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
875 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
876 05/add-to-eax 4/imm32
877 # eax = skip-chars-matching-in-slice(eax, ecx, 0x20/space)
879 68/push 0x20/imm32/space
883 e8/call skip-chars-matching-in-slice/disp32
885 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
886 # check-ints-equal(ecx-eax, 2, msg)
888 68/push "F - test-skip-chars-matching-in-slice-none"/imm32
891 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
894 e8/call check-ints-equal/disp32
896 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
900 skip-chars-matching-whitespace-in-slice: # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte)
903 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
908 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
910 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx
911 # var c/ebx: byte = 0
912 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
913 $skip-chars-matching-whitespace-in-slice:loop:
914 # if (curr >= end) break
915 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx
916 0f 83/jump-if-addr>= $skip-chars-matching-in-slice:end/disp32
918 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL
919 # if (c == ' ') goto body
920 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x20/imm32/space # compare ebx
921 74/jump-if-= $skip-chars-matching-whitespace-in-slice:body/disp8
922 # if (c == '\n') goto body
923 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0a/imm32/newline # compare ebx
924 74/jump-if-= $skip-chars-matching-whitespace-in-slice:body/disp8
925 # if (c == '\t') goto body
926 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x09/imm32/tab # compare ebx
927 74/jump-if-= $skip-chars-matching-whitespace-in-slice:body/disp8
928 # if (c != '\r') break
929 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0d/imm32/cr # compare ebx
930 75/jump-if-!= $skip-chars-matching-whitespace-in-slice:end/disp8
931 $skip-chars-matching-whitespace-in-slice:body:
934 eb/jump $skip-chars-matching-whitespace-in-slice:loop/disp8
935 $skip-chars-matching-whitespace-in-slice:end:
936 # . restore registers
940 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
944 test-skip-chars-matching-whitespace-in-slice:
945 # (eax..ecx) = " \nab"
946 b8/copy-to-eax " \nab"/imm32
947 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
948 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
949 05/add-to-eax 4/imm32
950 # eax = skip-chars-matching-whitespace-in-slice(eax, ecx)
955 e8/call skip-chars-matching-whitespace-in-slice/disp32
957 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
958 # check-ints-equal(ecx-eax, 2, msg)
960 68/push "F - test-skip-chars-matching-whitespace-in-slice"/imm32
963 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
966 e8/call check-ints-equal/disp32
968 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
972 # minor fork of 'skip-chars-matching-in-slice'
973 skip-chars-not-matching-in-slice: # curr: (addr byte), end: (addr byte), delimiter: byte -> curr/eax: (addr byte)
976 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
982 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
984 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx
986 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx
987 # var c/ebx: byte = 0
988 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
989 $skip-chars-not-matching-in-slice:loop:
990 # if (curr >= end) break
991 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx
992 73/jump-if-addr>= $skip-chars-not-matching-in-slice:end/disp8
994 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL
995 # if (c == delimiter) break
996 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx and edx
997 74/jump-if-= $skip-chars-not-matching-in-slice:end/disp8
1000 eb/jump $skip-chars-not-matching-in-slice:loop/disp8
1001 $skip-chars-not-matching-in-slice:end:
1002 # . restore registers
1007 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1011 test-skip-chars-not-matching-in-slice:
1012 # (eax..ecx) = "ab "
1013 b8/copy-to-eax "ab "/imm32
1014 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1015 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
1016 05/add-to-eax 4/imm32
1017 # eax = skip-chars-not-matching-in-slice(eax, ecx, 0x20/space)
1019 68/push 0x20/imm32/space
1023 e8/call skip-chars-not-matching-in-slice/disp32
1025 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1026 # check-ints-equal(ecx-eax, 1, msg)
1028 68/push "F - test-skip-chars-not-matching-in-slice"/imm32
1031 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1034 e8/call check-ints-equal/disp32
1036 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1040 test-skip-chars-not-matching-in-slice-none:
1041 # (eax..ecx) = " ab"
1042 b8/copy-to-eax " ab"/imm32
1043 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1044 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
1045 05/add-to-eax 4/imm32
1046 # eax = skip-chars-not-matching-in-slice(eax, ecx, 0x20/space)
1048 68/push 0x20/imm32/space
1052 e8/call skip-chars-not-matching-in-slice/disp32
1054 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1055 # check-ints-equal(ecx-eax, 3, msg)
1057 68/push "F - test-skip-chars-not-matching-in-slice-none"/imm32
1060 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1063 e8/call check-ints-equal/disp32
1065 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1069 test-skip-chars-not-matching-in-slice-all:
1071 b8/copy-to-eax "ab"/imm32
1072 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1073 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
1074 05/add-to-eax 4/imm32
1075 # eax = skip-chars-not-matching-in-slice(eax, ecx, 0x20/space)
1077 68/push 0x20/imm32/space
1081 e8/call skip-chars-not-matching-in-slice/disp32
1083 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1084 # check-ints-equal(ecx-eax, 0, msg)
1086 68/push "F - test-skip-chars-not-matching-in-slice-all"/imm32
1089 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1092 e8/call check-ints-equal/disp32
1094 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1098 skip-chars-not-matching-whitespace-in-slice: # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte)
1101 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1106 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
1108 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx
1109 # var c/ebx: byte = 0
1110 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
1111 $skip-chars-not-matching-whitespace-in-slice:loop:
1112 # if (curr >= end) break
1113 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx
1114 0f 83/jump-if-addr>= $skip-chars-not-matching-in-slice:end/disp32
1116 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL
1117 # if (c == ' ') break
1118 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x20/imm32/space # compare ebx
1119 74/jump-if-= $skip-chars-not-matching-whitespace-in-slice:end/disp8
1120 # if (c == '\n') break
1121 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0a/imm32/newline # compare ebx
1122 74/jump-if-= $skip-chars-not-matching-whitespace-in-slice:end/disp8
1123 # if (c == '\t') break
1124 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x09/imm32/tab # compare ebx
1125 74/jump-if-= $skip-chars-not-matching-whitespace-in-slice:end/disp8
1126 # if (c == '\r') break
1127 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0d/imm32/cr # compare ebx
1128 74/jump-if-= $skip-chars-not-matching-whitespace-in-slice:end/disp8
1131 eb/jump $skip-chars-not-matching-whitespace-in-slice:loop/disp8
1132 $skip-chars-not-matching-whitespace-in-slice:end:
1133 # . restore registers
1137 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1141 test-skip-chars-not-matching-whitespace-in-slice:
1142 # (eax..ecx) = "ab\n"
1143 b8/copy-to-eax "ab\n"/imm32
1144 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1145 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
1146 05/add-to-eax 4/imm32
1147 # eax = skip-chars-not-matching-whitespace-in-slice(eax, ecx)
1152 e8/call skip-chars-not-matching-whitespace-in-slice/disp32
1154 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1155 # check-ints-equal(ecx-eax, 1, msg)
1157 68/push "F - test-skip-chars-not-matching-whitespace-in-slice"/imm32
1160 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1163 e8/call check-ints-equal/disp32
1165 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1169 # update line->read to end of string literal surrounded by double quotes
1170 # line->read must start out at a double-quote
1171 skip-string: # line: (addr stream byte)
1174 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1180 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
1181 # eax = skip-string-in-slice(&line->data[line->read], &line->data[line->write])
1182 # . . push &line->data[line->write]
1183 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 8/disp8 . # copy *(ecx+8) to edx
1184 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx
1186 # . . push &line->data[line->read]
1187 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx
1188 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx
1191 e8/call skip-string-in-slice/disp32
1193 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1194 # line->read = eax - line->data
1195 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax
1196 2d/subtract-from-eax 0xc/imm32
1197 89/copy 1/mod/*+disp8 1/rm32/ecx . . 0/r32/eax 4/disp8 . # copy eax to *(ecx+4)
1199 # . restore registers
1204 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1211 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1213 # . clear-stream(_test-input-stream)
1215 68/push _test-input-stream/imm32
1217 e8/call clear-stream/disp32
1219 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1220 # . write(_test-input-stream, "\"abc\" def")
1221 # . indices: 0123 45
1223 68/push "\"abc\" def"/imm32
1224 68/push _test-input-stream/imm32
1226 e8/call write/disp32
1228 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1229 # precondition: line->read == 0
1231 68/push "F - test-skip-string/precondition"/imm32
1233 b8/copy-to-eax _test-input-stream/imm32
1234 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1236 e8/call check-ints-equal/disp32
1238 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1239 # skip-string(_test-input-stream)
1241 68/push _test-input-stream/imm32
1243 e8/call skip-string/disp32
1245 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1246 # check-ints-equal(line->read, 5, msg)
1248 68/push "F - test-skip-string"/imm32
1250 b8/copy-to-eax _test-input-stream/imm32
1251 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1253 e8/call check-ints-equal/disp32
1255 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1257 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1261 test-skip-string-ignores-spaces:
1264 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1266 # . clear-stream(_test-input-stream)
1268 68/push _test-input-stream/imm32
1270 e8/call clear-stream/disp32
1272 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1273 # . write(_test-input-stream, "\"a b\"/yz")
1274 # . indices: 0123 45
1276 68/push "\"a b\"/yz"/imm32
1277 68/push _test-input-stream/imm32
1279 e8/call write/disp32
1281 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1282 # precondition: line->read == 0
1284 68/push "F - test-skip-string-ignores-spaces/precondition"/imm32
1286 b8/copy-to-eax _test-input-stream/imm32
1287 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1289 e8/call check-ints-equal/disp32
1291 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1292 # skip-string(_test-input-stream)
1294 68/push _test-input-stream/imm32
1296 e8/call skip-string/disp32
1298 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1299 # check-ints-equal(line->read, 5, msg)
1301 68/push "F - test-skip-string-ignores-spaces"/imm32
1303 b8/copy-to-eax _test-input-stream/imm32
1304 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1306 e8/call check-ints-equal/disp32
1308 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1310 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1314 test-skip-string-ignores-escapes:
1317 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1319 # . clear-stream(_test-input-stream)
1321 68/push _test-input-stream/imm32
1323 e8/call clear-stream/disp32
1325 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1326 # . write(_test-input-stream, "\"a\\\"b\"/yz")
1327 # . indices: 01 2 34 56
1329 68/push "\"a\\\"b\"/yz"/imm32
1330 68/push _test-input-stream/imm32
1332 e8/call write/disp32
1334 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1335 # precondition: line->read == 0
1337 68/push "F - test-skip-string-ignores-escapes/precondition"/imm32
1339 b8/copy-to-eax _test-input-stream/imm32
1340 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1342 e8/call check-ints-equal/disp32
1344 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1345 # skip-string(_test-input-stream)
1347 68/push _test-input-stream/imm32
1349 e8/call skip-string/disp32
1351 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1352 # check-ints-equal(line->read, 6, msg)
1354 68/push "F - test-skip-string-ignores-escapes"/imm32
1356 b8/copy-to-eax _test-input-stream/imm32
1357 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1359 e8/call check-ints-equal/disp32
1361 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1363 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1367 test-skip-string-works-from-mid-stream:
1370 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1372 # . clear-stream(_test-input-stream)
1374 68/push _test-input-stream/imm32
1376 e8/call clear-stream/disp32
1378 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1379 # . write(_test-input-stream, "0 \"a\\\"b\"/yz")
1380 # . indices: 01 2 34 56
1382 68/push "0 \"a\\\"b\"/yz"/imm32
1383 68/push _test-input-stream/imm32
1385 e8/call write/disp32
1387 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1388 # precondition: line->read == 2
1389 b8/copy-to-eax _test-input-stream/imm32
1390 c7 0/subop/copy 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 2/imm32 # copy to *(eax+4)
1391 # skip-string(_test-input-stream)
1393 68/push _test-input-stream/imm32
1395 e8/call skip-string/disp32
1397 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1398 # check-ints-equal(line->read, 8, msg)
1400 68/push "F - test-skip-string-works-from-mid-stream"/imm32
1402 b8/copy-to-eax _test-input-stream/imm32
1403 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1405 e8/call check-ints-equal/disp32
1407 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1409 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1413 skip-string-in-slice: # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte)
1416 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1422 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
1424 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx
1425 # var c/eax: byte = 0
1426 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
1427 # skip initial dquote
1429 $skip-string-in-slice:loop:
1430 # if (curr >= end) return curr
1431 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
1432 73/jump-if-addr>= $skip-string-in-slice:return-curr/disp8
1434 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL
1435 $skip-string-in-slice:dquote:
1436 # if (c == '"') break
1437 3d/compare-eax-and 0x22/imm32/double-quote
1438 74/jump-if-= $skip-string-in-slice:break/disp8
1439 $skip-string-in-slice:check-for-escape:
1440 # if (c == '\') escape next char
1441 3d/compare-eax-and 0x5c/imm32/backslash
1442 75/jump-if-!= $skip-string-in-slice:continue/disp8
1443 $skip-string-in-slice:escape:
1445 $skip-string-in-slice:continue:
1448 eb/jump $skip-string-in-slice:loop/disp8
1449 $skip-string-in-slice:break:
1452 $skip-string-in-slice:return-curr:
1454 89/copy 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to eax
1455 $skip-string-in-slice:end:
1456 # . restore registers
1461 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1465 test-skip-string-in-slice:
1468 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1469 # setup: (eax..ecx) = "\"abc\" def"
1470 b8/copy-to-eax "\"abc\" def"/imm32
1471 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1472 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
1473 05/add-to-eax 4/imm32
1474 # eax = skip-string-in-slice(eax, ecx)
1479 e8/call skip-string-in-slice/disp32
1481 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1482 # check-ints-equal(ecx-eax, 4, msg) # number of chars remaining after the string literal
1484 68/push "F - test-skip-string-in-slice"/imm32
1487 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1490 e8/call check-ints-equal/disp32
1492 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1494 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1498 test-skip-string-in-slice-ignores-spaces:
1501 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1502 # setup: (eax..ecx) = "\"a b\"/yz"
1503 b8/copy-to-eax "\"a b\"/yz"/imm32
1504 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1505 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
1506 05/add-to-eax 4/imm32
1507 # eax = skip-string-in-slice(eax, ecx)
1512 e8/call skip-string-in-slice/disp32
1514 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1515 # check-ints-equal(ecx-eax, 3, msg) # number of chars remaining after the string literal
1517 68/push "F - test-skip-string-in-slice-ignores-spaces"/imm32
1520 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1523 e8/call check-ints-equal/disp32
1525 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1527 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1531 test-skip-string-in-slice-ignores-escapes:
1534 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1535 # setup: (eax..ecx) = "\"a\\\"b\"/yz"
1536 b8/copy-to-eax "\"a\\\"b\"/yz"/imm32
1537 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1538 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
1539 05/add-to-eax 4/imm32
1540 # eax = skip-string-in-slice(eax, ecx)
1545 e8/call skip-string-in-slice/disp32
1547 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1548 # check-ints-equal(ecx-eax, 3, msg) # number of chars remaining after the string literal
1550 68/push "F - test-skip-string-in-slice-ignores-escapes"/imm32
1553 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1556 e8/call check-ints-equal/disp32
1558 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1560 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1564 test-skip-string-in-slice-stops-at-end:
1567 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1568 # setup: (eax..ecx) = "\"abc" # unbalanced dquote
1569 b8/copy-to-eax "\"abc"/imm32
1570 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1571 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
1572 05/add-to-eax 4/imm32
1573 # eax = skip-string-in-slice(eax, ecx)
1578 e8/call skip-string-in-slice/disp32
1580 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1581 # check-ints-equal(ecx-eax, 0, msg) # skipped to end of slice
1583 68/push "F - test-skip-string-in-slice-stops-at-end"/imm32
1586 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1589 e8/call check-ints-equal/disp32
1591 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1593 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1597 # update line->read to ')'
1598 # line->read ends at ')'
1599 skip-until-close-paren: # line: (addr stream byte)
1602 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1608 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
1609 # eax = skip-until-close-paren-in-slice(&line->data[line->read], &line->data[line->write])
1610 # . . push &line->data[line->write]
1611 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 8/disp8 . # copy *(ecx+8) to edx
1612 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx
1614 # . . push &line->data[line->read]
1615 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx
1616 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx
1619 e8/call skip-until-close-paren-in-slice/disp32
1621 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1622 # line->read = eax - line->data
1623 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax
1624 2d/subtract-from-eax 0xc/imm32
1625 89/copy 1/mod/*+disp8 1/rm32/ecx . . 0/r32/eax 4/disp8 . # copy eax to *(ecx+4)
1626 $skip-until-close-paren:end:
1627 # . restore registers
1632 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1636 test-skip-until-close-paren:
1639 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1641 # . clear-stream(_test-input-stream)
1643 68/push _test-input-stream/imm32
1645 e8/call clear-stream/disp32
1647 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1648 # . write(_test-input-stream, "*(abc) def")
1649 # . indices: 0123 45
1651 68/push "*(abc) def"/imm32
1652 68/push _test-input-stream/imm32
1654 e8/call write/disp32
1656 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1657 # precondition: line->read == 0
1659 68/push "F - test-skip-until-close-paren/precondition"/imm32
1661 b8/copy-to-eax _test-input-stream/imm32
1662 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1664 e8/call check-ints-equal/disp32
1666 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1667 # skip-until-close-paren(_test-input-stream)
1669 68/push _test-input-stream/imm32
1671 e8/call skip-until-close-paren/disp32
1673 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1674 # check-ints-equal(line->read, 5, msg)
1676 68/push "F - test-skip-until-close-paren"/imm32
1678 b8/copy-to-eax _test-input-stream/imm32
1679 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1681 e8/call check-ints-equal/disp32
1683 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1685 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1689 test-skip-until-close-paren-ignores-spaces:
1692 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1694 # . clear-stream(_test-input-stream)
1696 68/push _test-input-stream/imm32
1698 e8/call clear-stream/disp32
1700 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1701 # . write(_test-input-stream, "*(a b)/yz")
1703 68/push "*(a b)/yz"/imm32
1704 68/push _test-input-stream/imm32
1706 e8/call write/disp32
1708 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1709 # precondition: line->read == 0
1711 68/push "F - test-skip-until-close-paren-ignores-spaces/precondition"/imm32
1713 b8/copy-to-eax _test-input-stream/imm32
1714 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1716 e8/call check-ints-equal/disp32
1718 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1719 # skip-until-close-paren(_test-input-stream)
1721 68/push _test-input-stream/imm32
1723 e8/call skip-until-close-paren/disp32
1725 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1726 # check-ints-equal(line->read, 5, msg)
1728 68/push "F - test-skip-until-close-paren-ignores-spaces"/imm32
1730 b8/copy-to-eax _test-input-stream/imm32
1731 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1733 e8/call check-ints-equal/disp32
1735 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1737 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1741 test-skip-until-close-paren-works-from-mid-stream:
1744 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1746 # . clear-stream(_test-input-stream)
1748 68/push _test-input-stream/imm32
1750 e8/call clear-stream/disp32
1752 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1753 # . write(_test-input-stream, "0 *(a b)/yz")
1755 68/push "0 *(a b)/yz"/imm32
1756 68/push _test-input-stream/imm32
1758 e8/call write/disp32
1760 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1761 # precondition: _test-input-stream->read == 2
1762 b8/copy-to-eax _test-input-stream/imm32
1763 c7 0/subop/copy 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 2/imm32 # copy to *(eax+4)
1764 # skip-until-close-paren(_test-input-stream)
1766 68/push _test-input-stream/imm32
1768 e8/call skip-until-close-paren/disp32
1770 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1771 # check-ints-equal(_test-input-stream->read, 7, msg)
1773 68/push "F - test-skip-until-close-paren-works-from-mid-stream"/imm32
1775 b8/copy-to-eax _test-input-stream/imm32
1776 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4)
1778 e8/call check-ints-equal/disp32
1780 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1782 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1786 skip-until-close-paren-in-slice: # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte)
1789 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1794 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
1796 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx
1797 # var c/eax: byte = 0
1798 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
1799 # skip initial dquote
1801 $skip-until-close-paren-in-slice:loop:
1802 # if (curr >= end) break
1803 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
1804 73/jump-if-addr>= $skip-until-close-paren-in-slice:break/disp8
1806 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL
1807 $skip-until-close-paren-in-slice:check-close:
1808 # if (c == ')') break
1809 3d/compare-eax-and 0x29/imm32/close-paren
1810 74/jump-if-= $skip-until-close-paren-in-slice:break/disp8
1813 eb/jump $skip-until-close-paren-in-slice:loop/disp8
1814 $skip-until-close-paren-in-slice:break:
1816 89/copy 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to eax
1817 $skip-until-close-paren-in-slice:end:
1818 # . restore registers
1822 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1826 test-skip-until-close-paren-in-slice:
1829 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1830 # setup: (eax..ecx) = "*(abc) def"
1831 b8/copy-to-eax "*(abc) def"/imm32
1832 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1833 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
1834 05/add-to-eax 4/imm32
1835 # eax = skip-until-close-paren-in-slice(eax, ecx)
1840 e8/call skip-until-close-paren-in-slice/disp32
1842 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1843 # check-ints-equal(ecx-eax, 5, msg) # eax is at the ')'
1845 68/push "F - test-skip-until-close-paren-in-slice"/imm32
1848 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1851 e8/call check-ints-equal/disp32
1853 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1855 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1859 test-skip-until-close-paren-in-slice-ignores-spaces:
1862 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1863 # setup: (eax..ecx) = "*(a b)/yz"
1864 b8/copy-to-eax "*(a b)/yz"/imm32
1865 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1866 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
1867 05/add-to-eax 4/imm32
1868 # eax = skip-until-close-paren-in-slice(eax, ecx)
1873 e8/call skip-until-close-paren-in-slice/disp32
1875 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1876 # check-ints-equal(ecx-eax, 4, msg) # eax is at the ')'
1878 68/push "F - test-skip-until-close-paren-in-slice-ignores-spaces"/imm32
1881 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1884 e8/call check-ints-equal/disp32
1886 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1888 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1892 test-skip-until-close-paren-in-slice-stops-at-end:
1895 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1896 # setup: (eax..ecx) = "*(abc" # unbalanced dquote
1897 b8/copy-to-eax "*(abc"/imm32
1898 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1899 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
1900 05/add-to-eax 4/imm32
1901 # eax = skip-until-close-paren-in-slice(eax, ecx)
1906 e8/call skip-until-close-paren-in-slice/disp32
1908 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1909 # check-ints-equal(ecx-eax, 0, msg) # skipped to end of slice
1911 68/push "F - test-skip-until-close-paren-in-slice-stops-at-end"/imm32
1914 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx
1917 e8/call check-ints-equal/disp32
1919 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1921 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1925 # . . vim:nowrap:textwidth=0