https://github.com/akkartik/mu/blob/main/123slice.subx
   1 # new data structure: a slice is an open interval of addresses [start, end)
   2 # that includes 'start' but not 'end'
   3 
   4 == code
   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
   8 
   9 slice-empty?:  # s: (addr slice) -> result/eax: boolean
  10     # . prologue
  11     55/push-ebp
  12     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
  13     # . save registers
  14     51/push-ecx
  15     # ecx = s
  16     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   8/disp8         .                 # copy *(ebp+8) to ecx
  17     <
parse/0: instruction: 1
parse/0:   ingredient: {name: "32", value: 0, type: 0, properties: ["32": "literal"]}
parse/0:   product: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
parse/0: instruction: 1
parse/0:   ingredient: {name: "33", value: 0, type: 0, properties: ["33": "literal"]}
parse/0:   product: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}
parse/0: instruction: 17
parse/0:   ingredient: {name: "1", value: 0, type: 1, properties: ["1": "integer"]}
parse/0:   ingredient: {name: "2", value: 0, type: 1, properties: ["2": "integer"]}
parse/0:   product: {name: "3", value: 0, type: 1, properties: ["3": "integer"]}
after-brace/0: recipe main
after-brace/0: copy ...
after-brace/0: copy ...
after-brace/0: lesser-or-equal ...
run/0: instruction main/0
run/0: ingredient 0 is 32
mem/0: storing 32 in location 1
run/0: instruction main/1
run/0: ingredient 0 is 33
mem/0: storing 33 in location 2
run/0: instruction main/2
run/0: ingredient 0 is 1
mem/0: location 1 is 32
run/0: ingredient 1 is 2
mem/0: location 2 is 33
run/0: product 0 is 1
mem/0: storing 1 in location 3
pan> 68/push 32/imm32/start 69 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 70 # slice-empty?(slice) 71 # . . push args 72 51/push-ecx 73 # . . call 74 e8/call slice-empty?/disp32 75 # . . discard args 76 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 77 # check-ints-equal(eax, 0, msg) 78 # . . push args 79 68/push "F - test-slice-empty-false"/imm32 80 68/push 0/imm32 81 50/push-eax 82 # . . call 83 e8/call check-ints-equal/disp32 84 # . . discard args 85 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 86 # . epilogue 87 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 88 5d/pop-to-ebp 89 c3/return 90 91 test-slice-empty-if-start-greater-than-end: 92 # . prologue 93 55/push-ebp 94 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 95 # var slice/ecx: slice = {34, 32} 96 68/push 32/imm32/end 97 68/push 34/imm32/start 98 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 99 # slice-empty?(slice) 100 # . . push args 101 51/push-ecx 102 # . . call 103 e8/call slice-empty?/disp32 104 # . . discard args 105 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 106 # check-ints-equal(eax, 1, msg) 107 # . . push args 108 68/push "F - test-slice-empty-if-start-greater-than-end"/imm32 109 68/push 1/imm32 110 50/push-eax 111 # . . call 112 e8/call check-ints-equal/disp32 113 # . . discard args 114 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 115 # . epilogue 116 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 117 5d/pop-to-ebp 118 c3/return 119 120 slice-equal?: # s: (addr slice), p: (addr array byte) -> result/eax: boolean 121 # pseudocode: 122 # if (p == 0) return (s == 0) 123 # currs = s->start 124 # maxs = s->end 125 # if (maxs - currs != p->size) return false 126 # currp = p->data 127 # while currs < maxs 128 # if (*currs != *currp) return false 129 # ++currs 130 # ++currp 131 # return true 132 # 133 # registers: 134 # currs: edx 135 # maxs: esi 136 # currp: ebx 137 # *currs: eax 138 # *currp: ecx 139 # 140 # . prologue 141 55/push-ebp 142 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 143 # . save registers 144 51/push-ecx 145 52/push-edx 146 53/push-ebx 147 56/push-esi 148 # esi = s 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 157 # ebx = p 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 177 $slice-equal?:loop: 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 181 # c1 = *currp 182 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL 183 # c2 = *currs 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 188 # ++currp 189 43/increment-ebx 190 # ++currs 191 42/increment-edx 192 eb/jump $slice-equal?:loop/disp8 193 $slice-equal?:false: 194 b8/copy-to-eax 0/imm32 195 eb/jump $slice-equal?:end/disp8 196 $slice-equal?:true: 197 b8/copy-to-eax 1/imm32 198 $slice-equal?:end: 199 # . restore registers 200 5e/pop-to-esi 201 5b/pop-to-ebx 202 5a/pop-to-edx 203 59/pop-to-ecx 204 # . epilogue 205 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 206 5d/pop-to-ebp 207 c3/return 208 209 test-slice-equal: 210 # - slice-equal?(slice("Abc"), "Abc") == 1 211 # . prologue 212 55/push-ebp 213 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 214 # (eax..ecx) = "Abc" 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} 220 51/push-ecx 221 50/push-eax 222 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 223 # eax = slice-equal?(ecx, "Abc") 224 # . . push args 225 68/push "Abc"/imm32 226 51/push-ecx 227 # . . call 228 e8/call slice-equal?/disp32 229 # . . discard args 230 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 231 # check-ints-equal(eax, 1, msg) 232 # . . push args 233 68/push "F - test-slice-equal"/imm32 234 68/push 1/imm32 235 50/push-eax 236 # . . call 237 e8/call check-ints-equal/disp32 238 # . . discard args 239 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 240 # . epilogue 241 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 242 5d/pop-to-ebp 243 c3/return 244 245 test-slice-equal-false: 246 # - slice-equal?(slice("bcd"), "Abc") == 0 247 # . prologue 248 55/push-ebp 249 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 250 # (eax..ecx) = "bcd" 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} 256 51/push-ecx 257 50/push-eax 258 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 259 # eax = slice-equal?(ecx, "Abc") 260 # . . push args 261 68/push "Abc"/imm32 262 51/push-ecx 263 # . . call 264 e8/call slice-equal?/disp32 265 # . . discard args 266 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 267 # check-ints-equal(eax, 0, msg) 268 # . . push args 269 68/push "F - test-slice-equal-false"/imm32 270 68/push 0/imm32 271 50/push-eax 272 # . . call 273 e8/call check-ints-equal/disp32 274 # . . discard args 275 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 276 # . epilogue 277 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 278 5d/pop-to-ebp 279 c3/return 280 281 test-slice-equal-too-long: 282 # - slice-equal?(slice("Abcd"), "Abc") == 0 283 # . prologue 284 55/push-ebp 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} 292 51/push-ecx 293 50/push-eax 294 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 295 # eax = slice-equal?(ecx, "Abc") 296 # . . push args 297 68/push "Abc"/imm32 298 51/push-ecx 299 # . . call 300 e8/call slice-equal?/disp32 301 # . . discard args 302 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 303 # check-ints-equal(eax, 0, msg) 304 # . . push args 305 68/push "F - test-slice-equal-too-long"/imm32 306 68/push 0/imm32 307 50/push-eax 308 # . . call 309 e8/call check-ints-equal/disp32 310 # . . discard args 311 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 312 # . epilogue 313 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 314 5d/pop-to-ebp 315 c3/return 316 317 test-slice-equal-too-short: 318 # - slice-equal?(slice("A"), "Abc") == 0 319 # . prologue 320 55/push-ebp 321 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 322 # (eax..ecx) = "A" 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} 328 51/push-ecx 329 50/push-eax 330 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 331 # eax = slice-equal?(ecx, "Abc") 332 # . . push args 333 68/push "Abc"/imm32 334 51/push-ecx 335 # . . call 336 e8/call slice-equal?/disp32 337 # . . discard args 338 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 339 # check-ints-equal(eax, 0, msg) 340 # . . push args 341 68/push "F - test-slice-equal-too-short"/imm32 342 68/push 0/imm32 343 50/push-eax 344 # . . call 345 e8/call check-ints-equal/disp32 346 # . . discard args 347 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 348 # . epilogue 349 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 350 5d/pop-to-ebp 351 c3/return 352 353 test-slice-equal-empty: 354 # - slice-equal?(slice(""), "Abc") == 0 355 # . prologue 356 55/push-ebp 357 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 358 # var slice/ecx: slice 359 68/push 0/imm32/end 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") 363 # . . push args 364 68/push "Abc"/imm32 365 51/push-ecx 366 # . . call 367 e8/call slice-equal?/disp32 368 # . . discard args 369 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 370 # check-ints-equal(eax, 0, msg) 371 # . . push args 372 68/push "F - test-slice-equal-empty"/imm32 373 68/push 0/imm32 374 50/push-eax 375 # . . call 376 e8/call check-ints-equal/disp32 377 # . . discard args 378 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 379 # . epilogue 380 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 381 5d/pop-to-ebp 382 c3/return 383 384 test-slice-equal-with-empty: 385 # - slice-equal?(slice("Ab"), "") == 0 386 # . prologue 387 55/push-ebp 388 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 389 # (eax..ecx) = "Ab" 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} 395 51/push-ecx 396 50/push-eax 397 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 398 # eax = slice-equal?(ecx, "") 399 # . . push args 400 68/push ""/imm32 401 51/push-ecx 402 # . . call 403 e8/call slice-equal?/disp32 404 # . . discard args 405 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 406 # check-ints-equal(eax, 0, msg) 407 # . . push args 408 68/push "F - test-slice-equal-with-empty"/imm32 409 68/push 0/imm32 410 50/push-eax 411 # . . call 412 e8/call check-ints-equal/disp32 413 # . . discard args 414 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 415 # . epilogue 416 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 417 5d/pop-to-ebp 418 c3/return 419 420 test-slice-equal-empty-with-empty: 421 # - slice-equal?(slice(""), "") == 1 422 # . prologue 423 55/push-ebp 424 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 425 # var slice/ecx: slice 426 68/push 0/imm32/end 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, "") 430 # . . push args 431 68/push ""/imm32 432 51/push-ecx 433 # . . call 434 e8/call slice-equal?/disp32 435 # . . discard args 436 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 437 # check-ints-equal(eax, 1, msg) 438 # . . push args 439 68/push "F - test-slice-equal-empty-with-empty"/imm32 440 68/push 1/imm32 441 50/push-eax 442 # . . call 443 e8/call check-ints-equal/disp32 444 # . . discard args 445 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 446 # . epilogue 447 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 448 5d/pop-to-ebp 449 c3/return 450 451 test-slice-equal-with-null: 452 # - slice-equal?(slice("Ab"), null) == 0 453 # . prologue 454 55/push-ebp 455 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 456 # (eax..ecx) = "Ab" 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} 462 51/push-ecx 463 50/push-eax 464 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 465 # eax = slice-equal?(ecx, 0) 466 # . . push args 467 68/push 0/imm32 468 51/push-ecx 469 # . . call 470 e8/call slice-equal?/disp32 471 # . . discard args 472 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 473 # check-ints-equal(eax, 0, msg) 474 # . . push args 475 68/push "F - test-slice-equal-with-null"/imm32 476 68/push 0/imm32 477 50/push-eax 478 # . . call 479 e8/call check-ints-equal/disp32 480 # . . discard args 481 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 482 # . epilogue 483 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 484 5d/pop-to-ebp 485 c3/return 486 487 slice-starts-with?: # s: (addr slice), head: (addr array byte) -> result/eax: boolean 488 # pseudocode 489 # hsize = head->size 490 # if (hsize > s->end - s->start) return false 491 # i = 0 492 # currs = s->start 493 # currp = head->data 494 # while i < hsize 495 # if (*currs != *currh) return false 496 # ++i 497 # ++currs 498 # ++currh 499 # return true 500 # 501 # registers: 502 # currs: esi 503 # currh: edi 504 # *currs: eax 505 # *currh: ebx 506 # i: ecx 507 # hsize: edx 508 # 509 # . prologue 510 55/push-ebp 511 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 512 # . save registers 513 51/push-ecx 514 52/push-edx 515 53/push-ebx 516 56/push-esi 517 57/push-edi 518 # esi = s 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 523 # edi = head 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 534 # var i/ecx: int = 0 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 544 # c1 = *currs 545 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL 546 # c2 = *currh 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 551 # ++i 552 41/increment-ecx 553 # ++currs 554 46/increment-esi 555 # ++currh 556 47/increment-edi 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 565 5f/pop-to-edi 566 5e/pop-to-esi 567 5b/pop-to-ebx 568 5a/pop-to-edx 569 59/pop-to-ecx 570 # . epilogue 571 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 572 5d/pop-to-ebp 573 c3/return 574 575 test-slice-starts-with-single-character: 576 # - slice-starts-with?(slice("Abc"), "A") == 1 577 # . prologue 578 55/push-ebp 579 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 580 # (eax..ecx) = "Abc" 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} 586 51/push-ecx 587 50/push-eax 588 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 589 # eax = slice-starts-with?(ecx, "A") 590 # . . push args 591 68/push "A"/imm32 592 51/push-ecx 593 # . . call 594 e8/call slice-starts-with?/disp32 595 # . . discard args 596 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 597 # check-ints-equal(eax, 1, msg) 598 # . . push args 599 68/push "F - test-slice-starts-with-single-character"/imm32 600 68/push 1/imm32 601 50/push-eax 602 # . . call 603 e8/call check-ints-equal/disp32 604 # . . discard args 605 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 606 # . epilogue 607 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 608 5d/pop-to-ebp 609 c3/return 610 611 test-slice-starts-with-empty-string: 612 # - slice-starts-with?(slice("Abc"), "") == 1 613 # . prologue 614 55/push-ebp 615 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 616 # (eax..ecx) = "Abc" 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} 622 51/push-ecx 623 50/push-eax 624 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 625 # eax = slice-starts-with?(ecx, "") 626 # . . push args 627 68/push ""/imm32 628 51/push-ecx 629 # . . call 630 e8/call slice-starts-with?/disp32 631 # . . discard args 632 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 633 # check-ints-equal(eax, 1, msg) 634 # . . push args 635 68/push "F - test-slice-starts-with-empty-string"/imm32 636 68/push 1/imm32 637 50/push-eax 638 # . . call 639 e8/call check-ints-equal/disp32 640 # . . discard args 641 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 642 # . epilogue 643 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 644 5d/pop-to-ebp 645 c3/return 646 647 test-slice-starts-with-multiple-characters: 648 # - slice-starts-with?(slice("Abc"), "Ab") == 1 649 # . prologue 650 55/push-ebp 651 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 652 # (eax..ecx) = "Abc" 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} 658 51/push-ecx 659 50/push-eax 660 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 661 # eax = slice-starts-with?(ecx, "Ab") 662 # . . push args 663 68/push "Ab"/imm32 664 51/push-ecx 665 # . . call 666 e8/call slice-starts-with?/disp32 667 # . . discard args 668 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 669 # check-ints-equal(eax, 1, msg) 670 # . . push args 671 68/push "F - test-slice-starts-with-multiple-characters"/imm32 672 68/push 1/imm32 673 50/push-eax 674 # . . call 675 e8/call check-ints-equal/disp32 676 # . . discard args 677 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 678 # . epilogue 679 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 680 5d/pop-to-ebp 681 c3/return 682 683 test-slice-starts-with-entire-string: 684 # - slice-starts-with?(slice("Abc"), "Abc") == 1 685 # . prologue 686 55/push-ebp 687 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 688 # (eax..ecx) = "Abc" 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} 694 51/push-ecx 695 50/push-eax 696 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 697 # eax = slice-starts-with?(ecx, "Abc") 698 # . . push args 699 68/push "Abc"/imm32 700 51/push-ecx 701 # . . call 702 e8/call slice-starts-with?/disp32 703 # . . discard args 704 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 705 # check-ints-equal(eax, 1, msg) 706 # . . push args 707 68/push "F - test-slice-starts-with-entire-string"/imm32 708 68/push 1/imm32 709 50/push-eax 710 # . . call 711 e8/call check-ints-equal/disp32 712 # . . discard args 713 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 714 # . epilogue 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-slice-starts-with-fails: 720 # - slice-starts-with?(slice("Abc"), "Abd") == 1 721 # . prologue 722 55/push-ebp 723 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 724 # (eax..ecx) = "Abc" 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} 730 51/push-ecx 731 50/push-eax 732 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 733 # eax = slice-starts-with?(ecx, "Abd") 734 # . . push args 735 68/push "Abd"/imm32 736 51/push-ecx 737 # . . call 738 e8/call slice-starts-with?/disp32 739 # . . discard args 740 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 741 # check-ints-equal(eax, 0, msg) 742 # . . push args 743 68/push "F - test-slice-starts-with-fails"/imm32 744 68/push 0/imm32 745 50/push-eax 746 # . . call 747 e8/call check-ints-equal/disp32 748 # . . discard args 749 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 750 # . epilogue 751 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 752 5d/pop-to-ebp 753 c3/return 754 755 test-slice-starts-with-fails-2: 756 # - slice-starts-with?(slice("Abc"), "Ac") == 1 757 # . prologue 758 55/push-ebp 759 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 760 # (eax..ecx) = "Abc" 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} 766 51/push-ecx 767 50/push-eax 768 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 769 # eax = slice-starts-with?(ecx, "Ac") 770 # . . push args 771 68/push "Ac"/imm32 772 51/push-ecx 773 # . . call 774 e8/call slice-starts-with?/disp32 775 # . . discard args 776 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 777 # check-ints-equal(eax, 0, msg) 778 # . . push args 779 68/push "F - test-slice-starts-with-fails-2"/imm32 780 68/push 0/imm32 781 50/push-eax 782 # . . call 783 e8/call check-ints-equal/disp32 784 # . . discard args 785 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 786 # . epilogue 787 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 788 5d/pop-to-ebp 789 c3/return 790 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) 794 # . prologue 795 55/push-ebp 796 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 797 # . save registers 798 50/push-eax 799 51/push-ecx 800 52/push-edx 801 53/push-ebx 802 56/push-esi 803 57/push-edi 804 # esi = s 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 810 # edi = out 811 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi 812 # edx = out->size 813 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 2/r32/edx 8/disp8 . # copy *(edi+8) to edx 814 # ebx = out->write 815 8b/copy 0/mod/indirect 7/rm32/edi . . . 3/r32/ebx . . # copy *edi to ebx 816 $write-slice:loop: 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 824 # . AL = *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) 829 # ++out->write 830 43/increment-ebx 831 # ++in 832 41/increment-ecx 833 eb/jump $write-slice:loop/disp8 834 $write-slice:loop-end: 835 # persist out->write 836 89/copy 0/mod/indirect 7/rm32/edi . . . 3/r32/ebx . . # copy ebx to *edi 837 $write-slice:end: 838 # . restore registers 839 5f/pop-to-edi 840 5e/pop-to-esi 841 5b/pop-to-ebx 842 5a/pop-to-edx 843 59/pop-to-ecx 844 58/pop-to-eax 845 # . epilogue 846 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 847 5d/pop-to-ebp 848 c3/return 849 850 $write-slice:abort: 851 (abort "write-slice: out of space") 852 # never gets here 853 854 test-write-slice: 855 # . prologue 856 55/push-ebp 857 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 858 # setup 859 # . clear-stream(_test-stream) 860 # . . push args 861 68/push _test-stream/imm32 862 # . . call 863 e8/call clear-stream/disp32 864 # . . discard args 865 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 866 # (eax..ecx) = "Abc" 867 b8/copy-to-eax "Abc"/imm32 868 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 869 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 870 05/add-to-eax 4/imm32 871 # var slice/ecx: slice = {eax, ecx} 872 51/push-ecx 873 50/push-eax 874 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 875 # write-slice(_test-stream, slice) 876 # . . push args 877 51/push-ecx 878 68/push _test-stream/imm32 879 # . . call 880 e8/call write-slice/disp32 881 # . . discard args 882 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 883 # check-stream-equal(_test-stream, "Abc", msg) 884 # . . push args 885 68/push "F - test-write-slice"/imm32 886 68/push "Abc"/imm32 887 68/push _test-stream/imm32 888 # . . call 889 e8/call check-stream-equal/disp32 890 # . . discard args 891 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 892 # . epilogue 893 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 894 5d/pop-to-ebp 895 c3/return 896 897 # copy a slice into a new (dynamically allocated) string 898 slice-to-string: # ad: (addr allocation-descriptor), in: (addr slice), out: (addr handle array byte) 899 # . prologue 900 55/push-ebp 901 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 902 # . save registers 903 50/push-eax 904 51/push-ecx 905 52/push-edx 906 53/push-ebx 907 56/push-esi 908 # esi = in 909 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 0xc/disp8 . # copy *(ebp+12) to esi 910 # var curr/edx: (addr byte) = in->start 911 8b/copy 0/mod/indirect 6/rm32/esi . . . 2/r32/edx . . # copy *esi to edx 912 # var max/ebx: (addr byte) = in->end 913 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 3/r32/ebx 4/disp8 . # copy *(esi+4) to ebx 914 # var size/ecx: int = max - curr + 4 # total size of output string (including the initial 'size' field) 915 89/copy 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # copy ebx to ecx 916 29/subtract 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # subtract edx from ecx 917 81 0/subop/add 3/mod/direct 1/rm32/ecx . . . . . 4/imm32 # add to ecx 918 # allocate(ad, size, out) 919 # . . push args 920 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) 921 51/push-ecx 922 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 923 # . . call 924 e8/call allocate/disp32 925 # . . discard args 926 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 927 # eax = out->payload 928 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 0x10/disp8 . # copy *(ebp+16) to eax 929 8b/copy 1/mod/*+disp8 0/rm32/eax . . . 0/r32/eax 4/disp8 . # copy *(eax+4) to eax 930 # skip payload->allocid 931 05/add-to-eax 4/imm32 932 # if (eax == 0) abort 933 3d/compare-eax-and 0/imm32 934 74/jump-if-= $slice-to-string:abort/disp8 935 # out->size = size-4 936 89/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to *eax 937 81 5/subop/subtract 0/mod/indirect 0/rm32/eax . . . . . 4/imm32 # subtract 4 from *eax 938 # save out 939 50/push-eax 940 $slice-to-string:initialize: 941 # eax = _append-4(eax+4, eax+size, curr, max) # clobbering ecx 942 # . . push args 943 53/push-ebx 944 52/push-edx 945 # . . push eax+size (clobbering ecx) 946 01/add 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # add eax to ecx 947 51/push-ecx 948 # . . push eax+4 (clobbering eax) 949 81 0/subop/add 3/mod/direct 0/rm32/eax . . . . . 4/imm32 # add to eax 950 50/push-eax 951 # . . call 952 e8/call _append-4/disp32 953 # . . discard args 954 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 955 # restore out (assumes _append-4 can't error) 956 58/pop-to-eax 957 $slice-to-string:end: 958 # . restore registers 959 5e/pop-to-esi 960 5b/pop-to-ebx 961 5a/pop-to-edx 962 59/pop-to-ecx 963 58/pop-to-eax 964 # . epilogue 965 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 966 5d/pop-to-ebp 967 c3/return 968 969 $slice-to-string:abort: 970 (abort "slice-to-string: out of space") 971 # never gets here 972 973 test-slice-to-string: 974 # . prologue 975 55/push-ebp 976 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 977 # var ad/edx: allocation-descriptor containing 16 bytes 978 # . var end/ecx: (addr byte) 979 89/<- %ecx 4/r32/esp 980 81 5/subop/subtract %esp 0x10/imm32 981 # . var start/edx: (addr byte) = end - 0x10 982 89/<- %edx 4/r32/esp 983 # . ad = {start, end} 984 51/push-ecx 985 52/push-edx 986 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx 987 # (eax..ecx) = "Abc" 988 b8/copy-to-eax "Abc"/imm32 989 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 990 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 991 05/add-to-eax 4/imm32 992 # var slice/ecx: slice = {eax, ecx} 993 51/push-ecx 994 50/push-eax 995 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 996 # var h/ebx: (handle array byte) 997 68/push 0/imm32 998 68/push 0/imm32 999 89/copy 3/mod/direct 3/rm32/ebx . . . 4/r32/esp . . # copy esp to ebx 1000 # slice-to-string(ad, slice, h) 1001 # . . push args 1002 53/push-ebx 1003 51/push-ecx 1004 52/push-edx 1005 # . . call 1006 e8/call slice-to-string/disp32 1007 # . . discard args 1008 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1009 # eax = h->payload 1010 8b/copy 1/mod/*+disp8 3/rm32/ebx . . . 0/r32/eax 4/disp8 . # copy *(ebx+4) to eax 1011 # skip payload->allocid 1012 05/add-to-eax 4/imm32 1013 +-- 26 lines: #? # dump eax --------------------------------------------------------------------------------------------------------------------------------------------------------- 1039 # eax = string-equal?(eax, "Abc") 1040 # . . push args 1041 68/push "Abc"/imm32 1042 50/push-eax 1043 # . . call 1044 e8/call string-equal?/disp32 1045 # . . discard args 1046 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1047 # check-ints-equal(eax, 1, msg) 1048 # . . push args 1049 68/push "F - test-slice-to-string"/imm32 1050 68/push 1/imm32/true 1051 50/push-eax 1052 # . . call 1053 e8/call check-ints-equal/disp32 1054 # . . discard args 1055 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1056 # . reclaim locals 1057 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x18/imm32 # add to esp 1058 # . epilogue 1059 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1060 5d/pop-to-ebp 1061 c3/return 1062 1063 # . . vim:nowrap:textwidth=0