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