https://github.com/akkartik/mu/blob/master/apps/hex.subx
   1 # Read a text file containing whitespace-separated pairs of ascii hex bytes
   2 # from stdin, and convert them into binary bytes (octets) on stdout. Ignore
   3 # comments between '#' and newline.
   4 #
   5 # To run:
   6 #   $ ./bootstrap translate init.linux 0*.subx apps/subx-params.subx apps/hex.subx  -o apps/hex
   7 #   $ echo '80 81 82  # comment'  |./bootstrap run apps/hex  |xxd -
   8 # Expected output:
   9 #   00000000: 8081 82
  10 #
  11 # Only hex bytes and comments are permitted. Outside of comments all words
  12 # must be exactly 2 characters long and contain only characters [0-9a-f]. No
  13 # uppercase hex.
  14 
  15 == code
  16 #   instruction                     effective address                                                   register    displacement    immediate
  17 # . op          subop               mod             rm32          base        index         scale       r32
  18 # . 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
  19 
  20 Entry:  # run tests if necessary, convert stdin if not
  21     # . prologue
  22     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
  23 
  24     # initialize heap
  25     # . Heap = new-segment(Heap-size)
  26     # . . push args
  27     68/push  Heap/imm32
  28     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Heap-size/disp32                  # push *Heap-size
  29     # . . call
  30     e8/call  new-segment/disp32
  31     # . . discard args
  32     81          0/subop/add         3/mod/direct    4/rm32/esp    .          
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - mu-init-test.subx</title>
<meta name="Generator" content="Vim/8.1">
<meta name="plugin-version" content="vim8.1_v1">
<meta name="syntax" content="none">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
<meta name="colorscheme" content="minimal-light">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #c6c6c6; }
body { font-size:12pt; font-family: monospace; color: #000000; background-color: #c6c6c6; }
a { color:inherit; }
* { font-size:12pt; font-size: 1em; }
.subxComment { color: #005faf; }
.LineNr { }
.SpecialChar { color: #d70000; }
.subxS1Comment { color: #0000af; }
.subxFunction { color: #af5f00; text-decoration: underline; }
.Constant { color: #008787; }
-->
</style>

<script type='text/javascript'>
<!--

/* function to open any folds containing a jumped-to line before jumping to it */
function JumpToLine()
{
  var lineNum;
  lineNum = window.location.hash;
  lineNum = lineNum.substr(1); /* strip off '#' */

  if (lineNum.indexOf('L') == -1) {
    lineNum = 'L'+lineNum;
  }
  var lineElem = document.getElementById(lineNum);
  /* Always jump to new location even if the line was hidden inside a fold, or
   * we corrected the raw number to a line ID.
   */
  if (lineElem) {
    lineElem.scrollIntoView(true);
  }
  return true;
}
if ('onhashchange' in window) {
  window.onhashchange = JumpToLine;
}

-->
</script>
</head>
<body onload='JumpToLine();'>
<a href='https://github.com/akkartik/mu/blob/master/mu-init-test.subx'>https://github.com/akkartik/mu/blob/master/mu-init-test.subx</a>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr"> 1 </span><span class="subxComment"># Just a test stub for mu-init.subx</span>
<span id="L2" class="LineNr"> 2 </span><span class="subxComment">#</span>
<span id="L3" class="LineNr"> 3 </span><span class="subxComment"># Try it out like this:</span>
<span id="L4" class="LineNr"> 4 </span><span class="subxComment">#   $ ./translate_subx init.linux [0-9]*.subx mu-init.subx mu-init-test.subx</span>
<span id="L5" class="LineNr"> 5 </span><span class="subxComment">#   $ ./a.elf  # should run all tests</span>
<span id="L6" class="LineNr"> 6 </span>
<span id="L7" class="LineNr"> 7 </span><span class="subxFunction">main</span>:  <span class="subxComment"># args: (addr array (addr array byte)) -&gt; result/ebx: int</span>
<span id="L8" class="LineNr"> 8 </span>    <span class="subxS1Comment"># . prologue</span>
<span id="L9" class="LineNr"> 9 </span>    55/push-ebp
<span id="L10" class="LineNr">10 </span>    89/&lt;- %ebp 4/r32/esp
<span id="L11" class="LineNr">11 </span>    <span class="subxS1Comment"># . save registers</span>
<span id="L12" class="LineNr">12 </span>    50/push-eax
<span id="L13" class="LineNr">13 </span>    56/push-esi
<span id="L14" class="LineNr">14 </span>    <span class="subxComment"># esi = args</span>
<span id="L15" class="LineNr">15 </span>    8b/-&gt; *(ebp+8) 6/r32/esi
<span id="L16" class="LineNr">16 </span>    {
<span id="L17" class="LineNr">17 </span>      <span class="subxComment"># if (argc &lt;= 1) break</span>
<span id="L18" class="LineNr">18 </span>      81 7/subop/compare *esi 4/imm32
<span id="L19" class="LineNr">19 </span>      7e/jump-if-&lt;= <span class="Constant">break</span>/disp8
<span id="L20" class="LineNr">20 </span>      <span class="subxComment"># if (argv[1] != &quot;test&quot;) break</span>
<span id="L21" class="LineNr">21 </span>      (<a href='105string-equal.subx.html#L15'>string-equal?</a> *(esi+8) <span class="Constant">&quot;test&quot;</span>)  <span class="subxComment"># =&gt; eax</span>
<span id="L22" class="LineNr">22 </span>      3d/compare-eax-and 0/imm32
<span id="L23" class="LineNr">23 </span>      74/jump-if-= <span class="Constant">break</span>/disp8
<span id="L24" class="LineNr">24 </span>      <span class="subxComment">#</span>
<span id="L25" class="LineNr">25 </span>      (run-tests)
<span id="L26" class="LineNr">26 </span>      <span class="subxComment"># return *Num-test-failures</span>
<span id="L27" class="LineNr">27 </span>      8b/-&gt; *<span class="SpecialChar"><a href='102test.subx.html#L89'>Num-test-failures</a></span> 3/r32/ebx
<span id="L28" class="LineNr">28 </span>      eb/jump $main:end/disp8
<span id="L29" class="LineNr">29 </span>    }
<span id="L30" class="LineNr">30 </span><span class="Constant">$main:end</span>:
<span id="L31" class="LineNr">31 </span>    <span class="subxS1Comment"># . restore registers</span>
<span id="L32" class="LineNr">32 </span>    5e/pop-to-esi
<span id="L33" class="LineNr">33 </span>    58/pop-to-eax
<span id="L34" class="LineNr">34 </span>    <span class="subxS1Comment"># . epilogue</span>
<span id="L35" class="LineNr">35 </span>    89/&lt;- %esp 5/r32/ebp
<span id="L36" class="LineNr">36 </span>    5d/pop-to-ebp
<span id="L37" class="LineNr">37 </span>    c3/return
</pre>
</body>
</html>
<!-- vim: set foldmethod=manual : -->
Nr"> 280 75/jump-if-!= $test-convert-next-octet:end/disp8 281 # check-ints-equal(eax, 0xab, msg) 282 # . . push args 283 68/push "F - test-convert-next-octet"/imm32 284 68/push 0xab/imm32/ab 285 50/push-eax 286 # . . call 287 e8/call check-ints-equal/disp32 288 # . . discard args 289 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 290 $test-convert-next-octet:end: 291 # . epilogue 292 # don't restore esp from ebp; manually reclaim locals 293 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 294 5d/pop-to-ebp 295 c3/return 296 297 test-convert-next-octet-handles-Eof: 298 # - check that reaching end of file returns Eof 299 # This test uses exit-descriptors. Use ebp for setting up local variables. 300 55/push-ebp 301 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 302 # clear all streams 303 # . clear-stream(_test-stream) 304 # . . push args 305 68/push _test-stream/imm32 306 # . . call 307 e8/call clear-stream/disp32 308 # . . discard args 309 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 310 # . clear-stream($_test-buffered-file->buffer) 311 # . . push args 312 68/push $_test-buffered-file->buffer/imm32 313 # . . call 314 e8/call clear-stream/disp32 315 # . . discard args 316 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 317 # . clear-stream(_test-error-stream) 318 # . . push args 319 68/push _test-error-stream/imm32 320 # . . call 321 e8/call clear-stream/disp32 322 # . . discard args 323 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 324 # . clear-stream($_test-error-buffered-file->buffer) 325 # . . push args 326 68/push $_test-error-buffered-file->buffer/imm32 327 # . . call 328 e8/call clear-stream/disp32 329 # . . discard args 330 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 331 # don't initialize '_test-stream' 332 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below 333 # . var ed/ecx: exit-descriptor 334 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 335 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 336 # . tailor-exit-descriptor(ed, 12) 337 # . . push args 338 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet 339 51/push-ecx/ed 340 # . . call 341 e8/call tailor-exit-descriptor/disp32 342 # . . discard args 343 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 344 # eax = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) 345 # . . push args 346 51/push-ecx/ed 347 68/push _test-error-buffered-file/imm32 348 68/push _test-buffered-file/imm32 349 # . . call 350 e8/call convert-next-octet/disp32 351 # registers except esp may be clobbered at this point 352 # pop args to convert-next-octet 353 # . . discard first 2 args 354 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 355 # . . restore ed 356 59/pop-to-ecx 357 # check that convert-next-octet didn't abort 358 # . check-ints-equal(ed->value, 0, msg) 359 # . . push args 360 68/push "F - test-convert-next-octet: unexpected abort"/imm32 361 68/push 0/imm32 362 # . . push ed->value 363 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 364 # . . call 365 e8/call check-ints-equal/disp32 366 # . . discard args 367 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 368 # return if abort 369 81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4) 370 75/jump-if-!= $test-convert-next-octet-handles-Eof:end/disp8 371 # check-ints-equal(eax, Eof, msg) 372 # . . push args 373 68/push "F - test-convert-next-octet-handles-Eof"/imm32 374 68/push 0xffffffff/imm32/Eof 375 50/push-eax 376 # . . call 377 e8/call check-ints-equal/disp32 378 # . . discard args 379 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 380 $test-convert-next-octet-handles-Eof:end: 381 # . epilogue 382 # don't restore esp from ebp; manually reclaim locals 383 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 384 5d/pop-to-ebp 385 c3/return 386 387 test-convert-next-octet-aborts-on-single-hex-byte: 388 # - check that a single unaccompanied hex byte aborts 389 # This test uses exit-descriptors. Use ebp for setting up local variables. 390 55/push-ebp 391 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 392 # clear all streams 393 # . clear-stream(_test-stream) 394 # . . push args 395 68/push _test-stream/imm32 396 # . . call 397 e8/call clear-stream/disp32 398 # . . discard args 399 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 400 # . clear-stream($_test-buffered-file->buffer) 401 # . . push args 402 68/push $_test-buffered-file->buffer/imm32 403 # . . call 404 e8/call clear-stream/disp32 405 # . . discard args 406 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 407 # . clear-stream(_test-error-stream) 408 # . . push args 409 68/push _test-error-stream/imm32 410 # . . call 411 e8/call clear-stream/disp32 412 # . . discard args 413 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 414 # . clear-stream($_test-error-buffered-file->buffer) 415 # . . push args 416 68/push $_test-error-buffered-file->buffer/imm32 417 # . . call 418 e8/call clear-stream/disp32 419 # . . discard args 420 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 421 # initialize '_test-stream' to "a" 422 # . write(_test-stream, "a") 423 # . . push args 424 68/push "a"/imm32 425 68/push _test-stream/imm32 426 # . . call 427 e8/call write/disp32 428 # . . discard args 429 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 430 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below 431 # . var ed/ecx: exit-descriptor 432 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 433 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 434 # . tailor-exit-descriptor(ed, 12) 435 # . . push args 436 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet 437 51/push-ecx/ed 438 # . . call 439 e8/call tailor-exit-descriptor/disp32 440 # . . discard args 441 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 442 # eax = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) 443 # . . push args 444 51/push-ecx/ed 445 68/push _test-error-buffered-file/imm32 446 68/push _test-buffered-file/imm32 447 # . . call 448 e8/call convert-next-octet/disp32 449 # registers except esp may be clobbered at this point 450 # pop args to convert-next-octet 451 # . . discard first 2 args 452 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 453 # . . restore ed 454 59/pop-to-ecx 455 # check that convert-next-octet aborted 456 # . check-ints-equal(ed->value, 2, msg) 457 # . . push args 458 68/push "F - test-convert-next-octet-aborts-on-single-hex-byte: unexpected abort"/imm32 459 68/push 2/imm32 460 # . . push ed->value 461 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 462 # . . call 463 e8/call check-ints-equal/disp32 464 # . . discard args 465 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 466 $test-convert-next-octet-aborts-on-single-hex-byte:end: 467 # . epilogue 468 # don't restore esp from ebp; manually reclaim locals 469 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 470 5d/pop-to-ebp 471 c3/return 472 473 # read whitespace until a hex byte, and return it 474 # return Eof if file ends without finding a hex byte 475 # on '#' skip all bytes until newline 476 # abort on any other byte 477 scan-next-byte: # in: (addr buffered-file), err: (addr buffered-file), ed: (addr exit-descriptor) -> byte-or-Eof/eax 478 # pseudocode: 479 # while true 480 # eax = read-byte-buffered(in) 481 # if (eax == Eof) return eax 482 # if (is-hex-digit?(eax)) return eax 483 # if (eax == ' ' or '\t' or '\n') continue 484 # if (eax == '#') skip-until-newline(in) 485 # else error-byte(ed, err, "invalid byte: " eax) 486 # 487 # . prologue 488 55/push-ebp 489 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 490 # . save registers 491 $scan-next-byte:loop: 492 # eax = read-byte-buffered(in) 493 # . . push args 494 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 495 # . . call 496 e8/call read-byte-buffered/disp32 497 # . . discard args 498 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 499 # if (eax == Eof) return eax 500 3d/compare-with-eax 0xffffffff/imm32/Eof 501 74/jump-if-= $scan-next-byte:end/disp8 502 # if (is-hex-digit?(eax)) return eax 503 # . save eax for now 504 50/push-eax 505 # . is-hex-digit?(eax) 506 # . . push args 507 50/push-eax 508 # . . call 509 e8/call is-hex-digit?/disp32 510 # . . discard args 511 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 512 # . compare with 'false' 513 3d/compare-with-eax 0/imm32/false 514 # . restore eax (does not affect flags) 515 58/pop-to-eax 516 # . check whether to return 517 75/jump-if-!= $scan-next-byte:end/disp8 518 $scan-next-byte:check1: 519 # if (eax == ' ') continue 520 3d/compare-eax-and 0x20/imm32/space 521 74/jump-if-= $scan-next-byte:loop/disp8 522 # if (eax == '\t') continue 523 3d/compare-eax-and 9/imm32/tab 524 74/jump-if-= $scan-next-byte:loop/disp8 525 # if (eax == '\n') continue 526 3d/compare-eax-and 0xa/imm32/newline 527 74/jump-if-= $scan-next-byte:loop/disp8 528 $scan-next-byte:check2: 529 # if (eax == '#') skip-until-newline(in) 530 3d/compare-with-eax 0x23/imm32/hash 531 75/jump-if-!= $scan-next-byte:check3/disp8 532 # . skip-until-newline(in) 533 # . . push args 534 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 535 # . . call 536 e8/call skip-until-newline/disp32 537 # . . discard args 538 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 539 eb/jump $scan-next-byte:loop/disp8 540 $scan-next-byte:check3: 541 # otherwise error-byte(ed, err, msg, eax) 542 # . . push args 543 50/push-eax 544 68/push "scan-next-byte: invalid byte"/imm32 545 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 546 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) 547 # . . call 548 e8/call error-byte/disp32 # never returns 549 $scan-next-byte:end: 550 # . restore registers 551 # . epilogue 552 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 553 5d/pop-to-ebp 554 c3/return 555 556 test-scan-next-byte: 557 # - check that the first byte of the input is returned 558 # This test uses exit-descriptors. Use ebp for setting up local variables. 559 55/push-ebp 560 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 561 # clear all streams 562 # . clear-stream(_test-stream) 563 # . . push args 564 68/push _test-stream/imm32 565 # . . call 566 e8/call clear-stream/disp32 567 # . . discard args 568 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 569 # . clear-stream($_test-buffered-file->buffer) 570 # . . push args 571 68/push $_test-buffered-file->buffer/imm32 572 # . . call 573 e8/call clear-stream/disp32 574 # . . discard args 575 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 576 # . clear-stream(_test-error-stream) 577 # . . push args 578 68/push _test-error-stream/imm32 579 # . . call 580 e8/call clear-stream/disp32 581 # . . discard args 582 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 583 # . clear-stream($_test-error-buffered-file->buffer) 584 # . . push args 585 68/push $_test-error-buffered-file->buffer/imm32 586 # . . call 587 e8/call clear-stream/disp32 588 # . . discard args 589 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 590 # initialize '_test-stream' to "abc" 591 # . write(_test-stream, "abc") 592 # . . push args 593 68/push "abc"/imm32 594 68/push _test-stream/imm32 595 # . . call 596 e8/call write/disp32 597 # . . discard args 598 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 599 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below 600 # . var ed/ecx: exit-descriptor 601 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 602 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 603 # . tailor-exit-descriptor(ed, 12) 604 # . . push args 605 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte 606 51/push-ecx/ed 607 # . . call 608 e8/call tailor-exit-descriptor/disp32 609 # . . discard args 610 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 611 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 612 # . . push args 613 51/push-ecx/ed 614 68/push _test-error-buffered-file/imm32 615 68/push _test-buffered-file/imm32 616 # . . call 617 e8/call scan-next-byte/disp32 618 # registers except esp may be clobbered at this point 619 # pop args to scan-next-byte 620 # . . discard first 2 args 621 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 622 # . . restore ed 623 59/pop-to-ecx 624 # check that scan-next-byte didn't abort 625 # . check-ints-equal(ed->value, 0, msg) 626 # . . push args 627 68/push "F - test-scan-next-byte: unexpected abort"/imm32 628 68/push 0/imm32 629 # . . push ed->value 630 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 631 # . . call 632 e8/call check-ints-equal/disp32 633 # . . discard args 634 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 635 # return if abort 636 81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4) 637 75/jump-if-!= $test-scan-next-byte:end/disp8 638 # check-ints-equal(eax, 0x61/a, msg) 639 # . . push args 640 68/push "F - test-scan-next-byte"/imm32 641 68/push 0x61/imm32/a 642 50/push-eax 643 # . . call 644 e8/call check-ints-equal/disp32 645 # . . discard args 646 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 647 $test-scan-next-byte:end: 648 # . epilogue 649 # don't restore esp from ebp; manually reclaim locals 650 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 651 5d/pop-to-ebp 652 c3/return 653 654 test-scan-next-byte-skips-whitespace: 655 # - check that the first byte after whitespace is returned 656 # This test uses exit-descriptors. Use ebp for setting up local variables. 657 55/push-ebp 658 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 659 # clear all streams 660 # . clear-stream(_test-stream) 661 # . . push args 662 68/push _test-stream/imm32 663 # . . call 664 e8/call clear-stream/disp32 665 # . . discard args 666 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 667 # . clear-stream($_test-buffered-file->buffer) 668 # . . push args 669 68/push $_test-buffered-file->buffer/imm32 670 # . . call 671 e8/call clear-stream/disp32 672 # . . discard args 673 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 674 # . clear-stream(_test-error-stream) 675 # . . push args 676 68/push _test-error-stream/imm32 677 # . . call 678 e8/call clear-stream/disp32 679 # . . discard args 680 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 681 # . clear-stream($_test-error-buffered-file->buffer) 682 # . . push args 683 68/push $_test-error-buffered-file->buffer/imm32 684 # . . call 685 e8/call clear-stream/disp32 686 # . . discard args 687 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 688 # initialize '_test-stream' to input with leading whitespace 689 # . write(_test-stream, text) 690 # . . push args 691 68/push " abc"/imm32 692 68/push _test-stream/imm32 693 # . . call 694 e8/call write/disp32 695 # . . discard args 696 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 697 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below 698 # . var ed/ecx: exit-descriptor 699 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 700 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 701 # . tailor-exit-descriptor(ed, 12) 702 # . . push args 703 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte 704 51/push-ecx/ed 705 # . . call 706 e8/call tailor-exit-descriptor/disp32 707 # . . discard args 708 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 709 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 710 # . . push args 711 51/push-ecx/ed 712 68/push _test-error-buffered-file/imm32 713 68/push _test-buffered-file/imm32 714 # . . call 715 e8/call scan-next-byte/disp32 716 # registers except esp may be clobbered at this point 717 # pop args to scan-next-byte 718 # . . discard first 2 args 719 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 720 # . . restore ed 721 59/pop-to-ecx 722 # check that scan-next-byte didn't abort 723 # . check-ints-equal(ed->value, 0, msg) 724 # . . push args 725 68/push "F - test-scan-next-byte-skips-whitespace: unexpected abort"/imm32 726 68/push 0/imm32 727 # . . push ed->value 728 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 729 # . . call 730 e8/call check-ints-equal/disp32 731 # . . discard args 732 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 733 # return if abort 734 81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4) 735 75/jump-if-!= $test-scan-next-byte-skips-whitespace:end/disp8 736 # check-ints-equal(eax, 0x61/a, msg) 737 # . . push args 738 68/push "F - test-scan-next-byte-skips-whitespace"/imm32 739 68/push 0x61/imm32/a 740 50/push-eax 741 # . . call 742 e8/call check-ints-equal/disp32 743 # . . discard args 744 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 745 $test-scan-next-byte-skips-whitespace:end: 746 # . epilogue 747 # don't restore esp from ebp; manually reclaim locals 748 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 749 5d/pop-to-ebp 750 c3/return 751 752 test-scan-next-byte-skips-comment: 753 # - check that the first byte after a comment (and newline) is returned 754 # This test uses exit-descriptors. Use ebp for setting up local variables. 755 55/push-ebp 756 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 757 # clear all streams 758 # . clear-stream(_test-stream) 759 # . . push args 760 68/push _test-stream/imm32 761 # . . call 762 e8/call clear-stream/disp32 763 # . . discard args 764 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 765 # . clear-stream($_test-buffered-file->buffer) 766 # . . push args 767 68/push $_test-buffered-file->buffer/imm32 768 # . . call 769 e8/call clear-stream/disp32 770 # . . discard args 771 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 772 # . clear-stream(_test-error-stream) 773 # . . push args 774 68/push _test-error-stream/imm32 775 # . . call 776 e8/call clear-stream/disp32 777 # . . discard args 778 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 779 # . clear-stream($_test-error-buffered-file->buffer) 780 # . . push args 781 68/push $_test-error-buffered-file->buffer/imm32 782 # . . call 783 e8/call clear-stream/disp32 784 # . . discard args 785 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 786 # initialize '_test-stream' to input with leading comment 787 # . write(_test-stream, comment) 788 # . . push args 789 68/push "#x\n"/imm32 790 68/push _test-stream/imm32 791 # . . call 792 e8/call write/disp32 793 # . . discard args 794 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 795 # . write(_test-stream, real text) 796 # . . push args 797 68/push "ab"/imm32 798 68/push _test-stream/imm32 799 # . . call 800 e8/call write/disp32 801 # . . discard args 802 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 803 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below 804 # . var ed/ecx: exit-descriptor 805 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 806 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 807 # . tailor-exit-descriptor(ed, 12) 808 # . . push args 809 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte 810 51/push-ecx/ed 811 # . . call 812 e8/call tailor-exit-descriptor/disp32 813 # . . discard args 814 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 815 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 816 # . . push args 817 51/push-ecx/ed 818 68/push _test-error-buffered-file/imm32 819 68/push _test-buffered-file/imm32 820 # . . call 821 e8/call scan-next-byte/disp32 822 # registers except esp may be clobbered at this point 823 # pop args to scan-next-byte 824 # . . discard first 2 args 825 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 826 # . . restore ed 827 59/pop-to-ecx 828 # check that scan-next-byte didn't abort 829 # . check-ints-equal(ed->value, 0, msg) 830 # . . push args 831 68/push "F - test-scan-next-byte-skips-comment: unexpected abort"/imm32 832 68/push 0/imm32 833 # . . push ed->value 834 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 835 # . . call 836 e8/call check-ints-equal/disp32 837 # . . discard args 838 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 839 # return if abort 840 81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4) 841 75/jump-if-!= $test-scan-next-byte-skips-comment:end/disp8 842 # check-ints-equal(eax, 0x61/a, msg) 843 # . . push args 844 68/push "F - test-scan-next-byte-skips-comment"/imm32 845 68/push 0x61/imm32/a 846 50/push-eax 847 # . . call 848 e8/call check-ints-equal/disp32 849 # . . discard args 850 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 851 $test-scan-next-byte-skips-comment:end: 852 # . epilogue 853 # don't restore esp from ebp; manually reclaim locals 854 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 855 5d/pop-to-ebp 856 c3/return 857 858 test-scan-next-byte-skips-comment-and-whitespace: 859 # - check that the first byte after a comment and any further whitespace is returned 860 # This test uses exit-descriptors. Use ebp for setting up local variables. 861 55/push-ebp 862 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 863 # clear all streams 864 # . clear-stream(_test-stream) 865 # . . push args 866 68/push _test-stream/imm32 867 # . . call 868 e8/call clear-stream/disp32 869 # . . discard args 870 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 871 # . clear-stream($_test-buffered-file->buffer) 872 # . . push args 873 68/push $_test-buffered-file->buffer/imm32 874 # . . call 875 e8/call clear-stream/disp32 876 # . . discard args 877 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 878 # . clear-stream(_test-error-stream) 879 # . . push args 880 68/push _test-error-stream/imm32 881 # . . call 882 e8/call clear-stream/disp32 883 # . . discard args 884 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 885 # . clear-stream($_test-error-buffered-file->buffer) 886 # . . push args 887 68/push $_test-error-buffered-file->buffer/imm32 888 # . . call 889 e8/call clear-stream/disp32 890 # . . discard args 891 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 892 # initialize '_test-stream' to input with leading comment and more whitespace after newline 893 # . write(_test-stream, comment) 894 # . . push args 895 68/push "#x\n"/imm32 896 68/push _test-stream/imm32 897 # . . call 898 e8/call write/disp32 899 # . . discard args 900 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 901 # . write(_test-stream, real text) 902 # . . push args 903 68/push " ab"/imm32 904 68/push _test-stream/imm32 905 # . . call 906 e8/call write/disp32 907 # . . discard args 908 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 909 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below 910 # . var ed/ecx: exit-descriptor 911 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 912 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 913 # . tailor-exit-descriptor(ed, 12) 914 # . . push args 915 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte 916 51/push-ecx/ed 917 # . . call 918 e8/call tailor-exit-descriptor/disp32 919 # . . discard args 920 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 921 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 922 # . . push args 923 51/push-ecx/ed 924 68/push _test-error-buffered-file/imm32 925 68/push _test-buffered-file/imm32 926 # . . call 927 e8/call scan-next-byte/disp32 928 # registers except esp may be clobbered at this point 929 # pop args to scan-next-byte 930 # . . discard first 2 args 931 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 932 # . . restore ed 933 59/pop-to-ecx 934 # check that scan-next-byte didn't abort 935 # . check-ints-equal(ed->value, 0, msg) 936 # . . push args 937 68/push "F - test-scan-next-byte-skips-comment-and-whitespace: unexpected abort"/imm32 938 68/push 0/imm32 939 # . . push ed->value 940 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 941 # . . call 942 e8/call check-ints-equal/disp32 943 # . . discard args 944 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 945 # return if abort 946 81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4) 947 75/jump-if-!= $test-scan-next-byte-skips-comment-and-whitespace:end/disp8 948 # check-ints-equal(eax, 0x61/a, msg) 949 # . . push args 950 68/push "F - test-scan-next-byte-skips-comment-and-whitespace"/imm32 951 68/push 0x61/imm32/a 952 50/push-eax 953 # . . call 954 e8/call check-ints-equal/disp32 955 # . . discard args 956 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 957 $test-scan-next-byte-skips-comment-and-whitespace:end: 958 # . epilogue 959 # don't restore esp from ebp; manually reclaim locals 960 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 961 5d/pop-to-ebp 962 c3/return 963 964 test-scan-next-byte-skips-whitespace-and-comment: 965 # - check that the first byte after any whitespace and comments is returned 966 # This test uses exit-descriptors. Use ebp for setting up local variables. 967 55/push-ebp 968 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 969 # clear all streams 970 # . clear-stream(_test-stream) 971 # . . push args 972 68/push _test-stream/imm32 973 # . . call 974 e8/call clear-stream/disp32 975 # . . discard args 976 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 977 # . clear-stream($_test-buffered-file->buffer) 978 # . . push args 979 b8/copy-to-eax _test-buffered-file/imm32 980 05/add-to-eax 4/imm32 981 50/push-eax 982 # . . call 983 e8/call clear-stream/disp32 984 # . . discard args 985 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 986 # . clear-stream(_test-error-stream) 987 # . . push args 988 68/push _test-error-stream/imm32 989 # . . call 990 e8/call clear-stream/disp32 991 # . . discard args 992 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 993 # . clear-stream($_test-error-buffered-file->buffer) 994 # . . push args 995 68/push $_test-error-buffered-file->buffer/imm32 996 # . . call 997 e8/call clear-stream/disp32 998 # . . discard args 999 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1000 # initialize '_test-stream' to input with leading whitespace and comment 1001 # . write(_test-stream, comment) 1002 # . . push args 1003 68/push " #x\n"/imm32 1004 68/push _test-stream/imm32 1005 # . . call 1006 e8/call write/disp32 1007 # . . discard args 1008 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1009 # . write(_test-stream, real text) 1010 # . . push args 1011 68/push "ab"/imm32 1012 68/push _test-stream/imm32 1013 # . . call 1014 e8/call write/disp32 1015 # . . discard args 1016 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1017 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below 1018 # . var ed/ecx: exit-descriptor 1019 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 1020 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 1021 # . tailor-exit-descriptor(ed, 12) 1022 # . . push args 1023 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte 1024 51/push-ecx/ed 1025 # . . call 1026 e8/call tailor-exit-descriptor/disp32 1027 # . . discard args 1028 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1029 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 1030 # . . push args 1031 51/push-ecx/ed 1032 68/push _test-error-buffered-file/imm32 1033 68/push _test-buffered-file/imm32 1034 # . . call 1035 e8/call scan-next-byte/disp32 1036 # registers except esp may be clobbered at this point 1037 # pop args to scan-next-byte 1038 # . . discard first 2 args 1039 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1040 # . . restore ed 1041 59/pop-to-ecx 1042 # check that scan-next-byte didn't abort 1043 # . check-ints-equal(ed->value, 0, msg) 1044 # . . push args 1045 68/push "F - test-scan-next-byte-skips-whitespace-and-comment: unexpected abort"/imm32 1046 68/push 0/imm32 1047 # . . push ed->value 1048 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 1049 # . . call 1050 e8/call check-ints-equal/disp32 1051 # . . discard args 1052 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1053 # return if abort 1054 81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4) 1055 75/jump-if-!= $test-scan-next-byte-skips-whitespace-and-comment:end/disp8 1056 # check-ints-equal(eax, 0x61/a, msg) 1057 # . . push args 1058 68/push "F - test-scan-next-byte-skips-whitespace-and-comment"/imm32 1059 68/push 0x61/imm32/a 1060 50/push-eax 1061 # . . call 1062 e8/call check-ints-equal/disp32 1063 # . . discard args 1064 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1065 $test-scan-next-byte-skips-whitespace-and-comment:end: 1066 # . epilogue 1067 # don't restore esp from ebp; manually reclaim locals 1068 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1069 5d/pop-to-ebp 1070 c3/return 1071 1072 test-scan-next-byte-reads-final-byte: 1073 # - check that the final byte in input is returned 1074 # This test uses exit-descriptors. Use ebp for setting up local variables. 1075 55/push-ebp 1076 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1077 # clear all streams 1078 # . clear-stream(_test-stream) 1079 # . . push args 1080 68/push _test-stream/imm32 1081 # . . call 1082 e8/call clear-stream/disp32 1083 # . . discard args 1084 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1085 # . clear-stream($_test-buffered-file->buffer) 1086 # . . push args 1087 68/push $_test-buffered-file->buffer/imm32 1088 # . . call 1089 e8/call clear-stream/disp32 1090 # . . discard args 1091 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1092 # . clear-stream(_test-error-stream) 1093 # . . push args 1094 68/push _test-error-stream/imm32 1095 # . . call 1096 e8/call clear-stream/disp32 1097 # . . discard args 1098 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1099 # . clear-stream($_test-error-buffered-file->buffer) 1100 # . . push args 1101 68/push $_test-error-buffered-file->buffer/imm32 1102 # . . call 1103 e8/call clear-stream/disp32 1104 # . . discard args 1105 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1106 # initialize '_test-stream' to input with single character 1107 # . write(_test-stream, character) 1108 # . . push args 1109 68/push "a"/imm32 1110 68/push _test-stream/imm32 1111 # . . call 1112 e8/call write/disp32 1113 # . . discard args 1114 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1115 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below 1116 # . var ed/ecx: exit-descriptor 1117 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 1118 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 1119 # . tailor-exit-descriptor(ed, 12) 1120 # . . push args 1121 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte 1122 51/push-ecx/ed 1123 # . . call 1124 e8/call tailor-exit-descriptor/disp32 1125 # . . discard args 1126 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1127 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 1128 # . . push args 1129 51/push-ecx/ed 1130 68/push _test-error-buffered-file/imm32 1131 68/push _test-buffered-file/imm32 1132 # . . call 1133 e8/call scan-next-byte/disp32 1134 # registers except esp may be clobbered at this point 1135 # pop args to scan-next-byte 1136 # . . discard first 2 args 1137 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1138 # . . restore ed 1139 59/pop-to-ecx 1140 # check that scan-next-byte didn't abort 1141 # . check-ints-equal(ed->value, 0, msg) 1142 # . . push args 1143 68/push "F - test-scan-next-byte-reads-final-byte: unexpected abort"/imm32 1144 68/push 0/imm32 1145 # . . push ed->value 1146 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 1147 # . . call 1148 e8/call check-ints-equal/disp32 1149 # . . discard args 1150 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1151 # return if abort 1152 81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4) 1153 75/jump-if-!= $test-scan-next-byte-reads-final-byte:end/disp8 1154 # check-ints-equal(eax, 0x61/a, msg) 1155 # . . push args 1156 68/push "F - test-scan-next-byte-reads-final-byte"/imm32 1157 68/push 0x61/imm32/a 1158 50/push-eax 1159 # . . call 1160 e8/call check-ints-equal/disp32 1161 # . . discard args 1162 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1163 $test-scan-next-byte-reads-final-byte:end: 1164 # . epilogue 1165 # don't restore esp from ebp; manually reclaim locals 1166 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1167 5d/pop-to-ebp 1168 c3/return 1169 1170 test-scan-next-byte-handles-Eof: 1171 # - check that the right sentinel value is returned when there's no data remaining to be read 1172 # This test uses exit-descriptors. Use ebp for setting up local variables. 1173 55/push-ebp 1174 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1175 # clear all streams 1176 # . clear-stream(_test-stream) 1177 # . . push args 1178 68/push _test-stream/imm32 1179 # . . call 1180 e8/call clear-stream/disp32 1181 # . . discard args 1182 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1183 # . clear-stream($_test-buffered-file->buffer) 1184 # . . push args 1185 68/push $_test-buffered-file->buffer/imm32 1186 # . . call 1187 e8/call clear-stream/disp32 1188 # . . discard args 1189 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1190 # . clear-stream(_test-error-stream) 1191 # . . push args 1192 68/push _test-error-stream/imm32 1193 # . . call 1194 e8/call clear-stream/disp32 1195 # . . discard args 1196 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1197 # . clear-stream($_test-error-buffered-file->buffer) 1198 # . . push args 1199 68/push $_test-error-buffered-file->buffer/imm32 1200 # . . call 1201 e8/call clear-stream/disp32 1202 # . . discard args 1203 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1204 # leave '_test-stream' empty 1205 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below 1206 # . var ed/ecx: exit-descriptor 1207 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 1208 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 1209 # . tailor-exit-descriptor(ed, 12) 1210 # . . push args 1211 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte 1212 51/push-ecx/ed 1213 # . . call 1214 e8/call tailor-exit-descriptor/disp32 1215 # . . discard args 1216 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1217 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 1218 # . . push args 1219 51/push-ecx/ed 1220 68/push _test-error-buffered-file/imm32 1221 68/push _test-buffered-file/imm32 1222 # . . call 1223 e8/call scan-next-byte/disp32 1224 # registers except esp may be clobbered at this point 1225 # pop args to scan-next-byte 1226 # . . discard first 2 args 1227 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1228 # . . restore ed 1229 59/pop-to-ecx 1230 # check that scan-next-byte didn't abort 1231 # . check-ints-equal(ed->value, 0, msg) 1232 # . . push args 1233 68/push "F - test-scan-next-byte-handles-Eof: unexpected abort"/imm32 1234 68/push 0/imm32 1235 # . . push ed->value 1236 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 1237 # . . call 1238 e8/call check-ints-equal/disp32 1239 # . . discard args 1240 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1241 # return if abort 1242 81 7/subop/compare 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 0/imm32 # compare *(ecx+4) 1243 75/jump-if-!= $test-scan-next-byte-handles-Eof:end/disp8 1244 # check-ints-equal(eax, Eof, msg) 1245 # . . push args 1246 68/push "F - test-scan-next-byte-handles-Eof"/imm32 1247 68/push 0xffffffff/imm32/Eof 1248 50/push-eax 1249 # . . call 1250 e8/call check-ints-equal/disp32 1251 # . . discard args 1252 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1253 $test-scan-next-byte-handles-Eof:end: 1254 # . epilogue 1255 # don't restore esp from ebp; manually reclaim locals 1256 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1257 5d/pop-to-ebp 1258 c3/return 1259 1260 test-scan-next-byte-aborts-on-invalid-byte: 1261 # - check that the a bad byte immediately aborts 1262 # This test uses exit-descriptors. Use ebp for setting up local variables. 1263 55/push-ebp 1264 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1265 # clear all streams 1266 # . clear-stream(_test-stream) 1267 # . . push args 1268 68/push _test-stream/imm32 1269 # . . call 1270 e8/call clear-stream/disp32 1271 # . . discard args 1272 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1273 # . clear-stream($_test-buffered-file->buffer) 1274 # . . push args 1275 68/push $_test-buffered-file->buffer/imm32 1276 # . . call 1277 e8/call clear-stream/disp32 1278 # . . discard args 1279 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1280 # . clear-stream(_test-error-stream) 1281 # . . push args 1282 68/push _test-error-stream/imm32 1283 # . . call 1284 e8/call clear-stream/disp32 1285 # . . discard args 1286 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1287 # . clear-stream($_test-error-buffered-file->buffer) 1288 # . . push args 1289 68/push $_test-error-buffered-file->buffer/imm32 1290 # . . call 1291 e8/call clear-stream/disp32 1292 # . . discard args 1293 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1294 # initialize '_test-stream' to "x" 1295 # . write(_test-stream, "x") 1296 # . . push args 1297 68/push "x"/imm32 1298 68/push _test-stream/imm32 1299 # . . call 1300 e8/call write/disp32 1301 # . . discard args 1302 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1303 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below 1304 # . var ed/ecx: exit-descriptor 1305 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # subtract from esp 1306 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 1307 # . tailor-exit-descriptor(ed, 12) 1308 # . . push args 1309 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte 1310 51/push-ecx/ed 1311 # . . call 1312 e8/call tailor-exit-descriptor/disp32 1313 # . . discard args 1314 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1315 # eax = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 1316 # . . push args 1317 51/push-ecx/ed 1318 68/push _test-error-buffered-file/imm32 1319 68/push _test-buffered-file/imm32 1320 # . . call 1321 e8/call scan-next-byte/disp32 1322 # registers except esp may be clobbered at this point 1323 # pop args to scan-next-byte 1324 # . . discard first 2 args 1325 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1326 # . . restore ed 1327 59/pop-to-ecx 1328 # check that scan-next-byte aborted 1329 # . check-ints-equal(ed->value, 2, msg) 1330 # . . push args 1331 68/push "F - test-scan-next-byte-aborts-on-invalid-byte"/imm32 1332 68/push 2/imm32 1333 # . . push ed->value 1334 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 1335 # . . call 1336 e8/call check-ints-equal/disp32 1337 # . . discard args 1338 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1339 $test-scan-next-byte-aborts-on-invalid-byte:end: 1340 # . epilogue 1341 # don't restore esp from ebp; manually reclaim locals 1342 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1343 5d/pop-to-ebp 1344 c3/return 1345 1346 skip-until-newline: # in: (addr buffered-file) 1347 # pseudocode: 1348 # push eax 1349 # while true 1350 # eax = read-byte-buffered(in) 1351 # if (eax == Eof) break 1352 # if (eax == 0x0a) break 1353 # pop eax 1354 # . prologue 1355 55/push-ebp 1356 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1357 # . save registers 1358 50/push-eax 1359 $skip-until-newline:loop: 1360 # . eax = read-byte-buffered(in) 1361 # . . push args 1362 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1363 # . . call 1364 e8/call read-byte-buffered/disp32 1365 # . . discard args 1366 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1367 # . if (eax == Eof) break 1368 3d/compare-eax-and 0xffffffff/imm32/Eof 1369 74/jump-if-= $skip-until-newline:end/disp8 1370 # . if (eax != 0xa/newline) loop 1371 3d/compare-eax-and 0xa/imm32/newline 1372 75/jump-if-!= $skip-until-newline:loop/disp8 1373 $skip-until-newline:end: 1374 # . restore registers 1375 58/pop-to-eax 1376 # . epilogue 1377 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1378 5d/pop-to-ebp 1379 c3/return 1380 1381 test-skip-until-newline: 1382 # - check that the read pointer points after the newline 1383 # setup 1384 # . clear-stream(_test-stream) 1385 # . . push args 1386 68/push _test-stream/imm32 1387 # . . call 1388 e8/call clear-stream/disp32 1389 # . . discard args 1390 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1391 # . clear-stream($_test-buffered-file->buffer) 1392 # . . push args 1393 68/push $_test-buffered-file->buffer/imm32 1394 # . . call 1395 e8/call clear-stream/disp32 1396 # . . discard args 1397 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1398 # initialize '_test-stream' to "abc\nde" 1399 # . write(_test-stream, "abc") 1400 # . . push args 1401 68/push "abc\n"/imm32 1402 68/push _test-stream/imm32 1403 # . . call 1404 e8/call write/disp32 1405 # . . discard args 1406 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1407 # . write(_test-stream, "de") 1408 # . . push args 1409 68/push "de"/imm32 1410 68/push _test-stream/imm32 1411 # . . call 1412 e8/call write/disp32 1413 # . . discard args 1414 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1415 # skip-until-newline(_test-buffered-file) 1416 # . . push args 1417 68/push _test-buffered-file/imm32 1418 # . . call 1419 e8/call skip-until-newline/disp32 1420 # . . discard args 1421 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1422 # check-ints-equal(_test-buffered-file->read, 4, msg) 1423 # . . push args 1424 68/push "F - test-skip-until-newline"/imm32 1425 68/push 4/imm32 1426 b8/copy-to-eax _test-buffered-file/imm32 1427 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 8/disp8 . # push *(eax+8) 1428 # . . call 1429 e8/call check-ints-equal/disp32 1430 # . . discard args 1431 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1432 # . end 1433 c3/return 1434 1435 # . . vim:nowrap:textwidth=0