1 # new data structure: a slice is an open interval of addresses [start, end)
2 # that includes 'start' but not 'end'
5 # instruction effective address register displacement immediate
6 # . op subop mod rm32 base index scale r32
7 # . 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
9 slice-empty?: # s: (addr slice) -> result/eax: boolean
12 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
16 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx
17 # if (s->start >= s->end) return true
19 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax
20 # . if (eax >= s->end) return true
21 3b/compare 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # compare eax with *(ecx+4)
22 b8/copy-to-eax 1/imm32/true
23 73/jump-if-addr>= $slice-empty?:end/disp8
24 b8/copy-to-eax 0/imm32/false
29 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
33 test-slice-empty-true:
36 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
37 # var slice/ecx: slice = {34, 34}
39 68/push 34/imm32/start
40 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
45 e8/call slice-empty?/disp32
47 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
48 # check-ints-equal(eax, 1, msg)
50 68/push "F - test-slice-empty-true"/imm32
54 e8/call check-ints-equal/disp32
56 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
58 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
62 test-slice-empty-false:
65 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
66 # var slice/ecx: slice = {32, 34}
68 68/push 32/imm32/start
69 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
74 e8/call slice-empty?/disp32
76 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
77 # check-ints-equal(eax, 0, msg)
79 68/push "F - test-slice-empty-false"/imm32
83 e8/call check-ints-equal/disp32
85 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
87 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
91 test-slice-empty-if-start-greater-than-end:
94 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
95 # var slice/ecx: slice = {34, 32}
97 68/push 34/imm32/start
98 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
103 e8/call slice-empty?/disp32
105 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
106 # check-ints-equal(eax, 1, msg)
108 68/push "F - test-slice-empty-if-start-greater-than-end"/imm32
112 e8/call check-ints-equal/disp32
114 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
116 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
120 slice-equal?: # s: (addr slice), p: (addr array byte) -> result/eax: boolean
122 # if (p == 0) return (s == 0)
125 # if (maxs - currs != p->size) return false
128 # if (*currs != *currp) return false
142 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
149 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
150 # var currs/edx: (addr byte) = s->start
151 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx
152 # var maxs/esi: (addr byte) = s->end
153 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 6/r32/esi 4/disp8 . # copy *(esi+4) to esi
154 # var ssize/eax: int = maxs - currs
155 89/copy 3/mod/direct 0/rm32/eax . . . 6/r32/esi . . # copy esi to eax
156 29/subtract 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # subtract edx from eax
158 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 3/r32/ebx 0xc/disp8 . # copy *(ebp+12) to ebx
159 # if (p != 0) goto next check
160 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32 # compare ebx
161 75/jump-if-!= $slice-equal?:nonnull-string/disp8
162 $slice-equal?:null-string:
163 # return s->start == s->end
164 3d/compare-eax-and 0/imm32
165 74/jump-if-= $slice-equal?:true/disp8
166 eb/jump $slice-equal?:false/disp8
167 $slice-equal?:nonnull-string:
168 # if (ssize != p->size) return false
169 39/compare 0/mod/indirect 3/rm32/ebx . . . 0/r32/eax . . # compare *ebx and eax
170 75/jump-if-!= $slice-equal?:false/disp8
171 # var currp/ebx: (addr byte) = p->data
172 81 0/subop/add 3/mod/direct 3/rm32/ebx . . . . . 4/imm32 # add to ebx
173 # var c1/eax: byte = 0
174 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
175 # var c2/ecx: byte = 0
176 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx
178 # if (currs >= maxs) return true
179 39/compare 3/mod/direct 2/rm32/edx . . . 6/r32/esi . . # compare edx with esi
180 73/jump-if-addr>= $slice-equal?:true/disp8
182 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL
184 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 1/r32/CL . . # copy byte at *edx to CL
185 # if (c1 != c2) return false
186 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax and ecx
187 75/jump-if-!= $slice-equal?:false/disp8
192 eb/jump $slice-equal?:loop/disp8
194 b8/copy-to-eax 0/imm32
195 eb/jump $slice-equal?:end/disp8
197 b8/copy-to-eax 1/imm32
199 # . restore registers
205 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
210 # - slice-equal?(slice("Abc"), "Abc") == 1
213 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
215 b8/copy-to-eax "Abc"/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
219 # var slice/ecx: slice = {eax, ecx}
222 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
223 # eax = slice-equal?(ecx, "Abc")
228 e8/call slice-equal?/disp32
230 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
231 # check-ints-equal(eax, 1, msg)
233 68/push "F - test-slice-equal"/imm32
237 e8/call check-ints-equal/disp32
239 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
241 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
245 test-slice-equal-false:
246 # - slice-equal?(slice("bcd"), "Abc") == 0
249 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
251 b8/copy-to-eax "bcd"/imm32
252 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
253 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
254 05/add-to-eax 4/imm32
255 # var slice/ecx: slice = {eax, ecx}
258 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
259 # eax = slice-equal?(ecx, "Abc")
264 e8/call slice-equal?/disp32
266 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
267 # check-ints-equal(eax, 0, msg)
269 68/push "F - test-slice-equal-false"/imm32
273 e8/call check-ints-equal/disp32
275 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
277 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
281 test-slice-equal-too-long:
282 # - slice-equal?(slice("Abcd"), "Abc") == 0
285 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
286 # (eax..ecx) = "Abcd"
287 b8/copy-to-eax "Abcd"/imm32
288 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
289 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
290 05/add-to-eax 4/imm32
291 # var slice/ecx: slice = {eax, ecx}
294 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
295 # eax = slice-equal?(ecx, "Abc")
300 e8/call slice-equal?/disp32
302 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
303 # check-ints-equal(eax, 0, msg)
305 68/push "F - test-slice-equal-too-long"/imm32
309 e8/call check-ints-equal/disp32
311 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
313 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
317 test-slice-equal-too-short:
318 # - slice-equal?(slice("A"), "Abc") == 0
321 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
323 b8/copy-to-eax "A"/imm32
324 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
325 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
326 05/add-to-eax 4/imm32
327 # var slice/ecx: slice = {eax, ecx}
330 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
331 # eax = slice-equal?(ecx, "Abc")
336 e8/call slice-equal?/disp32
338 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
339 # check-ints-equal(eax, 0, msg)
341 68/push "F - test-slice-equal-too-short"/imm32
345 e8/call check-ints-equal/disp32
347 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
349 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
353 test-slice-equal-empty:
354 # - slice-equal?(slice(""), "Abc") == 0
357 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
358 # var slice/ecx: slice
360 68/push 0/imm32/start
361 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
362 # eax = slice-equal?(ecx, "Abc")
367 e8/call slice-equal?/disp32
369 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
370 # check-ints-equal(eax, 0, msg)
372 68/push "F - test-slice-equal-empty"/imm32
376 e8/call check-ints-equal/disp32
378 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
380 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
384 test-slice-equal-with-empty:
385 # - slice-equal?(slice("Ab"), "") == 0
388 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
390 b8/copy-to-eax "Ab"/imm32
391 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
392 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
393 05/add-to-eax 4/imm32
394 # var slice/ecx: slice = {eax, ecx}
397 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
398 # eax = slice-equal?(ecx, "")
403 e8/call slice-equal?/disp32
405 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
406 # check-ints-equal(eax, 0, msg)
408 68/push "F - test-slice-equal-with-empty"/imm32
412 e8/call check-ints-equal/disp32
414 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
416 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
420 test-slice-equal-empty-with-empty:
421 # - slice-equal?(slice(""), "") == 1
424 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
425 # var slice/ecx: slice
427 68/push 0/imm32/start
428 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
429 # eax = slice-equal?(ecx, "")
434 e8/call slice-equal?/disp32
436 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
437 # check-ints-equal(eax, 1, msg)
439 68/push "F - test-slice-equal-empty-with-empty"/imm32
443 e8/call check-ints-equal/disp32
445 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
447 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
451 test-slice-equal-with-null:
452 # - slice-equal?(slice("Ab"), null) == 0
455 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
457 b8/copy-to-eax "Ab"/imm32
458 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
459 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
460 05/add-to-eax 4/imm32
461 # var slice/ecx: slice = {eax, ecx}
464 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
465 # eax = slice-equal?(ecx, 0)
470 e8/call slice-equal?/disp32
472 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
473 # check-ints-equal(eax, 0, msg)
475 68/push "F - test-slice-equal-with-null"/imm32
479 e8/call check-ints-equal/disp32
481 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
483 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
487 slice-starts-with?: # s: (addr slice), head: (addr array byte) -> result/eax: boolean
490 # if (hsize > s->end - s->start) return false
495 # if (*currs != *currh) return false
511 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
519 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
520 # var lens/ecx: int = s->end - s->start
521 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx
522 2b/subtract 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # subtract *esi from ecx
524 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
525 # var hsize/edx: int = head->size
526 8b/copy 0/mod/indirect 7/rm32/edi . . . 2/r32/edx . . # copy *edi to edx
527 # if (hsize > lens) return false
528 39/compare 3/mod/direct 2/rm32/edx . . . 1/r32/ecx . . # compare edx with ecx
529 7f/jump-if-> $slice-starts-with?:false/disp8
530 # var currs/esi: (addr byte) = s->start
531 8b/subtract 0/mod/indirect 6/rm32/esi . . . 6/r32/esi . . # copy *esi to esi
532 # var currh/edi: (addr byte) = head->data
533 81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 4/imm32 # add to edi
535 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx
536 # var c1/eax: byte = 0
537 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
538 # var c2/ebx: byte = 0
539 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
540 $slice-starts-with?:loop:
541 # if (i >= hsize) return true
542 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx
543 7d/jump-if->= $slice-starts-with?:true/disp8
545 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL
547 8a/copy-byte 0/mod/indirect 7/rm32/edi . . . 3/r32/BL . . # copy byte at *edi to BL
548 # if (c1 != c2) return false
549 39/compare 3/mod/direct 0/rm32/eax . . . 3/r32/ebx . . # compare eax and ebx
550 75/jump-if-!= $slice-starts-with?:false/disp8
557 eb/jump $slice-starts-with?:loop/disp8
558 $slice-starts-with?:true:
559 b8/copy-to-eax 1/imm32
560 eb/jump $slice-starts-with?:end/disp8
561 $slice-starts-with?:false:
562 b8/copy-to-eax 0/imm32
563 $slice-starts-with?:end:
564 # . restore registers
571 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
575 test-slice-starts-with-single-character:
576 # - slice-starts-with?(slice("Abc"), "A") == 1
579 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
581 b8/copy-to-eax "Abc"/imm32
582 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
583 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
584 05/add-to-eax 4/imm32
585 # var slice/ecx: slice = {eax, ecx}
588 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
589 # eax = slice-starts-with?(ecx, "A")
594 e8/call slice-starts-with?/disp32
596 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
597 # check-ints-equal(eax, 1, msg)
599 68/push "F - test-slice-starts-with-single-character"/imm32
603 e8/call check-ints-equal/disp32
605 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
607 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
611 test-slice-starts-with-empty-string:
612 # - slice-starts-with?(slice("Abc"), "") == 1
615 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
617 b8/copy-to-eax "Abc"/imm32
618 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
619 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
620 05/add-to-eax 4/imm32
621 # var slice/ecx: slice = {eax, ecx}
624 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
625 # eax = slice-starts-with?(ecx, "")
630 e8/call slice-starts-with?/disp32
632 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
633 # check-ints-equal(eax, 1, msg)
635 68/push "F - test-slice-starts-with-empty-string"/imm32
639 e8/call check-ints-equal/disp32
641 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
643 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
647 test-slice-starts-with-multiple-characters:
648 # - slice-starts-with?(slice("Abc"), "Ab") == 1
651 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
653 b8/copy-to-eax "Abc"/imm32
654 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
655 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
656 05/add-to-eax 4/imm32
657 # var slice/ecx: slice = {eax, ecx}
660 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
661 # eax = slice-starts-with?(ecx, "Ab")
666 e8/call slice-starts-with?/disp32
668 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
669 # check-ints-equal(eax, 1, msg)
671 68/push "F - test-slice-starts-with-multiple-characters"/imm32
675 e8/call check-ints-equal/disp32
677 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
679 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
683 test-slice-starts-with-entire-string:
684 # - slice-starts-with?(slice("Abc"), "Abc") == 1
687 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
689 b8/copy-to-eax "Abc"/imm32
690 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
691 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
692 05/add-to-eax 4/imm32
693 # var slice/ecx: slice = {eax, ecx}
696 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
697 # eax = slice-starts-with?(ecx, "Abc")
702 e8/call slice-starts-with?/disp32
704 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
705 # check-ints-equal(eax, 1, msg)
707 68/push "F - test-slice-starts-with-entire-string"/imm32
711 e8/call check-ints-equal/disp32
713 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
715 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
719 test-slice-starts-with-fails:
720 # - slice-starts-with?(slice("Abc"), "Abd") == 1
723 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
725 b8/copy-to-eax "Abc"/imm32
726 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
727 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
728 05/add-to-eax 4/imm32
729 # var slice/ecx: slice = {eax, ecx}
732 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
733 # eax = slice-starts-with?(ecx, "Abd")
738 e8/call slice-starts-with?/disp32
740 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
741 # check-ints-equal(eax, 0, msg)
743 68/push "F - test-slice-starts-with-fails"/imm32
747 e8/call check-ints-equal/disp32
749 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
751 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
755 test-slice-starts-with-fails-2:
756 # - slice-starts-with?(slice("Abc"), "Ac") == 1
759 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
761 b8/copy-to-eax "Abc"/imm32
762 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
763 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
764 05/add-to-eax 4/imm32
765 # var slice/ecx: slice = {eax, ecx}
768 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
769 # eax = slice-starts-with?(ecx, "Ac")
774 e8/call slice-starts-with?/disp32
776 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
777 # check-ints-equal(eax, 0, msg)
779 68/push "F - test-slice-starts-with-fails-2"/imm32
783 e8/call check-ints-equal/disp32
785 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
787 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
791 # write a slice to a stream
792 # abort if the stream doesn't have enough space
793 write-slice: # out: (addr stream byte), s: (addr slice)
796 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
805 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi
806 # var curr/ecx: (addr byte) = s->start
807 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
808 # var max/esi: (addr byte) = s->end
809 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 6/r32/esi 4/disp8 . # copy *(esi+4) to esi
811 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
813 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 . # copy *(edi+8) to edx
815 8b/copy 0/mod/indirect 7/rm32/edi . . . 3/r32/ebx . . # copy *edi to ebx
817 # if (curr >= max) break
818 39/compare 3/mod/direct 1/rm32/ecx . . . 6/r32/esi . . # compare ecx with esi
819 73/jump-if-addr>= $write-slice:loop-end/disp8
820 # if (out->write >= out->size) abort
821 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx with edx
822 7d/jump-if->= $write-slice:abort/disp8
823 # out->data[out->write] = *in
825 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
826 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL
827 # . out->data[out->write] = AL
828 88/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/edi 3/index/ebx . 0/r32/AL 0xc/disp8 . # copy AL to *(edi+ebx+12)
833 eb/jump $write-slice:loop/disp8
834 $write-slice:loop-end:
836 89/copy 0/mod/indirect 7/rm32/edi . . . 3/r32/ebx . . # copy ebx to *edi
838 # . restore registers
846 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
851 # . _write(2/stderr, error)
853 68/push "write-slice: out of space"/imm32
854 68/push 2/imm32/stderr
856 e8/call _write/disp32
858 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
860 bb/copy-to-ebx 1/imm32
861 e8/call syscall_exit/disp32
867 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
869 # . clear-stream(_test-stream)
871 68/push _test-stream/imm32
873 e8/call clear-stream/disp32
875 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
877 b8/copy-to-eax "Abc"/imm32
878 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
879 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
880 05/add-to-eax 4/imm32
881 # var slice/ecx: slice = {eax, ecx}
884 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
885 # write-slice(_test-stream, slice)
888 68/push _test-stream/imm32
890 e8/call write-slice/disp32
892 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
893 # check-stream-equal(_test-stream, "Abc", msg)
895 68/push "F - test-write-slice"/imm32
897 68/push _test-stream/imm32
899 e8/call check-stream-equal/disp32
901 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
903 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
907 # write a slice to a buffered-file
908 write-slice-buffered: # out: (addr buffered-file), s: (addr slice)
911 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
920 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi
921 # var curr/ecx: (addr byte) = s->start
922 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
923 # var max/esi: (addr byte) = s->end
924 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 6/r32/esi 4/disp8 . # copy *(esi+4) to esi
926 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
928 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 0xc/disp8 . # copy *(edi+12) to edx
930 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 4/disp8 . # copy *(edi+4) to ebx
931 $write-slice-buffered:loop:
932 # if (curr >= max) break
933 39/compare 3/mod/direct 1/rm32/ecx . . . 6/r32/esi . . # compare ecx with esi
934 73/jump-if-addr>= $write-slice-buffered:loop-end/disp8
935 # if (out->write >= out->size) flush and clear out's stream
936 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx with edx
937 7c/jump-if-< $write-slice-buffered:to-stream/disp8
938 # . persist out->write
939 89/copy 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 4/disp8 . # copy ebx to *(edi+4)
946 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
947 # . clear-stream(stream = out+4)
949 8d/copy-address 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy edi+4 to eax
952 e8/call clear-stream/disp32
954 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
955 # . out->write must now be 0; update its cache at ebx
956 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx
957 $write-slice-buffered:to-stream:
958 # out->data[out->write] = *in
960 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
961 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL
962 # . out->data[out->write] = AL
963 88/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/edi 3/index/ebx . 0/r32/AL 0x10/disp8 . # copy AL to *(edi+ebx+16)
968 eb/jump $write-slice-buffered:loop/disp8
969 $write-slice-buffered:loop-end:
970 # persist necessary variables from registers
971 89/copy 1/mod/*+disp8 7/rm32/edi . . . 3/r32/ebx 4/disp8 . # copy ebx to *(edi+4)
972 $write-slice-buffered:end:
973 # . restore registers
981 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
985 test-write-slice-buffered:
988 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
990 # . clear-stream(_test-stream)
992 68/push _test-stream/imm32
994 e8/call clear-stream/disp32
996 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
997 # . clear-stream($_test-buffered-file->buffer)
999 68/push $_test-buffered-file->buffer/imm32
1001 e8/call clear-stream/disp32
1003 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1004 # (eax..ecx) = "Abc"
1005 b8/copy-to-eax "Abc"/imm32
1006 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1007 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
1008 05/add-to-eax 4/imm32
1009 # var slice/ecx: slice = {eax, ecx}
1012 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
1013 # write-slice-buffered(_test-buffered-file, slice)
1016 68/push _test-buffered-file/imm32
1018 e8/call write-slice-buffered/disp32
1020 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1021 # flush(_test-buffered-file)
1023 68/push _test-buffered-file/imm32
1025 e8/call flush/disp32
1027 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
1028 # check-stream-equal(_test-stream, "Abc", msg)
1030 68/push "F - test-write-slice-buffered"/imm32
1032 68/push _test-stream/imm32
1034 e8/call check-stream-equal/disp32
1036 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1038 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1042 # copy a slice into a new (dynamically allocated) string
1043 slice-to-string: # ad: (addr allocation-descriptor), in: (addr slice), out: (addr handle array byte)
1046 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1054 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi
1055 # var curr/edx: (addr byte) = in->start
1056 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx
1057 # var max/ebx: (addr byte) = in->end
1058 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 3/r32/ebx 4/disp8 . # copy *(esi+4) to ebx
1059 # var size/ecx: int = max - curr + 4 # total size of output string (including the initial 'size' field)
1060 89/copy 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # copy ebx to ecx
1061 29/subtract 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # subtract edx from ecx
1062 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx
1063 # allocate(ad, size, out)
1065 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
1067 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
1069 e8/call allocate/disp32
1071 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1072 # eax = out->payload
1073 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax
1074 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax
1075 # skip payload->allocid
1076 05/add-to-eax 4/imm32
1077 # if (eax == 0) abort
1078 3d/compare-eax-and 0/imm32
1079 74/jump-if-= $slice-to-string:abort/disp8
1080 # out->size = size-4
1081 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax
1082 81 5/subop/subtract 0/mod/indirect 0/rm32/eax . . . . . 4/imm32 # subtract 4 from *eax
1085 $slice-to-string:initialize:
1086 # eax = _append-4(eax+4, eax+size, curr, max) # clobbering ecx
1090 # . . push eax+size (clobbering ecx)
1091 01/add 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # add eax to ecx
1093 # . . push eax+4 (clobbering eax)
1094 81 0/subop/add 3/mod/direct 0/rm32/eax . . . . . 4/imm32 # add to eax
1097 e8/call _append-4/disp32
1099 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp
1100 # restore out (assumes _append-4 can't error)
1102 $slice-to-string:end:
1103 # . restore registers
1110 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1114 $slice-to-string:abort:
1115 # . _write(2/stderr, error)
1117 68/push "slice-to-string: out of space\n"/imm32
1118 68/push 2/imm32/stderr
1120 e8/call _write/disp32
1122 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1124 bb/copy-to-ebx 1/imm32
1125 e8/call syscall_exit/disp32
1128 test-slice-to-string:
1131 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
1132 # var heap/edx: allocation-descriptor
1133 68/push 0/imm32/limit
1134 68/push 0/imm32/curr
1135 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx
1136 # heap = new-segment(512)
1141 e8/call new-segment/disp32
1143 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1144 # (eax..ecx) = "Abc"
1145 b8/copy-to-eax "Abc"/imm32
1146 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx
1147 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
1148 05/add-to-eax 4/imm32
1149 # var slice/ecx: slice = {eax, ecx}
1152 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx
1153 # var h/ebx: (handle array byte)
1156 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx
1157 # slice-to-string(heap, slice, h)
1163 e8/call slice-to-string/disp32
1165 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1167 8b/copy 1/mod/*+disp8 3/rm32/ebx . . . 0/r32/eax 4/disp8 . # copy *(ebx+4) to eax
1168 # skip payload->allocid
1169 05/add-to-eax 4/imm32
1171 #? # . write(2/stderr, "AA: ")
1173 #? 68/push "AA: "/imm32
1174 #? 68/push 2/imm32/stderr
1176 #? e8/call write/disp32
1177 #? # . . discard args
1178 #? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1179 #? # . write(2/stderr, eax)
1182 #? 68/push 2/imm32/stderr
1184 #? e8/call write/disp32
1185 #? # . . discard args
1186 #? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1187 #? # . write(2/stderr, "$\n")
1189 #? 68/push "$\n"/imm32
1190 #? 68/push 2/imm32/stderr
1192 #? e8/call write/disp32
1193 #? # . . discard args
1194 #? 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1196 # eax = string-equal?(eax, "Abc")
1201 e8/call string-equal?/disp32
1203 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
1204 # check-ints-equal(eax, 1, msg)
1206 68/push "F - test-slice-to-string"/imm32
1207 68/push 1/imm32/true
1210 e8/call check-ints-equal/disp32
1212 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
1214 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # add to esp
1216 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
1220 # . . vim:nowrap:textwidth=0