https://github.com/akkartik/mu/blob/master/apps/pack.subx
   1 # Read a text file of SubX instructions from stdin, and convert it into a list
   2 # of whitespace-separated ascii hex bytes on stdout. Label definitions and
   3 # uses are left untouched.
   4 #
   5 # To run:
   6 #   $ ./bootstrap translate init.linux 0*.subx apps/subx-params.subx apps/pack.subx  -o apps/pack
   7 #   $ echo '05/add-to-eax 0x20/imm32'  |./bootstrap run apps/pack
   8 # Expected output:
   9 #   05 20 00 00 00  # 05/add-to-eax 0x20/imm32
  10 # The original instruction gets included as a comment at the end of each
  11 # converted line.
  12 #
  13 # There's zero error-checking. For now we assume the input program is valid.
  14 # We'll continue to rely on the C++ version for error messages.
  15 
  16 == code
  17 #   instruction                     effective address                                                   register    displacement    immediate
  18 # . op          subop               mod             rm32          base        index         scale       r32
  19 # . 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
  20 
  21 Entry:  # run tests if necessary, convert stdin if not
  22     # . prologue
  23     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
  24 
  25     # initialize heap
  26     # . Heap = new-segment(Heap-size)
  27     # . . push args
  28     68/push  Heap/imm32
  29     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Heap-size/disp32                  # push *Heap-size
  30     # . . call
  31     e8/call  new-segment/disp32
  32     # . . discard args
  33     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
  34 
  35     # - if argc > 1 and argv[1] == "test", then return run_tests()
  36     # if (argc <= 1) goto interactive
  37     81          7/subop/compare     1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0/disp8         1/imm32           # compare *ebp
  38     7e/jump-if-<=  $subx-pack-main:interactive/disp8
  39     # if (!kernel-string-equal?(argv[1], "test")) goto interactive
  40     # . eax = kernel-string-equal?(argv[1], "test")
  41     # . . push args
  42     68/push  "test"/imm32
  43     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .          
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: module ranger.gui.widgets.pager</title>
</head><body bgcolor="#f0f0f8">

<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial">&nbsp;<br><big><big><strong><a href="ranger.html"><font color="#ffffff">ranger</font></a>.<a href="ranger.gui.html"><font color="#ffffff">gui</font></a>.<a href="ranger.gui.widgets.html"><font color="#ffffff">widgets</font></a>.pager</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/hut/ranger/ranger/gui/widgets/pager.py">/home/hut/ranger/ranger/gui/widgets/pager.py</a></font></td></tr></table>
    <p><tt>The&nbsp;pager&nbsp;displays&nbsp;text&nbsp;and&nbsp;allows&nbsp;you&nbsp;to&nbsp;scroll&nbsp;inside&nbsp;it.</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr>
    
<tr><td bgcolor="#aa55cc"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="re.html">re</a><br>
</td><td width="25%" valign=top></td><td width="25%" valign=top></td><td width="25%" valign=top></td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ee77aa">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr>
    
<tr><td bgcolor="#ee77aa"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl>
<dt><font face="helvetica, arial"><a href="ranger.gui.widgets.html#Widget">ranger.gui.widgets.Widget</a>(<a href="ranger.gui.displayable.html#Displayable">ranger.gui.displayable.Displayable</a>)
</font></dt><dd>
<dl>
<dt><font face="helvetica, arial"><a href="ranger.gui.widgets.pager.html#Pager">Pager</a>
</font></dt></dl>
</dd>
</dl>
 <p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#ffc8d8">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#000000" face="helvetica, arial"><a name="Pager">class <strong>Pager</strong></a>(<a href="ranger.gui.widgets.html#Widget">ranger.gui.widgets.Widget</a>)</font></td></tr>
    
<tr><td bgcolor="#ffc8d8"><tt>&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><dl><dt>Method resolution order:</dt>
<dd><a href="ranger.gui.widgets.pager.html#Pager">Pager</a></dd>
<dd><a href="ranger.gui.widgets.html#Widget">ranger.gui.widgets.Widget</a></dd>
<dd><a href="ranger.gui.displayable.html#Displayable">ranger.gui.displayable.Displayable</a></dd>
<dd><a href="ranger.shared.html#EnvironmentAware">ranger.shared.EnvironmentAware</a></dd>
<dd><a href="ranger.shared.html#FileManagerAware">ranger.shared.FileManagerAware</a></dd>
<dd><a href="ranger.shared.html#Awareness">ranger.shared.Awareness</a></dd>
<dd><a href="ranger.gui.curses_shortcuts.html#CursesShortcuts">ranger.gui.curses_shortcuts.CursesShortcuts</a></dd>
<dd><a href="ranger.shared.settings.html#SettingsAware">ranger.shared.settings.SettingsAware</a></dd>
<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
</dl>
<hr>
Methods defined here:<br>
<dl><dt><a name="Pager-__init__"><strong>__init__</strong></a>(self, win, embedded<font color="#909090">=False</font>)</dt></dl>

<dl><dt><a name="Pager-click"><strong>click</strong></a>(self, event)</dt></dl>

<dl><dt><a name="Pager-close"><strong>close</strong></a>(self)</dt></dl>

<dl><dt><a name="Pager-draw"><strong>draw</strong></a>(self)</dt></dl>

<dl><dt><a name="Pager-finalize"><strong>finalize</strong></a>(self)</dt></dl>

<dl><dt><a name="Pager-move"><strong>move</strong></a>(self, narg<font color="#909090">=None</font>, **kw)</dt></dl>

<dl><dt><a name="Pager-open"><strong>open</strong></a>(self)</dt></dl>

<dl><dt><a name="Pager-press"><strong>press</strong></a>(self, key)</dt></dl>

<dl><dt><a name="Pager-set_source"><strong>set_source</strong></a>(self, source, strip<font color="#909090">=False</font>)</dt></dl>

<hr>
Data and other attributes defined here:<br>
<dl><dt><strong>old_scroll_begin</strong> = 0</dl>

<dl><dt><strong>old_source</strong> = None</dl>

<dl><dt><strong>old_startx</strong> = 0</dl>

<dl><dt><strong>source</strong> = None</dl>

<dl><dt><strong>source_is_stream</strong> = False</dl>

<hr>
Methods inherited from <a href="ranger.gui.displayable.html#Displayable">ranger.gui.displayable.Displayable</a>:<br>
<dl><dt><a name="Pager-__bool__"><strong>__bool__</strong></a> = __nonzero__(self)</dt><dd><tt>Always&nbsp;True</tt></dd></dl>

<dl><dt><a name="Pager-__contains__"><strong>__contains__</strong></a>(self, item)</dt><dd><tt>Is&nbsp;item&nbsp;inside&nbsp;the&nbsp;boundaries?<br>
item&nbsp;can&nbsp;be&nbsp;an&nbsp;iterable&nbsp;like&nbsp;[y,&nbsp;x]&nbsp;or&nbsp;an&nbsp;object&nbsp;with&nbsp;x&nbsp;and&nbsp;y&nbsp;methods.</tt></dd></dl>

<dl><dt><a name="Pager-__nonzero__"><strong>__nonzero__</strong></a>(self)</dt><dd><tt>Always&nbsp;True</tt></dd></dl>

<dl><dt><a name="Pager-__str__"><strong>__str__</strong></a>(self)</dt></dl>

<dl><dt><a name="Pager-contains_point"><strong>contains_point</strong></a>(self, y, x)</dt><dd><tt>Test&nbsp;whether&nbsp;the&nbsp;point&nbsp;(with&nbsp;absolute&nbsp;coordinates)&nbsp;lies<br>
within&nbsp;the&nbsp;boundaries&nbsp;of&nbsp;this&nbsp;object.</tt></dd></dl>

<dl><dt><a name="Pager-destroy"><strong>destroy</strong></a>(self)</dt><dd><tt>Called&nbsp;when&nbsp;the&nbsp;object&nbsp;is&nbsp;destroyed.<br>
Override&nbsp;this!</tt></dd></dl>

<dl><dt><a name="Pager-poke"><strong>poke</strong></a>(self)</dt><dd><tt>Called&nbsp;before&nbsp;drawing,&nbsp;even&nbsp;if&nbsp;invisible</tt></dd></dl>

<dl><dt><a name="Pager-resize"><strong>resize</strong></a>(self, y, x, hei<font color="#909090">=None</font>, wid<font color="#909090">=None</font>)</dt><dd><tt>Resize&nbsp;the&nbsp;widget</tt></dd></dl>

<hr>
Data and other attributes inherited from <a href="ranger.shared.html#EnvironmentAware">ranger.shared.EnvironmentAware</a>:<br>
<dl><dt><strong>env</strong> = None</dl>

<hr>
Data and other attributes inherited from <a href="ranger.shared.html#FileManagerAware">ranger.shared.FileManagerAware</a>:<br>
<dl><dt><strong>fm</strong> = None</dl>

<hr>
Data descriptors inherited from <a href="ranger.shared.html#Awareness">ranger.shared.Awareness</a>:<br>
<dl><dt><strong>__dict__</strong></dt>
<dd><tt>dictionary&nbsp;for&nbsp;instance&nbsp;variables&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<dl><dt><strong>__weakref__</strong></dt>
<dd><tt>list&nbsp;of&nbsp;weak&nbsp;references&nbsp;to&nbsp;the&nbsp;object&nbsp;(if&nbsp;defined)</tt></dd>
</dl>
<hr>
Methods inherited from <a href="ranger.gui.curses_shortcuts.html#CursesShortcuts">ranger.gui.curses_shortcuts.CursesShortcuts</a>:<br>
<dl><dt><a name="Pager-addnstr"><strong>addnstr</strong></a>(self, *args)</dt></dl>

<dl><dt><a name="Pager-addstr"><strong>addstr</strong></a>(self, *args)</dt></dl>

<dl><dt><a name="Pager-color"><strong>color</strong></a>(self, *keys)</dt><dd><tt>Change&nbsp;the&nbsp;colors&nbsp;from&nbsp;now&nbsp;on.</tt></dd></dl>

<dl><dt><a name="Pager-color_at"><strong>color_at</strong></a>(self, y, x, wid, *keys)</dt><dd><tt>Change&nbsp;the&nbsp;colors&nbsp;at&nbsp;the&nbsp;specified&nbsp;position</tt></dd></dl>

<dl><dt><a name="Pager-color_reset"><strong>color_reset</strong></a>(self)</dt><dd><tt>Change&nbsp;the&nbsp;colors&nbsp;to&nbsp;the&nbsp;default&nbsp;colors</tt></dd></dl>

<hr>
Data and other attributes inherited from <a href="ranger.shared.settings.html#SettingsAware">ranger.shared.settings.SettingsAware</a>:<br>
<dl><dt><strong>settings</strong> = {}</dl>

</td></tr></table></td></tr></table><p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#55aa55">
<td colspan=3 valign=bottom>&nbsp;<br>
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
    
<tr><td bgcolor="#55aa55"><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt></td><td>&nbsp;</td>
<td width="100%"><strong>BAR_REGEXP</strong> = &lt;_sre.SRE_Pattern object&gt;<br>
<strong>QUOTES_REGEXP</strong> = &lt;_sre.SRE_Pattern object&gt;<br>
<strong>SPECIAL_CHARS_REGEXP</strong> = &lt;_sre.SRE_Pattern object&gt;<br>
<strong>TITLE_REGEXP</strong> = &lt;_sre.SRE_Pattern object&gt;</td></tr></table>
</body></html>
LineNr"> 589 590 test-subx-pack-in-data-segment: 591 # correctly process lines in the data segment 592 # . prologue 593 55/push-ebp 594 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 595 # setup 596 # . clear-stream(_test-input-stream) 597 # . . push args 598 68/push _test-input-stream/imm32 599 # . . call 600 e8/call clear-stream/disp32 601 # . . discard args 602 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 603 # . clear-stream($_test-input-buffered-file->buffer) 604 # . . push args 605 68/push $_test-input-buffered-file->buffer/imm32 606 # . . call 607 e8/call clear-stream/disp32 608 # . . discard args 609 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 610 # . clear-stream(_test-output-stream) 611 # . . push args 612 68/push _test-output-stream/imm32 613 # . . call 614 e8/call clear-stream/disp32 615 # . . discard args 616 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 617 # . clear-stream($_test-output-buffered-file->buffer) 618 # . . push args 619 68/push $_test-output-buffered-file->buffer/imm32 620 # . . call 621 e8/call clear-stream/disp32 622 # . . discard args 623 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 624 # initialize input 625 # == code 0x1 626 # == data 0x2 627 # 3 4/imm32 628 # . write(_test-input-stream, "== code 0x1") 629 # . . push args 630 68/push "== code 0x1\n"/imm32 631 68/push _test-input-stream/imm32 632 # . . call 633 e8/call write/disp32 634 # . . discard args 635 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 636 # . write(_test-input-stream, "== data 0x2\n") 637 # . . push args 638 68/push "== data 0x2\n"/imm32 639 68/push _test-input-stream/imm32 640 # . . call 641 e8/call write/disp32 642 # . . discard args 643 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 644 # . write(_test-input-stream, "3 4/imm32\n") 645 # . . push args 646 68/push "3 4/imm32\n"/imm32 647 68/push _test-input-stream/imm32 648 # . . call 649 e8/call write/disp32 650 # . . discard args 651 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 652 # subx-pack(_test-input-buffered-file, _test-output-buffered-file) 653 # . . push args 654 68/push _test-output-buffered-file/imm32 655 68/push _test-input-buffered-file/imm32 656 # . . call 657 e8/call subx-pack/disp32 658 # . . discard args 659 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 660 # check output 661 +-- 26 lines: #? # debug print ------------------------------------------------------------------------------------------------------------------------------------------------------ 687 # . flush(_test-output-buffered-file) 688 # . . push args 689 68/push _test-output-buffered-file/imm32 690 # . . call 691 e8/call flush/disp32 692 # . . discard args 693 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 694 # . check-next-stream-line-equal(_test-output-stream, "== code 0x1", msg) 695 # . . push args 696 68/push "F - test-subx-pack-in-data-segment/0"/imm32 697 68/push "== code 0x1"/imm32 698 68/push _test-output-stream/imm32 699 # . . call 700 e8/call check-next-stream-line-equal/disp32 701 # . . discard args 702 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 703 # . check-next-stream-line-equal(_test-output-stream, "== data 0x2", msg) 704 # . . push args 705 68/push "F - test-subx-pack-in-data-segment/1"/imm32 706 68/push "== data 0x2"/imm32 707 68/push _test-output-stream/imm32 708 # . . call 709 e8/call check-next-stream-line-equal/disp32 710 # . . discard args 711 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 712 # . check-next-stream-line-equal(_test-output-stream, "03 04 00 00 00 ", msg) 713 # . . push args 714 68/push "F - test-subx-pack-in-data-segment/2"/imm32 715 68/push "03 04 00 00 00 "/imm32 716 68/push _test-output-stream/imm32 717 # . . call 718 e8/call check-next-stream-line-equal/disp32 719 # . . discard args 720 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 721 # . epilogue 722 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 723 5d/pop-to-ebp 724 c3/return 725 726 test-subx-pack-code-and-data-segments: 727 # correctly process lines in both code and data segments 728 # . prologue 729 55/push-ebp 730 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 731 # setup 732 # . clear-stream(_test-input-stream) 733 # . . push args 734 68/push _test-input-stream/imm32 735 # . . call 736 e8/call clear-stream/disp32 737 # . . discard args 738 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 739 # . clear-stream($_test-input-buffered-file->buffer) 740 # . . push args 741 68/push $_test-input-buffered-file->buffer/imm32 742 # . . call 743 e8/call clear-stream/disp32 744 # . . discard args 745 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 746 # . clear-stream(_test-output-stream) 747 # . . push args 748 68/push _test-output-stream/imm32 749 # . . call 750 e8/call clear-stream/disp32 751 # . . discard args 752 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 753 # . clear-stream($_test-output-buffered-file->buffer) 754 # . . push args 755 68/push $_test-output-buffered-file->buffer/imm32 756 # . . call 757 e8/call clear-stream/disp32 758 # . . discard args 759 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 760 # initialize input 761 # == code 0x1 762 # e8/call 20/disp32 763 # 68/push 0x20/imm8 764 # == data 0x2 765 # 3 4/imm32 766 # . write(_test-input-stream, "== code 0x1\n") 767 # . . push args 768 68/push "== code 0x1\n"/imm32 769 68/push _test-input-stream/imm32 770 # . . call 771 e8/call write/disp32 772 # . . discard args 773 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 774 # . write(_test-input-stream, "e8/call 20/disp32\n") 775 # . . push args 776 68/push "e8/call 20/disp32\n"/imm32 777 68/push _test-input-stream/imm32 778 # . . call 779 e8/call write/disp32 780 # . . discard args 781 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 782 # . write(_test-input-stream, "68/push 0x20/imm8\n") 783 # . . push args 784 68/push "68/push 0x20/imm8\n"/imm32 785 68/push _test-input-stream/imm32 786 # . . call 787 e8/call write/disp32 788 # . . discard args 789 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 790 # . write(_test-input-stream, "== data 0x2\n") 791 # . . push args 792 68/push "== data 0x2\n"/imm32 793 68/push _test-input-stream/imm32 794 # . . call 795 e8/call write/disp32 796 # . . discard args 797 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 798 # . write(_test-input-stream, "3 4/imm32\n") 799 # . . push args 800 68/push "3 4/imm32\n"/imm32 801 68/push _test-input-stream/imm32 802 # . . call 803 e8/call write/disp32 804 # . . discard args 805 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 806 # subx-pack(_test-input-buffered-file, _test-output-buffered-file) 807 # . . push args 808 68/push _test-output-buffered-file/imm32 809 68/push _test-input-buffered-file/imm32 810 # . . call 811 e8/call subx-pack/disp32 812 # . . discard args 813 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 814 # check output 815 # == code 0x1 816 # e8 20 00 00 00 # e8/call 20/disp32 817 # 68 20 # 68/push 0x20/imm8 818 # == data 0x2 819 # 03 04 00 00 00 820 +-- 26 lines: #? # debug print ------------------------------------------------------------------------------------------------------------------------------------------------------ 846 # . flush(_test-output-buffered-file) 847 # . . push args 848 68/push _test-output-buffered-file/imm32 849 # . . call 850 e8/call flush/disp32 851 # . . discard args 852 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 853 # . check-next-stream-line-equal(_test-output-stream, "== code 0x1", msg) 854 # . . push args 855 68/push "F - test-subx-pack-code-and-data-segments/0"/imm32 856 68/push "== code 0x1"/imm32 857 68/push _test-output-stream/imm32 858 # . . call 859 e8/call check-next-stream-line-equal/disp32 860 # . . discard args 861 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 862 # . check-next-stream-line-equal(_test-output-stream, "e8 20 00 00 00 # e8/call 20/disp32", msg) 863 # . . push args 864 68/push "F - test-subx-pack-code-and-data-segments/1"/imm32 865 68/push "e8 20 00 00 00 # e8/call 20/disp32"/imm32 866 68/push _test-output-stream/imm32 867 # . . call 868 e8/call check-next-stream-line-equal/disp32 869 # . . discard args 870 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 871 # . check-next-stream-line-equal(_test-output-stream, "68 20 # 68/push 0x20/imm8", msg) 872 # . . push args 873 68/push "F - test-subx-pack-code-and-data-segments/2"/imm32 874 68/push "68 20 # 68/push 0x20/imm8"/imm32 875 68/push _test-output-stream/imm32 876 # . . call 877 e8/call check-next-stream-line-equal/disp32 878 # . . discard args 879 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 880 # . check-next-stream-line-equal(_test-output-stream, "== data 0x2", msg) 881 # . . push args 882 68/push "F - test-subx-pack-code-and-data-segments/3"/imm32 883 68/push "== data 0x2"/imm32 884 68/push _test-output-stream/imm32 885 # . . call 886 e8/call check-next-stream-line-equal/disp32 887 # . . discard args 888 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 889 # . check-next-stream-line-equal(_test-output-stream, "03 04 00 00 00 ", msg) 890 # . . push args 891 68/push "F - test-subx-pack-code-and-data-segments/4"/imm32 892 68/push "03 04 00 00 00 "/imm32 893 68/push _test-output-stream/imm32 894 # . . call 895 e8/call check-next-stream-line-equal/disp32 896 # . . discard args 897 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 898 # . epilogue 899 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 900 5d/pop-to-ebp 901 c3/return 902 903 convert-data: # line: (addr stream byte), out: (addr buffered-file) 904 # pseudocode: 905 # var word-slice: slice 906 # while true 907 # word-slice = next-word(line) 908 # if slice-empty?(word-slice) # end of file (maybe including trailing whitespace) 909 # break # skip emitting some whitespace 910 # if slice-starts-with?(word-slice, "#") # comment 911 # write-slice-buffered(out, word-slice) 912 # return 913 # if slice-ends-with?(word-slice, ":") # label 914 # write-stream-data(out, line) 915 # return 916 # if has-metadata?(word-slice, "imm32") 917 # emit(out, word-slice, 4) 918 # # disp32 is not permitted in data segments, and anything else is only a byte long 919 # else 920 # emit(out, word-slice, 1) 921 # write-buffered(out, "\n") 922 # 923 # . prologue 924 55/push-ebp 925 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 926 # . save registers 927 50/push-eax 928 51/push-ecx 929 52/push-edx 930 # var word-slice/ecx: slice 931 68/push 0/imm32/end 932 68/push 0/imm32/start 933 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 934 +-- 26 lines: #? # dump line -------------------------------------------------------------------------------------------------------------------------------------------------------- 960 $convert-data:loop: 961 # next-word(line, word-slice) 962 # . . push args 963 51/push-ecx 964 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 965 # . . call 966 e8/call next-word/disp32 967 # . . discard args 968 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 969 +-- 40 lines: #? # dump word-slice -------------------------------------------------------------------------------------------------------------------------------------------------- 1009 $convert-data:check0: 1010 # if (slice-empty?(word-slice)) break 1011 # . eax = slice-empty?(word-slice) 1012 # . . push args 1013 51/push-ecx 1014 # . . call 1015 e8/call slice-empty?/disp32 1016 # . . discard args 1017 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1018 # . if (eax != false) break 1019 3d/compare-eax-and 0/imm32/false 1020 0f 85/jump-if-!= $convert-data:break/disp32 1021 $convert-data:check-for-comment: 1022 # if (slice-starts-with?(word-slice, "#")) 1023 # . var start/edx: (addr byte) = word-slice->start 1024 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx 1025 # . var c/eax: byte = *start 1026 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 1027 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL 1028 # . if (c != '#') goto next check 1029 3d/compare-eax-and 0x23/imm32/hash 1030 75/jump-if-!= $convert-data:check-for-label/disp8 1031 $convert-data:comment: 1032 # write-slice-buffered(out, word-slice) 1033 # . . push args 1034 51/push-ecx 1035 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1036 # . . call 1037 e8/call write-slice-buffered/disp32 1038 # . . discard args 1039 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1040 # return 1041 0f 85/jump-if-!= $convert-data:end/disp32 1042 $convert-data:check-for-label: 1043 # if (slice-ends-with?(word-slice, ":")) 1044 # . var end/edx: (addr byte) = word-slice->end 1045 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx 1046 # . var c/eax: byte = *(end-1) 1047 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 1048 8a/copy-byte 1/mod/*+disp8 2/rm32/edx . . . 0/r32/AL -1/disp8 . # copy byte at *ecx to AL 1049 # . if (c != ':') goto next check 1050 3d/compare-eax-and 0x3a/imm32/colon 1051 75/jump-if-!= $convert-data:check-for-imm32/disp8 1052 $convert-data:label: 1053 # write-stream-data(out, line) 1054 # . . push args 1055 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1056 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1057 # . . call 1058 e8/call write-stream-data/disp32 1059 # . . discard args 1060 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1061 # return 1062 75/jump-if-!= $convert-data:end/disp8 1063 $convert-data:check-for-imm32: 1064 # if (has-metadata?(word-slice, "imm32")) 1065 # . eax = has-metadata?(ecx, "imm32") 1066 # . . push args 1067 68/push "imm32"/imm32 1068 51/push-ecx 1069 # . . call 1070 e8/call has-metadata?/disp32 1071 # . . discard args 1072 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1073 # . if (eax == false) process as a single byte 1074 3d/compare-eax-and 0/imm32/false 1075 74/jump-if-= $convert-data:single-byte/disp8 1076 $convert-data:imm32: 1077 # emit(out, word-slice, 4) 1078 # . . push args 1079 68/push 4/imm32 1080 51/push-ecx 1081 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1082 # . . call 1083 e8/call emit/disp32 1084 # . . discard args 1085 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1086 e9/jump $convert-data:loop/disp32 1087 $convert-data:single-byte: 1088 # emit(out, word-slice, 1) 1089 # . . push args 1090 68/push 1/imm32 1091 51/push-ecx 1092 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1093 # . . call 1094 e8/call emit/disp32 1095 # . . discard args 1096 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1097 e9/jump $convert-data:loop/disp32 1098 $convert-data:break: 1099 # write-buffered(out, "\n") 1100 # . . push args 1101 68/push Newline/imm32 1102 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1103 # . . call 1104 e8/call write-buffered/disp32 1105 # . . discard args 1106 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1107 $convert-data:end: 1108 # . reclaim locals 1109 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1110 # . restore registers 1111 5a/pop-to-edx 1112 59/pop-to-ecx 1113 58/pop-to-eax 1114 # . epilogue 1115 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1116 5d/pop-to-ebp 1117 c3/return 1118 1119 test-convert-data-passes-comments-through: 1120 # if a line starts with '#', pass it along unchanged 1121 # . prologue 1122 55/push-ebp 1123 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1124 # setup 1125 # . clear-stream(_test-input-stream) 1126 # . . push args 1127 68/push _test-input-stream/imm32 1128 # . . call 1129 e8/call clear-stream/disp32 1130 # . . discard args 1131 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1132 # . clear-stream(_test-output-stream) 1133 # . . push args 1134 68/push _test-output-stream/imm32 1135 # . . call 1136 e8/call clear-stream/disp32 1137 # . . discard args 1138 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1139 # . clear-stream($_test-output-buffered-file->buffer) 1140 # . . push args 1141 68/push $_test-output-buffered-file->buffer/imm32 1142 # . . call 1143 e8/call clear-stream/disp32 1144 # . . discard args 1145 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1146 # initialize input 1147 # . write(_test-input-stream, "# abcd") 1148 # . . push args 1149 68/push "# abcd"/imm32 1150 68/push _test-input-stream/imm32 1151 # . . call 1152 e8/call write/disp32 1153 # . . discard args 1154 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1155 # convert-data(_test-input-stream, _test-output-buffered-file) 1156 # . . push args 1157 68/push _test-output-buffered-file/imm32 1158 68/push _test-input-stream/imm32 1159 # . . call 1160 e8/call convert-data/disp32 1161 # . . discard args 1162 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1163 # check that the line just passed through 1164 # . flush(_test-output-buffered-file) 1165 # . . push args 1166 68/push _test-output-buffered-file/imm32 1167 # . . call 1168 e8/call flush/disp32 1169 # . . discard args 1170 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1171 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 1197 # . check-stream-equal(_test-output-stream, "# abcd", msg) 1198 # . . push args 1199 68/push "F - test-convert-data-passes-comments-through"/imm32 1200 68/push "# abcd"/imm32 1201 68/push _test-output-stream/imm32 1202 # . . call 1203 e8/call check-stream-equal/disp32 1204 # . . discard args 1205 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1206 # . epilogue 1207 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1208 5d/pop-to-ebp 1209 c3/return 1210 1211 test-convert-data-passes-labels-through: 1212 # if the first word ends with ':', pass along the entire line unchanged 1213 # . prologue 1214 55/push-ebp 1215 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1216 # setup 1217 # . clear-stream(_test-input-stream) 1218 # . . push args 1219 68/push _test-input-stream/imm32 1220 # . . call 1221 e8/call clear-stream/disp32 1222 # . . discard args 1223 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1224 # . clear-stream(_test-output-stream) 1225 # . . push args 1226 68/push _test-output-stream/imm32 1227 # . . call 1228 e8/call clear-stream/disp32 1229 # . . discard args 1230 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1231 # . clear-stream($_test-output-buffered-file->buffer) 1232 # . . push args 1233 68/push $_test-output-buffered-file->buffer/imm32 1234 # . . call 1235 e8/call clear-stream/disp32 1236 # . . discard args 1237 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1238 # initialize input 1239 # . write(_test-input-stream, "ab: # cd") 1240 # . . push args 1241 68/push "ab: # cd"/imm32 1242 68/push _test-input-stream/imm32 1243 # . . call 1244 e8/call write/disp32 1245 # . . discard args 1246 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1247 # convert-data(_test-input-stream, _test-output-buffered-file) 1248 # . . push args 1249 68/push _test-output-buffered-file/imm32 1250 68/push _test-input-stream/imm32 1251 # . . call 1252 e8/call convert-data/disp32 1253 # . . discard args 1254 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1255 # check that the line just passed through 1256 # . flush(_test-output-buffered-file) 1257 # . . push args 1258 68/push _test-output-buffered-file/imm32 1259 # . . call 1260 e8/call flush/disp32 1261 # . . discard args 1262 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1263 # . check-stream-equal(_test-output-stream, "ab: # cd", msg) 1264 # . . push args 1265 68/push "F - test-convert-data-passes-labels-through"/imm32 1266 68/push "ab: # cd"/imm32 1267 68/push _test-output-stream/imm32 1268 # . . call 1269 e8/call check-stream-equal/disp32 1270 # . . discard args 1271 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1272 # . epilogue 1273 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1274 5d/pop-to-ebp 1275 c3/return 1276 1277 test-convert-data-passes-names-through: 1278 # If a word is a valid name, just emit it unchanged. 1279 # Later phases will deal with it. 1280 # . prologue 1281 55/push-ebp 1282 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1283 # setup 1284 # . clear-stream(_test-input-stream) 1285 # . . push args 1286 68/push _test-input-stream/imm32 1287 # . . call 1288 e8/call clear-stream/disp32 1289 # . . discard args 1290 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1291 # . clear-stream(_test-output-stream) 1292 # . . push args 1293 68/push _test-output-stream/imm32 1294 # . . call 1295 e8/call clear-stream/disp32 1296 # . . discard args 1297 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1298 # . clear-stream($_test-output-buffered-file->buffer) 1299 # . . push args 1300 68/push $_test-output-buffered-file->buffer/imm32 1301 # . . call 1302 e8/call clear-stream/disp32 1303 # . . discard args 1304 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1305 # initialize input 1306 # . write(_test-input-stream, "abcd/imm32") 1307 # . . push args 1308 68/push "abcd/imm32"/imm32 1309 68/push _test-input-stream/imm32 1310 # . . call 1311 e8/call write/disp32 1312 # . . discard args 1313 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1314 # convert-data(_test-input-stream, _test-output-buffered-file) 1315 # . . push args 1316 68/push _test-output-buffered-file/imm32 1317 68/push _test-input-stream/imm32 1318 # . . call 1319 e8/call convert-data/disp32 1320 # . . discard args 1321 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1322 # check that the line just passed through 1323 # . flush(_test-output-buffered-file) 1324 # . . push args 1325 68/push _test-output-buffered-file/imm32 1326 # . . call 1327 e8/call flush/disp32 1328 # . . discard args 1329 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1330 # . check-stream-equal(_test-output-stream, "abcd/imm32 \n", msg) 1331 # . . push args 1332 68/push "F - test-convert-data-passes-names-through"/imm32 1333 68/push "abcd/imm32 \n"/imm32 1334 68/push _test-output-stream/imm32 1335 # . . call 1336 e8/call check-stream-equal/disp32 1337 # . . discard args 1338 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1339 # . epilogue 1340 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1341 5d/pop-to-ebp 1342 c3/return 1343 1344 test-convert-data-handles-imm32: 1345 # If a word has the /imm32 metadata, emit it in 4 bytes. 1346 # . prologue 1347 55/push-ebp 1348 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1349 # setup 1350 # . clear-stream(_test-input-stream) 1351 # . . push args 1352 68/push _test-input-stream/imm32 1353 # . . call 1354 e8/call clear-stream/disp32 1355 # . . discard args 1356 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1357 # . clear-stream(_test-output-stream) 1358 # . . push args 1359 68/push _test-output-stream/imm32 1360 # . . call 1361 e8/call clear-stream/disp32 1362 # . . discard args 1363 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1364 # . clear-stream($_test-output-buffered-file->buffer) 1365 # . . push args 1366 68/push $_test-output-buffered-file->buffer/imm32 1367 # . . call 1368 e8/call clear-stream/disp32 1369 # . . discard args 1370 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1371 # initialize input 1372 # . write(_test-input-stream, "30/imm32") 1373 # . . push args 1374 68/push "30/imm32"/imm32 1375 68/push _test-input-stream/imm32 1376 # . . call 1377 e8/call write/disp32 1378 # . . discard args 1379 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1380 # convert-data(_test-input-stream, _test-output-buffered-file) 1381 # . . push args 1382 68/push _test-output-buffered-file/imm32 1383 68/push _test-input-stream/imm32 1384 # . . call 1385 e8/call convert-data/disp32 1386 # . . discard args 1387 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1388 # check that 4 bytes were written 1389 # . flush(_test-output-buffered-file) 1390 # . . push args 1391 68/push _test-output-buffered-file/imm32 1392 # . . call 1393 e8/call flush/disp32 1394 # . . discard args 1395 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1396 # . check-stream-equal(_test-output-stream, "30 00 00 00 \n", msg) 1397 # . . push args 1398 68/push "F - test-convert-data-handles-imm32"/imm32 1399 68/push "30 00 00 00 \n"/imm32 1400 68/push _test-output-stream/imm32 1401 # . . call 1402 e8/call check-stream-equal/disp32 1403 # . . discard args 1404 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1405 # . epilogue 1406 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1407 5d/pop-to-ebp 1408 c3/return 1409 1410 test-convert-data-handles-single-byte: 1411 # Any metadata but /imm32 will emit a single byte. 1412 # Data segments can't have /disp32, and SubX doesn't support 16-bit operands. 1413 # . prologue 1414 55/push-ebp 1415 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1416 # setup 1417 # . clear-stream(_test-input-stream) 1418 # . . push args 1419 68/push _test-input-stream/imm32 1420 # . . call 1421 e8/call clear-stream/disp32 1422 # . . discard args 1423 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1424 # . clear-stream(_test-output-stream) 1425 # . . push args 1426 68/push _test-output-stream/imm32 1427 # . . call 1428 e8/call clear-stream/disp32 1429 # . . discard args 1430 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1431 # . clear-stream($_test-output-buffered-file->buffer) 1432 # . . push args 1433 68/push $_test-output-buffered-file->buffer/imm32 1434 # . . call 1435 e8/call clear-stream/disp32 1436 # . . discard args 1437 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1438 # initialize input 1439 # . write(_test-input-stream, "30/imm16") 1440 # . . push args 1441 68/push "30/imm16"/imm32 1442 68/push _test-input-stream/imm32 1443 # . . call 1444 e8/call write/disp32 1445 # . . discard args 1446 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1447 # convert-data(_test-input-stream, _test-output-buffered-file) 1448 # . . push args 1449 68/push _test-output-buffered-file/imm32 1450 68/push _test-input-stream/imm32 1451 # . . call 1452 e8/call convert-data/disp32 1453 # . . discard args 1454 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1455 # check that a single byte was written (imm16 is not a valid operand type) 1456 # . flush(_test-output-buffered-file) 1457 # . . push args 1458 68/push _test-output-buffered-file/imm32 1459 # . . call 1460 e8/call flush/disp32 1461 # . . discard args 1462 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1463 # . check-stream-equal(_test-output-stream, "30 \n", msg) 1464 # . . push args 1465 68/push "F - test-convert-data-handles-single-byte"/imm32 1466 68/push "30 \n"/imm32 1467 68/push _test-output-stream/imm32 1468 # . . call 1469 e8/call check-stream-equal/disp32 1470 # . . discard args 1471 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1472 # . epilogue 1473 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1474 5d/pop-to-ebp 1475 c3/return 1476 1477 test-convert-data-multiple-bytes: 1478 # Multiple single-byte words in input stream get processed one by one. 1479 # . prologue 1480 55/push-ebp 1481 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1482 # setup 1483 # . clear-stream(_test-input-stream) 1484 # . . push args 1485 68/push _test-input-stream/imm32 1486 # . . call 1487 e8/call clear-stream/disp32 1488 # . . discard args 1489 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1490 # . clear-stream(_test-output-stream) 1491 # . . push args 1492 68/push _test-output-stream/imm32 1493 # . . call 1494 e8/call clear-stream/disp32 1495 # . . discard args 1496 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1497 # . clear-stream($_test-output-buffered-file->buffer) 1498 # . . push args 1499 68/push $_test-output-buffered-file->buffer/imm32 1500 # . . call 1501 e8/call clear-stream/disp32 1502 # . . discard args 1503 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1504 # initialize input 1505 # . write(_test-input-stream, "1 2") 1506 # . . push args 1507 68/push "1 2"/imm32 1508 68/push _test-input-stream/imm32 1509 # . . call 1510 e8/call write/disp32 1511 # . . discard args 1512 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1513 # convert-data(_test-input-stream, _test-output-buffered-file) 1514 # . . push args 1515 68/push _test-output-buffered-file/imm32 1516 68/push _test-input-stream/imm32 1517 # . . call 1518 e8/call convert-data/disp32 1519 # . . discard args 1520 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1521 # check output 1522 # . flush(_test-output-buffered-file) 1523 # . . push args 1524 68/push _test-output-buffered-file/imm32 1525 # . . call 1526 e8/call flush/disp32 1527 # . . discard args 1528 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1529 # . check-stream-equal(_test-output-stream, "01 02 \n", msg) 1530 # . . push args 1531 68/push "F - test-convert-data-multiple-bytes"/imm32 1532 68/push "01 02 \n"/imm32 1533 68/push _test-output-stream/imm32 1534 # . . call 1535 e8/call check-stream-equal/disp32 1536 # . . discard args 1537 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1538 # . epilogue 1539 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1540 5d/pop-to-ebp 1541 c3/return 1542 1543 test-convert-data-byte-then-name: 1544 # Single-byte word followed by valid name get processed one by one. 1545 # . prologue 1546 55/push-ebp 1547 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1548 # setup 1549 # . clear-stream(_test-input-stream) 1550 # . . push args 1551 68/push _test-input-stream/imm32 1552 # . . call 1553 e8/call clear-stream/disp32 1554 # . . discard args 1555 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1556 # . clear-stream(_test-output-stream) 1557 # . . push args 1558 68/push _test-output-stream/imm32 1559 # . . call 1560 e8/call clear-stream/disp32 1561 # . . discard args 1562 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1563 # . clear-stream($_test-output-buffered-file->buffer) 1564 # . . push args 1565 68/push $_test-output-buffered-file->buffer/imm32 1566 # . . call 1567 e8/call clear-stream/disp32 1568 # . . discard args 1569 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1570 # initialize input 1571 # . write(_test-input-stream, "30 abcd/o") 1572 # . . push args 1573 68/push "30 abcd/o"/imm32 1574 68/push _test-input-stream/imm32 1575 # . . call 1576 e8/call write/disp32 1577 # . . discard args 1578 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1579 # convert-data(_test-input-stream, _test-output-buffered-file) 1580 # . . push args 1581 68/push _test-output-buffered-file/imm32 1582 68/push _test-input-stream/imm32 1583 # . . call 1584 e8/call convert-data/disp32 1585 # . . discard args 1586 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1587 # check output 1588 # . flush(_test-output-buffered-file) 1589 # . . push args 1590 68/push _test-output-buffered-file/imm32 1591 # . . call 1592 e8/call flush/disp32 1593 # . . discard args 1594 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1595 # . check-stream-equal(_test-output-stream, "30 abcd/o \n", msg) 1596 # . . push args 1597 68/push "F - test-convert-data-byte-then-name"/imm32 1598 68/push "30 abcd/o \n"/imm32 1599 68/push _test-output-stream/imm32 1600 # . . call 1601 e8/call check-stream-equal/disp32 1602 # . . discard args 1603 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1604 # . epilogue 1605 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1606 5d/pop-to-ebp 1607 c3/return 1608 1609 test-convert-data-multiple-words: 1610 # Multiple words in input stream get processed one by one. 1611 # . prologue 1612 55/push-ebp 1613 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1614 # setup 1615 # . clear-stream(_test-input-stream) 1616 # . . push args 1617 68/push _test-input-stream/imm32 1618 # . . call 1619 e8/call clear-stream/disp32 1620 # . . discard args 1621 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1622 # . clear-stream(_test-output-stream) 1623 # . . push args 1624 68/push _test-output-stream/imm32 1625 # . . call 1626 e8/call clear-stream/disp32 1627 # . . discard args 1628 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1629 # . clear-stream($_test-output-buffered-file->buffer) 1630 # . . push args 1631 68/push $_test-output-buffered-file->buffer/imm32 1632 # . . call 1633 e8/call clear-stream/disp32 1634 # . . discard args 1635 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1636 # initialize input 1637 # . write(_test-input-stream, "30 abcd/o 42e1/imm32") 1638 # . . push args 1639 68/push "30 abcd/o 42e1/imm32"/imm32 1640 68/push _test-input-stream/imm32 1641 # . . call 1642 e8/call write/disp32 1643 # . . discard args 1644 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1645 # convert-data(_test-input-stream, _test-output-buffered-file) 1646 # . . push args 1647 68/push _test-output-buffered-file/imm32 1648 68/push _test-input-stream/imm32 1649 # . . call 1650 e8/call convert-data/disp32 1651 # . . discard args 1652 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1653 # check output 1654 # . flush(_test-output-buffered-file) 1655 # . . push args 1656 68/push _test-output-buffered-file/imm32 1657 # . . call 1658 e8/call flush/disp32 1659 # . . discard args 1660 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1661 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 1687 # . check-stream-equal(_test-output-stream, "30 abcd/o 42 e1 00 00 \n", msg) 1688 # . . push args 1689 68/push "F - test-convert-data-multiple-words"/imm32 1690 68/push "30 abcd/o e1 42 00 00 \n"/imm32 1691 68/push _test-output-stream/imm32 1692 # . . call 1693 e8/call check-stream-equal/disp32 1694 # . . discard args 1695 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1696 # . epilogue 1697 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1698 5d/pop-to-ebp 1699 c3/return 1700 1701 test-convert-data-trailing-comment: 1702 # Trailing comments in data segment get appropriately ignored. 1703 # . prologue 1704 55/push-ebp 1705 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1706 # setup 1707 # . clear-stream(_test-input-stream) 1708 # . . push args 1709 68/push _test-input-stream/imm32 1710 # . . call 1711 e8/call clear-stream/disp32 1712 # . . discard args 1713 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1714 # . clear-stream(_test-output-stream) 1715 # . . push args 1716 68/push _test-output-stream/imm32 1717 # . . call 1718 e8/call clear-stream/disp32 1719 # . . discard args 1720 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1721 # . clear-stream($_test-output-buffered-file->buffer) 1722 # . . push args 1723 68/push $_test-output-buffered-file->buffer/imm32 1724 # . . call 1725 e8/call clear-stream/disp32 1726 # . . discard args 1727 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1728 # initialize input 1729 # . write(_test-input-stream, "30/imm32 # comment") 1730 # . . push args 1731 68/push "30/imm32 # comment"/imm32 1732 68/push _test-input-stream/imm32 1733 # . . call 1734 e8/call write/disp32 1735 # . . discard args 1736 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1737 # convert-data(_test-input-stream, _test-output-buffered-file) 1738 # . . push args 1739 68/push _test-output-buffered-file/imm32 1740 68/push _test-input-stream/imm32 1741 # . . call 1742 e8/call convert-data/disp32 1743 # . . discard args 1744 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1745 # check output 1746 # . flush(_test-output-buffered-file) 1747 # . . push args 1748 68/push _test-output-buffered-file/imm32 1749 # . . call 1750 e8/call flush/disp32 1751 # . . discard args 1752 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1753 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 1779 # . check-stream-equal(_test-output-stream, "30 00 00 00 # comment", msg) 1780 # . . push args 1781 68/push "F - test-convert-data-trailing-comment"/imm32 1782 68/push "30 00 00 00 # comment"/imm32 1783 68/push _test-output-stream/imm32 1784 # . . call 1785 e8/call check-stream-equal/disp32 1786 # . . discard args 1787 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1788 # . epilogue 1789 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1790 5d/pop-to-ebp 1791 c3/return 1792 1793 # pack an instruction, following the C++ version 1794 # 1795 # zero error handling at the moment (continuing to rely on the C++ version for that): 1796 # missing fields are always 0-filled 1797 # bytes never mentioned are silently dropped; if you don't provide /mod, /rm32 or /r32 you don't get a 0 ModR/M byte. You get *no* ModR/M byte. 1798 # may pick up any of duplicate operands in an instruction 1799 # silently drop extraneous operands 1800 # unceremoniously abort on non-numeric operands except disp or imm 1801 # opcodes must be lowercase and zero padded 1802 # opcodes with misleading operand metadata may get duplicated as operands as well. don't rely on this. 1803 convert-instruction: # line: (addr stream byte), out: (addr buffered-file) 1804 # pseudocode: 1805 # # some early exits 1806 # var word-slice = next-word(line) 1807 # if slice-empty?(word-slice) 1808 # write-stream-data(out, line) 1809 # return 1810 # if slice-starts-with?(word-slice, "#") 1811 # write-stream-data(out, line) 1812 # return 1813 # if slice-ends-with?(word-slice, ":") 1814 # write-stream-data(out, line) 1815 # return 1816 # # really convert 1817 # emit-opcodes(line, out) 1818 # emit-modrm(line, out) 1819 # emit-sib(line, out) 1820 # emit-disp(line, out) 1821 # emit-imm(line, out) 1822 # emit-line-in-comment(line, out) 1823 # 1824 # . prologue 1825 55/push-ebp 1826 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1827 # . save registers 1828 50/push-eax 1829 51/push-ecx 1830 52/push-edx 1831 # var word-slice/ecx: slice 1832 68/push 0/imm32/end 1833 68/push 0/imm32/start 1834 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 1835 # next-word(line, word-slice) 1836 # . . push args 1837 51/push-ecx 1838 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1839 # . . call 1840 e8/call next-word/disp32 1841 # . . discard args 1842 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1843 $convert-instruction:check0: 1844 # if (slice-empty?(word-slice)) break 1845 # . eax = slice-empty?(word-slice) 1846 # . . push args 1847 51/push-ecx 1848 # . . call 1849 e8/call slice-empty?/disp32 1850 # . . discard args 1851 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1852 # . if (eax != false) pass through 1853 3d/compare-eax-and 0/imm32/false 1854 75/jump-if-!= $convert-instruction:pass-through/disp8 1855 $convert-instruction:check1: 1856 # if (slice-starts-with?(word-slice, "#")) write-stream-data(out, line) 1857 # . var start/edx: (addr byte) = word-slice->start 1858 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx 1859 # . var c/eax: byte = *start 1860 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 1861 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL 1862 # . if (c == '#') pass through 1863 3d/compare-eax-and 0x23/imm32/hash 1864 74/jump-if-= $convert-instruction:pass-through/disp8 1865 $convert-instruction:check2: 1866 # if (slice-ends-with?(word-slice, ":")) write-stream-data(out, line) 1867 # . var end/edx: (addr byte) = word-slice->end 1868 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx 1869 # . var c/eax: byte = *(end-1) 1870 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 1871 8a/copy-byte 1/mod/*+disp8 2/rm32/edx . . . 0/r32/AL -1/disp8 . # copy byte at *ecx to AL 1872 # . if (c == ':') pass through 1873 3d/compare-eax-and 0x3a/imm32/colon 1874 75/jump-if-!= $convert-instruction:really-convert/disp8 1875 $convert-instruction:pass-through: 1876 # write-stream-data(out, line) 1877 # . . push args 1878 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1879 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1880 # . . call 1881 e8/call write-stream-data/disp32 1882 # . . discard args 1883 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1884 # return 1885 eb/jump $convert-instruction:end/disp8 1886 $convert-instruction:really-convert: 1887 # emit-opcodes(line, out) 1888 # . . push args 1889 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1890 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1891 # . . call 1892 e8/call emit-opcodes/disp32 1893 # . . discard args 1894 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1895 # emit-modrm(line, out) 1896 # . . push args 1897 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1898 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1899 # . . call 1900 e8/call emit-modrm/disp32 1901 # . . discard args 1902 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1903 # emit-sib(line, out) 1904 # . . push args 1905 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1906 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1907 # . . call 1908 e8/call emit-sib/disp32 1909 # . . discard args 1910 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1911 # emit-disp(line, out) 1912 # . . push args 1913 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1914 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1915 # . . call 1916 e8/call emit-disp/disp32 1917 # . . discard args 1918 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1919 # emit-imm(line, out) 1920 # . . push args 1921 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1922 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1923 # . . call 1924 e8/call emit-imm/disp32 1925 # . . discard args 1926 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1927 # emit-line-in-comment(line, out) 1928 # . . push args 1929 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 1930 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1931 # . . call 1932 e8/call emit-line-in-comment/disp32 1933 # . . discard args 1934 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1935 $convert-instruction:end: 1936 # . restore locals 1937 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1938 # . restore registers 1939 5a/pop-to-edx 1940 59/pop-to-ecx 1941 58/pop-to-eax 1942 # . epilogue 1943 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1944 5d/pop-to-ebp 1945 c3/return 1946 1947 emit-opcodes: # line: (addr stream byte), out: (addr buffered-file) 1948 # opcodes occupy 1-3 bytes: 1949 # xx 1950 # 0f xx 1951 # f2 xx 1952 # f3 xx 1953 # f2 0f xx 1954 # f3 0f xx 1955 # 1956 # pseudocode: 1957 # rewind-stream(line) 1958 # 1959 # var op1 = next-word(line) 1960 # if (slice-empty?(op1) || slice-starts-with?(op1, "#")) return 1961 # op1 = next-token-from-slice(op1->start, op1->end, "/") 1962 # write-slice-buffered(out, op1) 1963 # if !slice-equal?(op1, "0f") && !slice-equal?(op1, "f2") && !slice-equal?(op1, "f3") 1964 # return 1965 # 1966 # var op2 = next-word(line) 1967 # if (slice-empty?(op2) || slice-starts-with?(op2, "#")) return 1968 # op2 = next-token-from-slice(op2->start, op2->end, "/") 1969 # write-slice-buffered(out, op2) 1970 # if slice-equal?(op1, "0f") 1971 # return 1972 # if !slice-equal?(op2, "0f") 1973 # return 1974 # 1975 # var op3 = next-word(line) 1976 # if (slice-empty?(op3) || slice-starts-with?(op3, "#")) return 1977 # op3 = next-token-from-slice(op3->start, op3->end, "/") 1978 # write-slice-buffered(out, op3) 1979 # 1980 # . prologue 1981 55/push-ebp 1982 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1983 # . save registers 1984 50/push-eax 1985 51/push-ecx 1986 52/push-edx 1987 53/push-ebx 1988 # var op1/ecx: slice 1989 68/push 0/imm32/end 1990 68/push 0/imm32/start 1991 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 1992 # var op2/edx: slice 1993 68/push 0/imm32/end 1994 68/push 0/imm32/start 1995 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx 1996 # rewind-stream(line) 1997 # . . push args 1998 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 1999 # . . call 2000 e8/call rewind-stream/disp32 2001 # . . discard args 2002 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2003 $emit-opcodes:op1: 2004 # next-word(line, op1) 2005 # . . push args 2006 51/push-ecx 2007 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2008 # . . call 2009 e8/call next-word/disp32 2010 # . . discard args 2011 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2012 # if (slice-empty?(op1)) return 2013 # . eax = slice-empty?(op1) 2014 # . . push args 2015 51/push-ecx 2016 # . . call 2017 e8/call slice-empty?/disp32 2018 # . . discard args 2019 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2020 # . if (eax != false) return 2021 3d/compare-eax-and 0/imm32/false 2022 0f 85/jump-if-!= $emit-opcodes:end/disp32 2023 # if (slice-starts-with?(op1, "#")) return 2024 # . var start/ebx: (addr byte) = op1->start 2025 8b/copy 0/mod/indirect 1/rm32/ecx . . . 3/r32/ebx . . # copy *ecx to ebx 2026 # . var c/eax: byte = *start 2027 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 2028 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL 2029 # . if (c == '#') return 2030 3d/compare-eax-and 0x23/imm32/hash 2031 0f 84/jump-if-= $emit-opcodes:end/disp32 2032 # op1 = next-token-from-slice(op1->start, op1->end, '/') 2033 # . . push args 2034 51/push-ecx 2035 68/push 0x2f/imm32/slash 2036 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 2037 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx 2038 # . . call 2039 e8/call next-token-from-slice/disp32 2040 # . . discard args 2041 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 2042 # write-slice-buffered(out, op1) 2043 # . . push args 2044 51/push-ecx 2045 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 2046 # . . call 2047 e8/call write-slice-buffered/disp32 2048 # . . discard args 2049 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2050 # write-buffered(out, " ") 2051 # . . push args 2052 68/push Space/imm32 2053 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 2054 # . . call 2055 e8/call write-buffered/disp32 2056 # . . discard args 2057 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2058 # if (slice-equal?(op1, "0f")) goto op2 2059 # . eax = slice-equal?(op1, "0f") 2060 # . . push args 2061 68/push "0f"/imm32 2062 51/push-ecx 2063 # . . call 2064 e8/call slice-equal?/disp32 2065 # . . discard args 2066 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2067 # . if (eax != false) goto op2 2068 3d/compare-eax-and 0/imm32/false 2069 75/jump-if-!= $emit-opcodes:op2/disp8 2070 # if (slice-equal?(op1, "f2")) goto op2 2071 # . eax = slice-equal?(op1, "f2") 2072 # . . push args 2073 68/push "f2"/imm32 2074 51/push-ecx 2075 # . . call 2076 e8/call slice-equal?/disp32 2077 # . . discard args 2078 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2079 # . if (eax != false) goto op2 2080 3d/compare-eax-and 0/imm32/false 2081 75/jump-if-!= $emit-opcodes:op2/disp8 2082 # if (slice-equal?(op1, "f3")) goto op2 2083 # . eax = slice-equal?(op1, "f3") 2084 # . . push args 2085 68/push "f3"/imm32 2086 51/push-ecx 2087 # . . call 2088 e8/call slice-equal?/disp32 2089 # . . discard args 2090 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2091 # . if (eax != false) goto op2 2092 3d/compare-eax-and 0/imm32/false 2093 75/jump-if-!= $emit-opcodes:op2/disp8 2094 # otherwise return 2095 e9/jump $emit-opcodes:end/disp32 2096 $emit-opcodes:op2: 2097 # next-word(line, op2) 2098 # . . push args 2099 52/push-edx 2100 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2101 # . . call 2102 e8/call next-word/disp32 2103 # . . discard args 2104 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2105 # if (slice-empty?(op2)) return 2106 # . eax = slice-empty?(op2) 2107 # . . push args 2108 52/push-edx 2109 # . . call 2110 e8/call slice-empty?/disp32 2111 # . . discard args 2112 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2113 # . if (eax != false) return 2114 3d/compare-eax-and 0/imm32/false 2115 0f 85/jump-if-!= $emit-opcodes:end/disp32 2116 # if (slice-starts-with?(op2, "#")) return 2117 # . var start/ebx: (addr byte) = op2->start 2118 8b/copy 0/mod/indirect 2/rm32/edx . . . 3/r32/ebx . . # copy *edx to ebx 2119 # . var c/eax: byte = *start 2120 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 2121 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL 2122 # . if (c == '#') return 2123 3d/compare-eax-and 0x23/imm32/hash 2124 0f 84/jump-if-= $emit-opcodes:end/disp32 2125 # op2 = next-token-from-slice(op2->start, op2->end, '/') 2126 # . . push args 2127 52/push-edx 2128 68/push 0x2f/imm32/slash 2129 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) 2130 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx 2131 # . . call 2132 e8/call next-token-from-slice/disp32 2133 # . . discard args 2134 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 2135 # write-slice-buffered(out, op2) 2136 # . . push args 2137 52/push-edx 2138 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 2139 # . . call 2140 e8/call write-slice-buffered/disp32 2141 # . . discard args 2142 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2143 # write-buffered(out, " ") 2144 # . . push args 2145 68/push Space/imm32 2146 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 2147 # . . call 2148 e8/call write-buffered/disp32 2149 # . . discard args 2150 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2151 # if (slice-equal?(op1, "0f")) return 2152 # . eax = slice-equal?(op1, "0f") 2153 # . . push args 2154 68/push "0f"/imm32 2155 51/push-ecx 2156 # . . call 2157 e8/call slice-equal?/disp32 2158 # . . discard args 2159 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2160 # . if (eax != false) return 2161 3d/compare-eax-and 0/imm32/false 2162 0f 85/jump-if-!= $emit-opcodes:end/disp32 2163 # if (!slice-equal?(op2, "0f")) return 2164 # . eax = slice-equal?(op2, "0f") 2165 # . . push args 2166 68/push "0f"/imm32 2167 52/push-edx 2168 # . . call 2169 e8/call slice-equal?/disp32 2170 # . . discard args 2171 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2172 # . if (eax == false) return 2173 3d/compare-eax-and 0/imm32/false 2174 0f 84/jump-if-= $emit-opcodes:end/disp32 2175 $emit-opcodes:op3: 2176 # next-word(line, op3) # reuse op2/edx 2177 # . . push args 2178 52/push-edx 2179 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2180 # . . call 2181 e8/call next-word/disp32 2182 # . . discard args 2183 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2184 # if (slice-empty?(op3)) return 2185 # . eax = slice-empty?(op3) 2186 # . . push args 2187 52/push-edx 2188 # . . call 2189 e8/call slice-empty?/disp32 2190 # . . discard args 2191 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2192 # . if (eax != false) return 2193 3d/compare-eax-and 0/imm32/false 2194 0f 85/jump-if-!= $emit-opcodes:end/disp32 2195 # if (slice-starts-with?(op3, "#")) return 2196 # . var start/ebx: (addr byte) = op2->start 2197 8b/copy 0/mod/indirect 2/rm32/edx . . . 3/r32/ebx . . # copy *edx to ebx 2198 # . var c/eax: byte = *start 2199 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 2200 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL 2201 # . if (c == '#') return 2202 3d/compare-eax-and 0x23/imm32/hash 2203 0f 84/jump-if-= $emit-opcodes:end/disp32 2204 # op3 = next-token-from-slice(op3->start, op3->end, '/') 2205 # . . push args 2206 52/push-edx 2207 68/push 0x2f/imm32/slash 2208 ff 6/subop/push 1/mod/*+disp8 2/rm32/edx . . . . 4/disp8 . # push *(edx+4) 2209 ff 6/subop/push 0/mod/indirect 2/rm32/edx . . . . . . # push *edx 2210 # . . call 2211 e8/call next-token-from-slice/disp32 2212 # . . discard args 2213 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 2214 # write-slice-buffered(out, op3) 2215 # . . push args 2216 52/push-edx 2217 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 2218 # . . call 2219 e8/call write-slice-buffered/disp32 2220 # . . discard args 2221 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2222 # write-buffered(out, " ") 2223 # . . push args 2224 68/push Space/imm32 2225 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 2226 # . . call 2227 e8/call write-buffered/disp32 2228 # . . discard args 2229 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2230 $emit-opcodes:end: 2231 # . restore locals 2232 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 2233 # . restore registers 2234 5b/pop-to-ebx 2235 5a/pop-to-edx 2236 59/pop-to-ecx 2237 58/pop-to-eax 2238 # . epilogue 2239 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 2240 5d/pop-to-ebp 2241 c3/return 2242 2243 emit-modrm: # line: (addr stream byte), out: (addr buffered-file) 2244 # pseudocode: 2245 # rewind-stream(line) 2246 # var has-modrm? = false, mod = 0, rm32 = 0, r32 = 0 2247 # var word-slice: slice 2248 # while true 2249 # word-slice = next-word(line) 2250 # if (slice-empty?(word-slice)) break 2251 # if (slice-starts-with?(word-slice, "#")) break 2252 # if (has-metadata?(word-slice, "mod")) 2253 # mod = parse-hex-int-from-slice(next-token-from-slice(word-slice, "/")) 2254 # has-modrm? = true 2255 # else if has-metadata?(word-slice, "rm32") or has-metadata?(word-slice, "xm32") 2256 # rm32 = parse-hex-int-from-slice(next-token-from-slice(word-slice, "/")) 2257 # has-modrm? = true 2258 # else if has-metadata?(word-slice, "r32") or has-metadata?(word-slice, "x32") or has-metadata?(word-slice, "subop") 2259 # r32 = parse-hex-int-from-slice(next-token-from-slice(word-slice, "/")) 2260 # has-modrm? = true 2261 # if has-modrm? 2262 # var modrm = mod & 0b11 2263 # modrm <<= 3 2264 # modrm |= r32 & 0b111 2265 # modrm <<= 3 2266 # modrm |= rm32 & 0b111 2267 # emit-hex(out, modrm, 1) 2268 # 2269 # . prologue 2270 55/push-ebp 2271 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 2272 # . save registers 2273 50/push-eax 2274 51/push-ecx 2275 52/push-edx 2276 53/push-ebx 2277 56/push-esi 2278 57/push-edi 2279 # var word-slice/ecx: slice 2280 68/push 0/imm32/end 2281 68/push 0/imm32/start 2282 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 2283 # var has-modrm?/edx: boolean = false 2284 31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx 2285 # var mod/ebx: byte = 0 2286 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx 2287 # var rm32/esi: byte = 0 2288 31/xor 3/mod/direct 6/rm32/esi . . . 6/r32/esi . . # clear esi 2289 # var r32/edi: byte = 0 2290 31/xor 3/mod/direct 7/rm32/edi . . . 7/r32/edi . . # clear edi 2291 # rewind-stream(line) 2292 # . . push args 2293 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2294 # . . call 2295 e8/call rewind-stream/disp32 2296 # . . discard args 2297 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2298 +-- 33 lines: #? # dump line -------------------------------------------------------------------------------------------------------------------------------------------------------- 2331 $emit-modrm:loop: 2332 # next-word(line, word-slice) 2333 # . . push args 2334 51/push-ecx 2335 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2336 # . . call 2337 e8/call next-word/disp32 2338 # . . discard args 2339 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2340 +-- 40 lines: #? # dump word-slice -------------------------------------------------------------------------------------------------------------------------------------------------- 2380 $emit-modrm:check0: 2381 # if (slice-empty?(word-slice)) break 2382 # . eax = slice-empty?(word-slice) 2383 # . . push args 2384 51/push-ecx 2385 # . . call 2386 e8/call slice-empty?/disp32 2387 # . . discard args 2388 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2389 # . if (eax != false) pass through 2390 3d/compare-eax-and 0/imm32/false 2391 0f 85/jump-if-!= $emit-modrm:break/disp32 2392 $emit-modrm:check1: 2393 # if (slice-starts-with?(word-slice, "#")) break 2394 # . spill edx 2395 52/push-edx 2396 # . var start/edx: (addr byte) = word-slice->start 2397 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx 2398 # . var c/eax: byte = *start 2399 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 2400 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL 2401 # . restore edx 2402 5a/pop-to-edx 2403 # . if (c == '#') pass through 2404 3d/compare-eax-and 0x23/imm32/hash 2405 0f 84/jump-if-= $emit-modrm:break/disp32 2406 $emit-modrm:check-for-mod: 2407 # if (has-metadata?(word-slice, "mod")) 2408 # . eax = has-metadata?(ecx, "mod") 2409 # . . push args 2410 68/push "mod"/imm32 2411 51/push-ecx 2412 # . . call 2413 e8/call has-metadata?/disp32 2414 # . . discard args 2415 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2416 # . if (eax == false) goto next check 2417 3d/compare-eax-and 0/imm32/false 2418 74/jump-if-= $emit-modrm:check-for-rm32/disp8 2419 $emit-modrm:mod: 2420 # mod = parse-hex-int-from-slice(next-token-from-slice(word-slice->start, word-slice->end, '/')) 2421 # . eax = parse-datum-of-word(word-slice) 2422 # . . push args 2423 51/push-ecx 2424 # . . call 2425 e8/call parse-datum-of-word/disp32 2426 # . . discard args 2427 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2428 # . mod = eax 2429 89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx 2430 # has-modrm? = true 2431 ba/copy-to-edx 1/imm32/true 2432 # continue 2433 e9/jump $emit-modrm:loop/disp32 2434 $emit-modrm:check-for-rm32: 2435 # if (has-metadata?(word-slice, "rm32")) 2436 # . eax = has-metadata?(ecx, "rm32") 2437 # . . push args 2438 68/push "rm32"/imm32 2439 51/push-ecx 2440 # . . call 2441 e8/call has-metadata?/disp32 2442 # . . discard args 2443 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2444 # . if (eax == false) goto next check 2445 3d/compare-eax-and 0/imm32/false 2446 74/jump-if-= $emit-modrm:check-for-xm32/disp8 2447 $emit-modrm:rm32: 2448 # rm32 = parse-hex-int-from-slice(next-token-from-slice(word-slice->start, word-slice->end, '/')) 2449 # . eax = parse-datum-of-word(word-slice) 2450 # . . push args 2451 51/push-ecx 2452 # . . call 2453 e8/call parse-datum-of-word/disp32 2454 # . . discard args 2455 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2456 # . rm32 = eax 2457 89/copy 3/mod/direct 6/rm32/esi . . . 0/r32/eax . . # copy eax to esi 2458 # has-modrm? = true 2459 ba/copy-to-edx 1/imm32/true 2460 # continue 2461 e9/jump $emit-modrm:loop/disp32 2462 $emit-modrm:check-for-xm32: 2463 # if (has-metadata?(word-slice, "xm32")) 2464 # . eax = has-metadata?(ecx, "xm32") 2465 # . . push args 2466 68/push "xm32"/imm32 2467 51/push-ecx 2468 # . . call 2469 e8/call has-metadata?/disp32 2470 # . . discard args 2471 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2472 # . if (eax == false) goto next check 2473 3d/compare-eax-and 0/imm32/false 2474 74/jump-if-= $emit-modrm:check-for-r32/disp8 2475 $emit-modrm:xm32: 2476 # rm32 = parse-hex-int-from-slice(next-token-from-slice(word-slice->start, word-slice->end, '/')) 2477 # . eax = parse-datum-of-word(word-slice) 2478 # . . push args 2479 51/push-ecx 2480 # . . call 2481 e8/call parse-datum-of-word/disp32 2482 # . . discard args 2483 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2484 # . rm32 = eax 2485 89/copy 3/mod/direct 6/rm32/esi . . . 0/r32/eax . . # copy eax to esi 2486 # has-modrm? = true 2487 ba/copy-to-edx 1/imm32/true 2488 # continue 2489 e9/jump $emit-modrm:loop/disp32 2490 $emit-modrm:check-for-r32: 2491 # if (has-metadata?(word-slice, "r32")) 2492 # . eax = has-metadata?(ecx, "r32") 2493 # . . push args 2494 68/push "r32"/imm32 2495 51/push-ecx 2496 # . . call 2497 e8/call has-metadata?/disp32 2498 # . . discard args 2499 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2500 # . if (eax == false) goto next check 2501 3d/compare-eax-and 0/imm32/false 2502 74/jump-if-= $emit-modrm:check-for-x32/disp8 2503 $emit-modrm:r32: 2504 # r32 = parse-hex-int-from-slice(next-token-from-slice(word-slice->start, word-slice->end, '/')) 2505 # . eax = parse-datum-of-word(word-slice) 2506 # . . push args 2507 51/push-ecx 2508 # . . call 2509 e8/call parse-datum-of-word/disp32 2510 # . . discard args 2511 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2512 # . r32 = eax 2513 89/copy 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # copy eax to edi 2514 # has-modrm? = true 2515 ba/copy-to-edx 1/imm32/true 2516 # continue 2517 e9/jump $emit-modrm:loop/disp32 2518 $emit-modrm:check-for-x32: 2519 # if (has-metadata?(word-slice, "x32")) 2520 # . eax = has-metadata?(ecx, "x32") 2521 # . . push args 2522 68/push "x32"/imm32 2523 51/push-ecx 2524 # . . call 2525 e8/call has-metadata?/disp32 2526 # . . discard args 2527 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2528 # . if (eax == false) goto next check 2529 3d/compare-eax-and 0/imm32/false 2530 74/jump-if-= $emit-modrm:check-for-subop/disp8 2531 $emit-modrm:x32: 2532 # r32 = parse-hex-int-from-slice(next-token-from-slice(word-slice->start, word-slice->end, '/')) 2533 # . eax = parse-datum-of-word(word-slice) 2534 # . . push args 2535 51/push-ecx 2536 # . . call 2537 e8/call parse-datum-of-word/disp32 2538 # . . discard args 2539 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2540 # . r32 = eax 2541 89/copy 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # copy eax to edi 2542 # has-modrm? = true 2543 ba/copy-to-edx 1/imm32/true 2544 # continue 2545 e9/jump $emit-modrm:loop/disp32 2546 $emit-modrm:check-for-subop: 2547 # if (has-metadata?(word-slice, "subop")) 2548 # . eax = has-metadata?(ecx, "subop") 2549 # . . push args 2550 68/push "subop"/imm32 2551 51/push-ecx 2552 # . . call 2553 e8/call has-metadata?/disp32 2554 # . . discard args 2555 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2556 # . if (eax == false) loop 2557 3d/compare-eax-and 0/imm32/false 2558 0f 84/jump-if-= $emit-modrm:loop/disp32 2559 $emit-modrm:subop: 2560 # r32 = parse-hex-int-from-slice(next-token-from-slice(word-slice->start, word-slice->end, '/')) 2561 # . eax = parse-datum-of-word(word-slice) 2562 # . . push args 2563 51/push-ecx 2564 # . . call 2565 e8/call parse-datum-of-word/disp32 2566 # . . discard args 2567 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2568 # . r32 = eax 2569 89/copy 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # copy eax to edi 2570 # has-modrm? = true 2571 ba/copy-to-edx 1/imm32/true 2572 # continue 2573 e9/jump $emit-modrm:loop/disp32 2574 $emit-modrm:break: 2575 # if (!has-modrm?) return 2576 81 7/subop/compare 3/mod/direct 2/rm32/edx . . . . . 0/imm32/false # compare edx 2577 74/jump-if-= $emit-modrm:end/disp8 2578 $emit-modrm:calculate: 2579 # var modrm/ebx: byte = mod & 0b11 2580 81 4/subop/and 3/mod/direct 3/rm32/ebx . . . . . 3/imm32/0b11 # bitwise and of ebx 2581 # modrm <<= 3 2582 c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 3/imm8 # shift ebx left by 3 bits 2583 # modrm |= r32 & 0b111 2584 81 4/subop/and 3/mod/direct 7/rm32/edi . . . . . 7/imm32/0b111 # bitwise and of edi 2585 09/or 3/mod/direct 3/rm32/ebx . . . 7/r32/edi . . # ebx = bitwise OR with edi 2586 # modrm <<= 3 2587 c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 3/imm8 # shift ebx left by 3 bits 2588 # modrm |= rm32 & 0b111 2589 81 4/subop/and 3/mod/direct 6/rm32/esi . . . . . 7/imm32/0b111 # bitwise and of esi 2590 09/or 3/mod/direct 3/rm32/ebx . . . 6/r32/esi . . # ebx = bitwise OR with esi 2591 $emit-modrm:emit: 2592 # emit-hex(out, modrm, 1) 2593 # . . push args 2594 68/push 1/imm32 2595 53/push-ebx 2596 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 2597 # . . call 2598 e8/call emit-hex/disp32 2599 # . . discard args 2600 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 2601 $emit-modrm:end: 2602 # . restore locals 2603 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2604 # . restore registers 2605 5f/pop-to-edi 2606 5e/pop-to-esi 2607 5b/pop-to-ebx 2608 5a/pop-to-edx 2609 59/pop-to-ecx 2610 58/pop-to-eax 2611 # . epilogue 2612 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 2613 5d/pop-to-ebp 2614 c3/return 2615 2616 emit-sib: # line: (addr stream byte), out: (addr buffered-file) 2617 # pseudocode: 2618 # var has-sib? = false, base = 0, index = 0, scale = 0 2619 # var word-slice: slice 2620 # while true 2621 # word-slice = next-word(line) 2622 # if (slice-empty?(word-slice)) break 2623 # if (slice-starts-with?(word-slice, "#")) break 2624 # if (has-metadata?(word-slice, "base") 2625 # base = parse-hex-int-from-slice(next-token-from-slice(word-slice, "/")) 2626 # has-sib? = true 2627 # else if (has-metadata?(word-slice, "index") 2628 # index = parse-hex-int-from-slice(next-token-from-slice(word-slice, "/")) 2629 # has-sib? = true 2630 # else if (has-metadata?(word-slice, "scale") 2631 # scale = parse-hex-int-from-slice(next-token-from-slice(word-slice, "/")) 2632 # has-sib? = true 2633 # if has-sib? 2634 # var sib = scale & 0b11 2635 # sib <<= 3 2636 # sib |= index & 0b111 2637 # sib <<= 3 2638 # sib |= base & 0b111 2639 # emit-hex(out, sib, 1) 2640 # 2641 # . prologue 2642 55/push-ebp 2643 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 2644 # . save registers 2645 50/push-eax 2646 51/push-ecx 2647 52/push-edx 2648 53/push-ebx 2649 56/push-esi 2650 57/push-edi 2651 # var word-slice/ecx: slice 2652 68/push 0/imm32/end 2653 68/push 0/imm32/start 2654 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 2655 # var has-sib?/edx: boolean = false 2656 31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx 2657 # var scale/ebx: byte = 0 2658 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx 2659 # var base/esi: byte = 0 2660 31/xor 3/mod/direct 6/rm32/esi . . . 6/r32/esi . . # clear esi 2661 # var index/edi: byte = 0 2662 31/xor 3/mod/direct 7/rm32/edi . . . 7/r32/edi . . # clear edi 2663 # rewind-stream(line) 2664 # . . push args 2665 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2666 # . . call 2667 e8/call rewind-stream/disp32 2668 # . . discard args 2669 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2670 $emit-sib:loop: 2671 +-- 26 lines: #? # dump line -------------------------------------------------------------------------------------------------------------------------------------------------------- 2697 # next-word(line, word-slice) 2698 # . . push args 2699 51/push-ecx 2700 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2701 # . . call 2702 e8/call next-word/disp32 2703 # . . discard args 2704 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2705 +-- 40 lines: #? # dump word-slice -------------------------------------------------------------------------------------------------------------------------------------------------- 2745 $emit-sib:check0: 2746 # if (slice-empty?(word-slice)) break 2747 # . eax = slice-empty?(word-slice) 2748 # . . push args 2749 51/push-ecx 2750 # . . call 2751 e8/call slice-empty?/disp32 2752 # . . discard args 2753 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2754 # . if (eax != false) pass through 2755 3d/compare-eax-and 0/imm32/false 2756 0f 85/jump-if-!= $emit-sib:break/disp32 2757 $emit-sib:check1: 2758 # if (slice-starts-with?(word-slice, "#")) break 2759 # . spill edx 2760 52/push-edx 2761 # . var start/edx: (addr byte) = word-slice->start 2762 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx 2763 # . var c/eax: byte = *start 2764 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 2765 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL 2766 # . restore edx 2767 5a/pop-to-edx 2768 # . if (c == '#') pass through 2769 3d/compare-eax-and 0x23/imm32/hash 2770 0f 84/jump-if-= $emit-sib:break/disp32 2771 $emit-sib:check-for-scale: 2772 # if (has-metadata?(word-slice, "scale")) 2773 # . eax = has-metadata?(ecx, "scale") 2774 # . . push args 2775 68/push "scale"/imm32 2776 51/push-ecx 2777 # . . call 2778 e8/call has-metadata?/disp32 2779 # . . discard args 2780 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2781 # . if (eax == false) goto next check 2782 3d/compare-eax-and 0/imm32/false 2783 74/jump-if-= $emit-sib:check-for-base/disp8 2784 $emit-sib:scale: 2785 # scale = parse-hex-int-from-slice(next-token-from-slice(word-slice->start, word-slice->end, '/')) 2786 # . eax = parse-datum-of-word(word-slice) 2787 # . . push args 2788 51/push-ecx 2789 # . . call 2790 e8/call parse-datum-of-word/disp32 2791 # . . discard args 2792 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2793 # . scale = eax 2794 89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx 2795 # has-sib? = true 2796 ba/copy-to-edx 1/imm32/true 2797 # continue 2798 e9/jump $emit-sib:loop/disp32 2799 $emit-sib:check-for-base: 2800 # if (has-metadata?(word-slice, "base")) 2801 # . eax = has-metadata?(ecx, "base") 2802 # . . push args 2803 68/push "base"/imm32 2804 51/push-ecx 2805 # . . call 2806 e8/call has-metadata?/disp32 2807 # . . discard args 2808 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2809 # . if (eax == false) goto next check 2810 3d/compare-eax-and 0/imm32/false 2811 74/jump-if-= $emit-sib:check-for-index/disp8 2812 $emit-sib:base: 2813 # base = parse-hex-int-from-slice(next-token-from-slice(word-slice->start, word-slice->end, '/')) 2814 # . eax = parse-datum-of-word(word-slice) 2815 # . . push args 2816 51/push-ecx 2817 # . . call 2818 e8/call parse-datum-of-word/disp32 2819 # . . discard args 2820 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2821 # . base = eax 2822 89/copy 3/mod/direct 6/rm32/esi . . . 0/r32/eax . . # copy eax to esi 2823 # has-sib? = true 2824 ba/copy-to-edx 1/imm32/true 2825 # continue 2826 e9/jump $emit-sib:loop/disp32 2827 $emit-sib:check-for-index: 2828 # if (has-metadata?(word-slice, "index")) 2829 # . eax = has-metadata?(ecx, "index") 2830 # . . push args 2831 68/push "index"/imm32 2832 51/push-ecx 2833 # . . call 2834 e8/call has-metadata?/disp32 2835 # . . discard args 2836 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2837 # . if (eax == false) loop 2838 3d/compare-eax-and 0/imm32/false 2839 0f 84/jump-if-= $emit-sib:loop/disp32 2840 $emit-sib:index: 2841 # index = parse-hex-int-from-slice(next-token-from-slice(word-slice->start, word-slice->end, '/')) 2842 # . eax = parse-datum-of-word(word-slice) 2843 # . . push args 2844 51/push-ecx 2845 # . . call 2846 e8/call parse-datum-of-word/disp32 2847 # . . discard args 2848 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2849 # . index = eax 2850 89/copy 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # copy eax to edi 2851 # has-sib? = true 2852 ba/copy-to-edx 1/imm32/true 2853 # continue 2854 e9/jump $emit-sib:loop/disp32 2855 $emit-sib:break: 2856 # if (!has-sib?) return 2857 81 7/subop/compare 3/mod/direct 2/rm32/edx . . . . . 0/imm32/false # compare edx 2858 74/jump-if-= $emit-sib:end/disp8 2859 $emit-sib:calculate: 2860 # var sib/ebx: byte = scale & 0b11 2861 81 4/subop/and 3/mod/direct 3/rm32/ebx . . . . . 3/imm32/0b11 # bitwise and of ebx 2862 # sib <<= 2 2863 c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 3/imm8 # shift ebx left by 3 bits 2864 # sib |= index & 0b111 2865 81 4/subop/and 3/mod/direct 7/rm32/edi . . . . . 7/imm32/0b111 # bitwise and of edi 2866 09/or 3/mod/direct 3/rm32/ebx . . . 7/r32/edi . . # ebx = bitwise OR with edi 2867 # sib <<= 3 2868 c1/shift 4/subop/left 3/mod/direct 3/rm32/ebx . . . . . 3/imm8 # shift ebx left by 3 bits 2869 # sib |= base & 0b111 2870 81 4/subop/and 3/mod/direct 6/rm32/esi . . . . . 7/imm32/0b111 # bitwise and of esi 2871 09/or 3/mod/direct 3/rm32/ebx . . . 6/r32/esi . . # ebx = bitwise OR with esi 2872 $emit-sib:emit: 2873 # emit-hex(out, sib, 1) 2874 # . . push args 2875 68/push 1/imm32 2876 53/push-ebx 2877 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 2878 # . . call 2879 e8/call emit-hex/disp32 2880 # . . discard args 2881 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 2882 $emit-sib:end: 2883 # . restore locals 2884 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2885 # . restore registers 2886 5f/pop-to-edi 2887 5e/pop-to-esi 2888 5b/pop-to-ebx 2889 5a/pop-to-edx 2890 59/pop-to-ecx 2891 58/pop-to-eax 2892 # . epilogue 2893 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 2894 5d/pop-to-ebp 2895 c3/return 2896 2897 emit-disp: # line: (addr stream byte), out: (addr buffered-file) 2898 # pseudocode: 2899 # rewind-stream(line) 2900 # var word-slice: slice 2901 # while true 2902 # word-slice = next-word(line) 2903 # if (slice-empty?(word-slice)) break 2904 # if (slice-starts-with?(word-slice, "#")) break 2905 # if has-metadata?(word-slice, "disp32") 2906 # emit(out, word-slice, 4) 2907 # break 2908 # if has-metadata?(word-slice, "disp16") 2909 # emit(out, word-slice, 2) 2910 # break 2911 # if has-metadata?(word-slice, "disp8") 2912 # emit(out, word-slice, 1) 2913 # break 2914 # 2915 # . prologue 2916 55/push-ebp 2917 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 2918 # . save registers 2919 50/push-eax 2920 51/push-ecx 2921 52/push-edx 2922 # var word-slice/ecx: slice 2923 68/push 0/imm32/end 2924 68/push 0/imm32/start 2925 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 2926 # rewind-stream(line) 2927 # . . push args 2928 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2929 # . . call 2930 e8/call rewind-stream/disp32 2931 # . . discard args 2932 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 2933 +-- 26 lines: #? # dump line -------------------------------------------------------------------------------------------------------------------------------------------------------- 2959 $emit-disp:loop: 2960 # next-word(line, word-slice) 2961 # . . push args 2962 51/push-ecx 2963 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2964 # . . call 2965 e8/call next-word/disp32 2966 # . . discard args 2967 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 2968 +-- 40 lines: #? # dump word-slice -------------------------------------------------------------------------------------------------------------------------------------------------- 3008 $emit-disp:check0: 3009 # if (slice-empty?(word-slice)) break 3010 # . eax = slice-empty?(word-slice) 3011 # . . push args 3012 51/push-ecx 3013 # . . call 3014 e8/call slice-empty?/disp32 3015 # . . discard args 3016 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3017 # . if (eax != false) pass through 3018 3d/compare-eax-and 0/imm32/false 3019 0f 85/jump-if-!= $emit-disp:break/disp32 3020 $emit-disp:check1: 3021 # if (slice-starts-with?(word-slice, "#")) break 3022 # . var start/edx: (addr byte) = word-slice->start 3023 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx 3024 # . var c/eax: byte = *start 3025 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 3026 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL 3027 # . if (c == '#') break 3028 3d/compare-eax-and 0x23/imm32/hash 3029 0f 84/jump-if-= $emit-disp:break/disp32 3030 $emit-disp:check-for-disp32: 3031 # if (has-metadata?(word-slice, "disp32")) 3032 # . eax = has-metadata?(ecx, "disp32") 3033 # . . push args 3034 68/push "disp32"/imm32 3035 51/push-ecx 3036 # . . call 3037 e8/call has-metadata?/disp32 3038 # . . discard args 3039 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3040 # . if (eax == false) goto next check 3041 3d/compare-eax-and 0/imm32/false 3042 74/jump-if-= $emit-disp:check-for-disp16/disp8 3043 $emit-disp:disp32: 3044 # emit(out, word-slice, 4) 3045 # . . push args 3046 68/push 4/imm32 3047 51/push-ecx 3048 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 3049 # . . call 3050 e8/call emit/disp32 3051 # . . discard args 3052 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3053 # break 3054 e9/jump $emit-disp:break/disp32 3055 $emit-disp:check-for-disp16: 3056 # else if (has-metadata?(word-slice, "disp16")) 3057 # . eax = has-metadata?(ecx, "disp16") 3058 # . . push args 3059 68/push "disp16"/imm32 3060 51/push-ecx 3061 # . . call 3062 e8/call has-metadata?/disp32 3063 # . . discard args 3064 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3065 # . if (eax == false) goto next check 3066 3d/compare-eax-and 0/imm32/false 3067 74/jump-if-= $emit-disp:check-for-disp8/disp8 3068 $emit-disp:disp16: 3069 # emit(out, word-slice, 2) 3070 # . . push args 3071 68/push 2/imm32 3072 51/push-ecx 3073 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 3074 # . . call 3075 e8/call emit/disp32 3076 # . . discard args 3077 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3078 # break 3079 e9/jump $emit-disp:break/disp32 3080 $emit-disp:check-for-disp8: 3081 # if (has-metadata?(word-slice, "disp8")) 3082 # . eax = has-metadata?(ecx, "disp8") 3083 # . . push args 3084 68/push "disp8"/imm32 3085 51/push-ecx 3086 # . . call 3087 e8/call has-metadata?/disp32 3088 # . . discard args 3089 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3090 # . if (eax == false) loop 3091 3d/compare-eax-and 0/imm32/false 3092 0f 84/jump-if-= $emit-disp:loop/disp32 3093 $emit-disp:disp8: 3094 # emit(out, word-slice, 1) 3095 # . . push args 3096 68/push 1/imm32 3097 51/push-ecx 3098 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 3099 # . . call 3100 e8/call emit/disp32 3101 # . . discard args 3102 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3103 # break 3104 $emit-disp:break: 3105 # . restore locals 3106 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3107 # . restore registers 3108 5a/pop-to-edx 3109 59/pop-to-ecx 3110 58/pop-to-eax 3111 # . epilogue 3112 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3113 5d/pop-to-ebp 3114 c3/return 3115 3116 emit-imm: # line: (addr stream byte), out: (addr buffered-file) 3117 # pseudocode: 3118 # rewind-stream(line) 3119 # var word-slice: slice 3120 # while true 3121 # word-slice = next-word(line) 3122 # if (slice-empty?(word-slice)) break 3123 # if (slice-starts-with?(word-slice, "#")) break 3124 # if has-metadata?(word-slice, "imm32") 3125 # emit(out, word-slice, 4) 3126 # break 3127 # if has-metadata?(word-slice, "imm16") 3128 # emit(out, word-slice, 2) 3129 # break 3130 # if has-metadata?(word-slice, "imm8") 3131 # emit(out, word-slice, 1) 3132 # break 3133 # 3134 # . prologue 3135 55/push-ebp 3136 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3137 # . save registers 3138 50/push-eax 3139 51/push-ecx 3140 52/push-edx 3141 # var word-slice/ecx: slice 3142 68/push 0/imm32/end 3143 68/push 0/imm32/start 3144 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 3145 # rewind-stream(line) 3146 # . . push args 3147 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 3148 # . . call 3149 e8/call rewind-stream/disp32 3150 # . . discard args 3151 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3152 +-- 26 lines: #? # dump line -------------------------------------------------------------------------------------------------------------------------------------------------------- 3178 $emit-imm:loop: 3179 # next-word(line, word-slice) 3180 # . . push args 3181 51/push-ecx 3182 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 3183 # . . call 3184 e8/call next-word/disp32 3185 # . . discard args 3186 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3187 +-- 40 lines: #? # dump word-slice -------------------------------------------------------------------------------------------------------------------------------------------------- 3227 $emit-imm:check0: 3228 # if (slice-empty?(word-slice)) break 3229 # . eax = slice-empty?(word-slice) 3230 # . . push args 3231 51/push-ecx 3232 # . . call 3233 e8/call slice-empty?/disp32 3234 # . . discard args 3235 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3236 # . if (eax != false) pass through 3237 3d/compare-eax-and 0/imm32/false 3238 0f 85/jump-if-!= $emit-imm:break/disp32 3239 $emit-imm:check1: 3240 # if (slice-starts-with?(word-slice, "#")) break 3241 # . var start/edx: (addr byte) = slice->start 3242 8b/copy 0/mod/indirect 1/rm32/ecx . . . 2/r32/edx . . # copy *ecx to edx 3243 # . var c/eax: byte = *start 3244 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 3245 8a/copy-byte 0/mod/indirect 2/rm32/edx . . . 0/r32/AL . . # copy byte at *edx to AL 3246 # . if (c == '#') break 3247 3d/compare-eax-and 0x23/imm32/hash 3248 0f 84/jump-if-= $emit-imm:break/disp32 3249 $emit-imm:check-for-imm32: 3250 # if (has-metadata?(word-slice, "imm32")) 3251 # . eax = has-metadata?(ecx, "imm32") 3252 # . . push args 3253 68/push "imm32"/imm32 3254 51/push-ecx 3255 # . . call 3256 e8/call has-metadata?/disp32 3257 # . . discard args 3258 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3259 # . if (eax == false) goto next check 3260 3d/compare-eax-and 0/imm32/false 3261 74/jump-if-= $emit-imm:check-for-imm16/disp8 3262 $emit-imm:imm32: 3263 # emit(out, word-slice, 4) 3264 # . . push args 3265 68/push 4/imm32 3266 51/push-ecx 3267 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 3268 # . . call 3269 e8/call emit/disp32 3270 # . . discard args 3271 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3272 # break 3273 e9/jump $emit-imm:break/disp32 3274 $emit-imm:check-for-imm16: 3275 # if (has-metadata?(word-slice, "imm16")) 3276 # . eax = has-metadata?(ecx, "imm16") 3277 # . . push args 3278 68/push "imm16"/imm32 3279 51/push-ecx 3280 # . . call 3281 e8/call has-metadata?/disp32 3282 # . . discard args 3283 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3284 # . if (eax == false) goto next check 3285 3d/compare-eax-and 0/imm32/false 3286 74/jump-if-= $emit-imm:check-for-imm8/disp8 3287 $emit-imm:imm16: 3288 # emit(out, word-slice, 2) 3289 # . . push args 3290 68/push 2/imm32 3291 51/push-ecx 3292 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 3293 # . . call 3294 e8/call emit/disp32 3295 # . . discard args 3296 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3297 # break 3298 e9/jump $emit-imm:break/disp32 3299 $emit-imm:check-for-imm8: 3300 # if (has-metadata?(word-slice, "imm8")) 3301 # . eax = has-metadata?(ecx, "imm8") 3302 # . . push args 3303 68/push "imm8"/imm32 3304 51/push-ecx 3305 # . . call 3306 e8/call has-metadata?/disp32 3307 # . . discard args 3308 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3309 # . if (eax == false) loop 3310 3d/compare-eax-and 0/imm32/false 3311 0f 84/jump-if-= $emit-imm:loop/disp32 3312 $emit-imm:imm8: 3313 # emit(out, word-slice, 1) 3314 # . . push args 3315 68/push 1/imm32 3316 51/push-ecx 3317 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 3318 # . . call 3319 e8/call emit/disp32 3320 # . . discard args 3321 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3322 # break 3323 $emit-imm:break: 3324 # . restore locals 3325 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3326 # . restore registers 3327 5a/pop-to-edx 3328 59/pop-to-ecx 3329 58/pop-to-eax 3330 # . epilogue 3331 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3332 5d/pop-to-ebp 3333 c3/return 3334 3335 emit-line-in-comment: # line: (addr stream byte), out: (addr buffered-file) 3336 # . prologue 3337 55/push-ebp 3338 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3339 # write-buffered(out, " # ") 3340 # . . push args 3341 68/push " # "/imm32 3342 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 3343 # . . call 3344 e8/call write-buffered/disp32 3345 # . . discard args 3346 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3347 # write-stream-data(out, line) 3348 # . . push args 3349 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 3350 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 3351 # . . call 3352 e8/call write-stream-data/disp32 3353 # . . discard args 3354 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3355 $emit-line-in-comment:end: 3356 # . epilogue 3357 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3358 5d/pop-to-ebp 3359 c3/return 3360 3361 test-convert-instruction-passes-comments-through: 3362 # if a line starts with '#', pass it along unchanged 3363 # . prologue 3364 55/push-ebp 3365 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3366 # setup 3367 # . clear-stream(_test-input-stream) 3368 # . . push args 3369 68/push _test-input-stream/imm32 3370 # . . call 3371 e8/call clear-stream/disp32 3372 # . . discard args 3373 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3374 # . clear-stream(_test-output-stream) 3375 # . . push args 3376 68/push _test-output-stream/imm32 3377 # . . call 3378 e8/call clear-stream/disp32 3379 # . . discard args 3380 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3381 # . clear-stream($_test-output-buffered-file->buffer) 3382 # . . push args 3383 68/push $_test-output-buffered-file->buffer/imm32 3384 # . . call 3385 e8/call clear-stream/disp32 3386 # . . discard args 3387 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3388 # initialize input 3389 # . write(_test-input-stream, "# abcd") 3390 # . . push args 3391 68/push "# abcd"/imm32 3392 68/push _test-input-stream/imm32 3393 # . . call 3394 e8/call write/disp32 3395 # . . discard args 3396 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3397 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3398 # . . push args 3399 68/push _test-output-buffered-file/imm32 3400 68/push _test-input-stream/imm32 3401 # . . call 3402 e8/call convert-instruction/disp32 3403 # . . discard args 3404 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3405 # check that the line just passed through 3406 # . flush(_test-output-buffered-file) 3407 # . . push args 3408 68/push _test-output-buffered-file/imm32 3409 # . . call 3410 e8/call flush/disp32 3411 # . . discard args 3412 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3413 # . check-stream-equal(_test-output-stream, "# abcd", msg) 3414 # . . push args 3415 68/push "F - test-convert-instruction-passes-comments-through"/imm32 3416 68/push "# abcd"/imm32 3417 68/push _test-output-stream/imm32 3418 # . . call 3419 e8/call check-stream-equal/disp32 3420 # . . discard args 3421 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3422 # . epilogue 3423 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3424 5d/pop-to-ebp 3425 c3/return 3426 3427 test-convert-instruction-passes-labels-through: 3428 # if the first word ends with ':', pass along the entire line unchanged 3429 # . prologue 3430 55/push-ebp 3431 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3432 # setup 3433 # . clear-stream(_test-input-stream) 3434 # . . push args 3435 68/push _test-input-stream/imm32 3436 # . . call 3437 e8/call clear-stream/disp32 3438 # . . discard args 3439 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3440 # . clear-stream(_test-output-stream) 3441 # . . push args 3442 68/push _test-output-stream/imm32 3443 # . . call 3444 e8/call clear-stream/disp32 3445 # . . discard args 3446 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3447 # . clear-stream($_test-output-buffered-file->buffer) 3448 # . . push args 3449 68/push $_test-output-buffered-file->buffer/imm32 3450 # . . call 3451 e8/call clear-stream/disp32 3452 # . . discard args 3453 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3454 # initialize input 3455 # . write(_test-input-stream, "ab: # cd") 3456 # . . push args 3457 68/push "ab: # cd"/imm32 3458 68/push _test-input-stream/imm32 3459 # . . call 3460 e8/call write/disp32 3461 # . . discard args 3462 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3463 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3464 # . . push args 3465 68/push _test-output-buffered-file/imm32 3466 68/push _test-input-stream/imm32 3467 # . . call 3468 e8/call convert-instruction/disp32 3469 # . . discard args 3470 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3471 # check that the line just passed through 3472 # . flush(_test-output-buffered-file) 3473 # . . push args 3474 68/push _test-output-buffered-file/imm32 3475 # . . call 3476 e8/call flush/disp32 3477 # . . discard args 3478 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3479 # . check-stream-equal(_test-output-stream, "ab: # cd", msg) 3480 # . . push args 3481 68/push "F - test-convert-instruction-passes-labels-through"/imm32 3482 68/push "ab: # cd"/imm32 3483 68/push _test-output-stream/imm32 3484 # . . call 3485 e8/call check-stream-equal/disp32 3486 # . . discard args 3487 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3488 # . epilogue 3489 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3490 5d/pop-to-ebp 3491 c3/return 3492 3493 test-convert-instruction-handles-single-opcode: 3494 # if the instruction consists of a single opcode, strip its metadata and pass it along 3495 # . prologue 3496 55/push-ebp 3497 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3498 # setup 3499 # . clear-stream(_test-input-stream) 3500 # . . push args 3501 68/push _test-input-stream/imm32 3502 # . . call 3503 e8/call clear-stream/disp32 3504 # . . discard args 3505 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3506 # . clear-stream(_test-output-stream) 3507 # . . push args 3508 68/push _test-output-stream/imm32 3509 # . . call 3510 e8/call clear-stream/disp32 3511 # . . discard args 3512 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3513 # . clear-stream($_test-output-buffered-file->buffer) 3514 # . . push args 3515 68/push $_test-output-buffered-file->buffer/imm32 3516 # . . call 3517 e8/call clear-stream/disp32 3518 # . . discard args 3519 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3520 # initialize input 3521 # . write(_test-input-stream, "ab/cd # comment") 3522 # . . push args 3523 68/push "ab/cd # comment"/imm32 3524 68/push _test-input-stream/imm32 3525 # . . call 3526 e8/call write/disp32 3527 # . . discard args 3528 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3529 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3530 # . . push args 3531 68/push _test-output-buffered-file/imm32 3532 68/push _test-input-stream/imm32 3533 # . . call 3534 e8/call convert-instruction/disp32 3535 # . . discard args 3536 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3537 # check output 3538 # . flush(_test-output-buffered-file) 3539 # . . push args 3540 68/push _test-output-buffered-file/imm32 3541 # . . call 3542 e8/call flush/disp32 3543 # . . discard args 3544 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3545 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 3571 # . check-stream-equal(_test-output-stream, "ab # ab/cd # comment", msg) 3572 # . . push args 3573 68/push "F - test-convert-instruction-handles-single-opcode"/imm32 3574 68/push "ab # ab/cd # comment"/imm32 3575 68/push _test-output-stream/imm32 3576 # . . call 3577 e8/call check-stream-equal/disp32 3578 # . . discard args 3579 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3580 # . epilogue 3581 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3582 5d/pop-to-ebp 3583 c3/return 3584 3585 test-convert-instruction-handles-0f-opcode: 3586 # if the instruction starts with 0f opcode, include a second opcode 3587 # . prologue 3588 55/push-ebp 3589 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3590 # setup 3591 # . clear-stream(_test-input-stream) 3592 # . . push args 3593 68/push _test-input-stream/imm32 3594 # . . call 3595 e8/call clear-stream/disp32 3596 # . . discard args 3597 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3598 # . clear-stream(_test-output-stream) 3599 # . . push args 3600 68/push _test-output-stream/imm32 3601 # . . call 3602 e8/call clear-stream/disp32 3603 # . . discard args 3604 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3605 # . clear-stream($_test-output-buffered-file->buffer) 3606 # . . push args 3607 68/push $_test-output-buffered-file->buffer/imm32 3608 # . . call 3609 e8/call clear-stream/disp32 3610 # . . discard args 3611 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3612 # initialize input 3613 # . write(_test-input-stream, "0f/m1 ab/m2 # comment") 3614 # . . push args 3615 68/push "0f/m1 ab/m2 # comment"/imm32 3616 68/push _test-input-stream/imm32 3617 # . . call 3618 e8/call write/disp32 3619 # . . discard args 3620 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3621 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3622 # . . push args 3623 68/push _test-output-buffered-file/imm32 3624 68/push _test-input-stream/imm32 3625 # . . call 3626 e8/call convert-instruction/disp32 3627 # . . discard args 3628 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3629 # check output 3630 # . flush(_test-output-buffered-file) 3631 # . . push args 3632 68/push _test-output-buffered-file/imm32 3633 # . . call 3634 e8/call flush/disp32 3635 # . . discard args 3636 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3637 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 3663 # . check-stream-equal(_test-output-stream, "0f ab # 0f/m1 ab/m2 # comment", msg) 3664 # . . push args 3665 68/push "F - test-convert-instruction-handles-0f-opcode"/imm32 3666 68/push "0f ab # 0f/m1 ab/m2 # comment"/imm32 3667 68/push _test-output-stream/imm32 3668 # . . call 3669 e8/call check-stream-equal/disp32 3670 # . . discard args 3671 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3672 # . epilogue 3673 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3674 5d/pop-to-ebp 3675 c3/return 3676 3677 test-convert-instruction-handles-f2-opcode: 3678 # if the instruction starts with f2 opcode, include a second opcode 3679 # . prologue 3680 55/push-ebp 3681 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3682 # setup 3683 # . clear-stream(_test-input-stream) 3684 # . . push args 3685 68/push _test-input-stream/imm32 3686 # . . call 3687 e8/call clear-stream/disp32 3688 # . . discard args 3689 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3690 # . clear-stream(_test-output-stream) 3691 # . . push args 3692 68/push _test-output-stream/imm32 3693 # . . call 3694 e8/call clear-stream/disp32 3695 # . . discard args 3696 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3697 # . clear-stream($_test-output-buffered-file->buffer) 3698 # . . push args 3699 68/push $_test-output-buffered-file->buffer/imm32 3700 # . . call 3701 e8/call clear-stream/disp32 3702 # . . discard args 3703 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3704 # initialize input 3705 # . write(_test-input-stream, "f2/m1 ab/m2 # comment") 3706 # . . push args 3707 68/push "f2/m1 ab/m2 # comment"/imm32 3708 68/push _test-input-stream/imm32 3709 # . . call 3710 e8/call write/disp32 3711 # . . discard args 3712 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3713 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3714 # . . push args 3715 68/push _test-output-buffered-file/imm32 3716 68/push _test-input-stream/imm32 3717 # . . call 3718 e8/call convert-instruction/disp32 3719 # . . discard args 3720 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3721 # check output 3722 # . flush(_test-output-buffered-file) 3723 # . . push args 3724 68/push _test-output-buffered-file/imm32 3725 # . . call 3726 e8/call flush/disp32 3727 # . . discard args 3728 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3729 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 3755 # . check-stream-equal(_test-output-stream, "f2 ab # f2/m1 ab/m2 # comment", msg) 3756 # . . push args 3757 68/push "F - test-convert-instruction-handles-f2-opcode"/imm32 3758 68/push "f2 ab # f2/m1 ab/m2 # comment"/imm32 3759 68/push _test-output-stream/imm32 3760 # . . call 3761 e8/call check-stream-equal/disp32 3762 # . . discard args 3763 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3764 # . epilogue 3765 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3766 5d/pop-to-ebp 3767 c3/return 3768 3769 test-convert-instruction-handles-f3-opcode: 3770 # if the instruction starts with f3 opcode, include a second opcode 3771 # . prologue 3772 55/push-ebp 3773 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3774 # setup 3775 # . clear-stream(_test-input-stream) 3776 # . . push args 3777 68/push _test-input-stream/imm32 3778 # . . call 3779 e8/call clear-stream/disp32 3780 # . . discard args 3781 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3782 # . clear-stream(_test-output-stream) 3783 # . . push args 3784 68/push _test-output-stream/imm32 3785 # . . call 3786 e8/call clear-stream/disp32 3787 # . . discard args 3788 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3789 # . clear-stream($_test-output-buffered-file->buffer) 3790 # . . push args 3791 68/push $_test-output-buffered-file->buffer/imm32 3792 # . . call 3793 e8/call clear-stream/disp32 3794 # . . discard args 3795 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3796 # initialize input 3797 # . write(_test-input-stream, "f3/m1 ab/m2 # comment") 3798 # . . push args 3799 68/push "f3/m1 ab/m2 # comment"/imm32 3800 68/push _test-input-stream/imm32 3801 # . . call 3802 e8/call write/disp32 3803 # . . discard args 3804 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3805 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3806 # . . push args 3807 68/push _test-output-buffered-file/imm32 3808 68/push _test-input-stream/imm32 3809 # . . call 3810 e8/call convert-instruction/disp32 3811 # . . discard args 3812 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3813 # check output 3814 # . flush(_test-output-buffered-file) 3815 # . . push args 3816 68/push _test-output-buffered-file/imm32 3817 # . . call 3818 e8/call flush/disp32 3819 # . . discard args 3820 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3821 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 3847 # . check-stream-equal(_test-output-stream, "f3 ab # f3/m1 ab/m2 # comment", msg) 3848 # . . push args 3849 68/push "F - test-convert-instruction-handles-f3-opcode"/imm32 3850 68/push "f3 ab # f3/m1 ab/m2 # comment"/imm32 3851 68/push _test-output-stream/imm32 3852 # . . call 3853 e8/call check-stream-equal/disp32 3854 # . . discard args 3855 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3856 # . epilogue 3857 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3858 5d/pop-to-ebp 3859 c3/return 3860 3861 test-convert-instruction-handles-f2-0f-opcode: 3862 # if the instruction starts with f2 0f opcode, include a second opcode 3863 # . prologue 3864 55/push-ebp 3865 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3866 # setup 3867 # . clear-stream(_test-input-stream) 3868 # . . push args 3869 68/push _test-input-stream/imm32 3870 # . . call 3871 e8/call clear-stream/disp32 3872 # . . discard args 3873 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3874 # . clear-stream(_test-output-stream) 3875 # . . push args 3876 68/push _test-output-stream/imm32 3877 # . . call 3878 e8/call clear-stream/disp32 3879 # . . discard args 3880 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3881 # . clear-stream($_test-output-buffered-file->buffer) 3882 # . . push args 3883 68/push $_test-output-buffered-file->buffer/imm32 3884 # . . call 3885 e8/call clear-stream/disp32 3886 # . . discard args 3887 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3888 # initialize input 3889 # . write(_test-input-stream, "f2/m1 0f/m2 ab/m3 # comment") 3890 # . . push args 3891 68/push "f2/m1 0f/m2 ab/m3 # comment"/imm32 3892 68/push _test-input-stream/imm32 3893 # . . call 3894 e8/call write/disp32 3895 # . . discard args 3896 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3897 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3898 # . . push args 3899 68/push _test-output-buffered-file/imm32 3900 68/push _test-input-stream/imm32 3901 # . . call 3902 e8/call convert-instruction/disp32 3903 # . . discard args 3904 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3905 # check output 3906 # . flush(_test-output-buffered-file) 3907 # . . push args 3908 68/push _test-output-buffered-file/imm32 3909 # . . call 3910 e8/call flush/disp32 3911 # . . discard args 3912 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3913 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 3939 # . check-stream-equal(_test-output-stream, "f2 0f ab # f2/m1 0f/m2 ab/m3 # comment", msg) 3940 # . . push args 3941 68/push "F - test-convert-instruction-handles-f2-0f-opcode"/imm32 3942 68/push "f2 0f ab # f2/m1 0f/m2 ab/m3 # comment"/imm32 3943 68/push _test-output-stream/imm32 3944 # . . call 3945 e8/call check-stream-equal/disp32 3946 # . . discard args 3947 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 3948 # . epilogue 3949 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 3950 5d/pop-to-ebp 3951 c3/return 3952 3953 test-convert-instruction-handles-f3-0f-opcode: 3954 # if the instruction starts with f3 0f opcode, include a second opcode 3955 # . prologue 3956 55/push-ebp 3957 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 3958 # setup 3959 # . clear-stream(_test-input-stream) 3960 # . . push args 3961 68/push _test-input-stream/imm32 3962 # . . call 3963 e8/call clear-stream/disp32 3964 # . . discard args 3965 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3966 # . clear-stream(_test-output-stream) 3967 # . . push args 3968 68/push _test-output-stream/imm32 3969 # . . call 3970 e8/call clear-stream/disp32 3971 # . . discard args 3972 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3973 # . clear-stream($_test-output-buffered-file->buffer) 3974 # . . push args 3975 68/push $_test-output-buffered-file->buffer/imm32 3976 # . . call 3977 e8/call clear-stream/disp32 3978 # . . discard args 3979 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 3980 # initialize input 3981 # . write(_test-input-stream, "f3/m1 0f/m2 ab/m3 # comment") 3982 # . . push args 3983 68/push "f3/m1 0f/m2 ab/m3 # comment"/imm32 3984 68/push _test-input-stream/imm32 3985 # . . call 3986 e8/call write/disp32 3987 # . . discard args 3988 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3989 # convert-instruction(_test-input-stream, _test-output-buffered-file) 3990 # . . push args 3991 68/push _test-output-buffered-file/imm32 3992 68/push _test-input-stream/imm32 3993 # . . call 3994 e8/call convert-instruction/disp32 3995 # . . discard args 3996 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 3997 # check output 3998 # . flush(_test-output-buffered-file) 3999 # . . push args 4000 68/push _test-output-buffered-file/imm32 4001 # . . call 4002 e8/call flush/disp32 4003 # . . discard args 4004 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4005 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4031 # . check-stream-equal(_test-output-stream, "f3 0f ab # f3/m1 0f/m2 ab/m3 # comment", msg) 4032 # . . push args 4033 68/push "F - test-convert-instruction-handles-f3-0f-opcode"/imm32 4034 68/push "f3 0f ab # f3/m1 0f/m2 ab/m3 # comment"/imm32 4035 68/push _test-output-stream/imm32 4036 # . . call 4037 e8/call check-stream-equal/disp32 4038 # . . discard args 4039 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4040 # . epilogue 4041 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4042 5d/pop-to-ebp 4043 c3/return 4044 4045 test-convert-instruction-handles-unused-opcodes: 4046 # if the instruction doesn't start with f2, f3 or 0f, don't include other opcodes 4047 # . prologue 4048 55/push-ebp 4049 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4050 # setup 4051 # . clear-stream(_test-input-stream) 4052 # . . push args 4053 68/push _test-input-stream/imm32 4054 # . . call 4055 e8/call clear-stream/disp32 4056 # . . discard args 4057 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4058 # . clear-stream(_test-output-stream) 4059 # . . push args 4060 68/push _test-output-stream/imm32 4061 # . . call 4062 e8/call clear-stream/disp32 4063 # . . discard args 4064 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4065 # . clear-stream($_test-output-buffered-file->buffer) 4066 # . . push args 4067 68/push $_test-output-buffered-file->buffer/imm32 4068 # . . call 4069 e8/call clear-stream/disp32 4070 # . . discard args 4071 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4072 # initialize input 4073 # . write(_test-input-stream, "ab/m1 cd/m2 # comment") 4074 # . . push args 4075 68/push "ab/m1 cd/m2 # comment"/imm32 4076 68/push _test-input-stream/imm32 4077 # . . call 4078 e8/call write/disp32 4079 # . . discard args 4080 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4081 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4082 # . . push args 4083 68/push _test-output-buffered-file/imm32 4084 68/push _test-input-stream/imm32 4085 # . . call 4086 e8/call convert-instruction/disp32 4087 # . . discard args 4088 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4089 # check output 4090 # . flush(_test-output-buffered-file) 4091 # . . push args 4092 68/push _test-output-buffered-file/imm32 4093 # . . call 4094 e8/call flush/disp32 4095 # . . discard args 4096 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4097 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4123 # . check-stream-equal(_test-output-stream, "ab # f3/m1 0f/m2 ab/m3 # comment", msg) 4124 # . . push args 4125 68/push "F - test-convert-instruction-handles-unused-opcodes"/imm32 4126 68/push "ab # ab/m1 cd/m2 # comment"/imm32 4127 68/push _test-output-stream/imm32 4128 # . . call 4129 e8/call check-stream-equal/disp32 4130 # . . discard args 4131 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4132 # . epilogue 4133 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4134 5d/pop-to-ebp 4135 c3/return 4136 4137 test-convert-instruction-handles-unused-second-opcodes: 4138 # if the second opcode isn't 0f, don't include further opcodes 4139 # . prologue 4140 55/push-ebp 4141 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4142 # setup 4143 # . clear-stream(_test-input-stream) 4144 # . . push args 4145 68/push _test-input-stream/imm32 4146 # . . call 4147 e8/call clear-stream/disp32 4148 # . . discard args 4149 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4150 # . clear-stream(_test-output-stream) 4151 # . . push args 4152 68/push _test-output-stream/imm32 4153 # . . call 4154 e8/call clear-stream/disp32 4155 # . . discard args 4156 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4157 # . clear-stream($_test-output-buffered-file->buffer) 4158 # . . push args 4159 68/push $_test-output-buffered-file->buffer/imm32 4160 # . . call 4161 e8/call clear-stream/disp32 4162 # . . discard args 4163 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4164 # initialize input 4165 # . write(_test-input-stream, "f2/m1 ab/m2 cd/m3 # comment") 4166 # . . push args 4167 68/push "f2/m1 ab/m2 cd/m3 # comment"/imm32 4168 68/push _test-input-stream/imm32 4169 # . . call 4170 e8/call write/disp32 4171 # . . discard args 4172 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4173 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4174 # . . push args 4175 68/push _test-output-buffered-file/imm32 4176 68/push _test-input-stream/imm32 4177 # . . call 4178 e8/call convert-instruction/disp32 4179 # . . discard args 4180 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4181 # check output 4182 # . flush(_test-output-buffered-file) 4183 # . . push args 4184 68/push _test-output-buffered-file/imm32 4185 # . . call 4186 e8/call flush/disp32 4187 # . . discard args 4188 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4189 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4215 # . check-stream-equal(_test-output-stream, "f2 ab # f2/m1 ab/m2 cd/m3 # comment", msg) 4216 # . . push args 4217 68/push "F - test-convert-instruction-handles-unused-second-opcodes"/imm32 4218 68/push "f2 ab # f2/m1 ab/m2 cd/m3 # comment"/imm32 4219 68/push _test-output-stream/imm32 4220 # . . call 4221 e8/call check-stream-equal/disp32 4222 # . . discard args 4223 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4224 # . epilogue 4225 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4226 5d/pop-to-ebp 4227 c3/return 4228 4229 test-convert-instruction-handles-unused-second-opcodes-2: 4230 # if the second opcode isn't 0f, don't include further opcodes 4231 # . prologue 4232 55/push-ebp 4233 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4234 # setup 4235 # . clear-stream(_test-input-stream) 4236 # . . push args 4237 68/push _test-input-stream/imm32 4238 # . . call 4239 e8/call clear-stream/disp32 4240 # . . discard args 4241 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4242 # . clear-stream(_test-output-stream) 4243 # . . push args 4244 68/push _test-output-stream/imm32 4245 # . . call 4246 e8/call clear-stream/disp32 4247 # . . discard args 4248 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4249 # . clear-stream($_test-output-buffered-file->buffer) 4250 # . . push args 4251 68/push $_test-output-buffered-file->buffer/imm32 4252 # . . call 4253 e8/call clear-stream/disp32 4254 # . . discard args 4255 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4256 # initialize input 4257 # . write(_test-input-stream, "f3/m1 ab/m2 cd/m3 # comment") 4258 # . . push args 4259 68/push "f3/m1 ab/m2 cd/m3 # comment"/imm32 4260 68/push _test-input-stream/imm32 4261 # . . call 4262 e8/call write/disp32 4263 # . . discard args 4264 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4265 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4266 # . . push args 4267 68/push _test-output-buffered-file/imm32 4268 68/push _test-input-stream/imm32 4269 # . . call 4270 e8/call convert-instruction/disp32 4271 # . . discard args 4272 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4273 # check output 4274 # . flush(_test-output-buffered-file) 4275 # . . push args 4276 68/push _test-output-buffered-file/imm32 4277 # . . call 4278 e8/call flush/disp32 4279 # . . discard args 4280 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4281 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4307 # . check-stream-equal(_test-output-stream, "f3 ab # f3/m1 ab/m2 cd/m3 # comment", msg) 4308 # . . push args 4309 68/push "F - test-convert-instruction-handles-unused-second-opcodes"/imm32 4310 68/push "f3 ab # f3/m1 ab/m2 cd/m3 # comment"/imm32 4311 68/push _test-output-stream/imm32 4312 # . . call 4313 e8/call check-stream-equal/disp32 4314 # . . discard args 4315 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4316 # . epilogue 4317 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4318 5d/pop-to-ebp 4319 c3/return 4320 4321 test-convert-instruction-emits-modrm-byte: 4322 # pack mod, rm32 and r32 operands into ModR/M byte 4323 # . prologue 4324 55/push-ebp 4325 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4326 # setup 4327 # . clear-stream(_test-input-stream) 4328 # . . push args 4329 68/push _test-input-stream/imm32 4330 # . . call 4331 e8/call clear-stream/disp32 4332 # . . discard args 4333 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4334 # . clear-stream(_test-output-stream) 4335 # . . push args 4336 68/push _test-output-stream/imm32 4337 # . . call 4338 e8/call clear-stream/disp32 4339 # . . discard args 4340 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4341 # . clear-stream($_test-output-buffered-file->buffer) 4342 # . . push args 4343 68/push $_test-output-buffered-file->buffer/imm32 4344 # . . call 4345 e8/call clear-stream/disp32 4346 # . . discard args 4347 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4348 # initialize input 4349 # . write(_test-input-stream, "8b/copy 0/mod 0/rm32 1/r32") 4350 # . . push args 4351 68/push "8b/copy 0/mod 0/rm32 1/r32"/imm32 4352 68/push _test-input-stream/imm32 4353 # . . call 4354 e8/call write/disp32 4355 # . . discard args 4356 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4357 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4358 # . . push args 4359 68/push _test-output-buffered-file/imm32 4360 68/push _test-input-stream/imm32 4361 # . . call 4362 e8/call convert-instruction/disp32 4363 # . . discard args 4364 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4365 # check output 4366 # . flush(_test-output-buffered-file) 4367 # . . push args 4368 68/push _test-output-buffered-file/imm32 4369 # . . call 4370 e8/call flush/disp32 4371 # . . discard args 4372 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4373 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4399 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/mod 0/rm32 1/r32", msg) 4400 # . . push args 4401 68/push "F - test-convert-instruction-emits-modrm-byte"/imm32 4402 68/push "8b 08 # 8b/copy 0/mod 0/rm32 1/r32"/imm32 4403 68/push _test-output-stream/imm32 4404 # . . call 4405 e8/call check-stream-equal/disp32 4406 # . . discard args 4407 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4408 # . epilogue 4409 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4410 5d/pop-to-ebp 4411 c3/return 4412 4413 test-convert-instruction-emits-modrm-byte-with-non-zero-mod: 4414 # . prologue 4415 55/push-ebp 4416 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4417 # setup 4418 # . clear-stream(_test-input-stream) 4419 # . . push args 4420 68/push _test-input-stream/imm32 4421 # . . call 4422 e8/call clear-stream/disp32 4423 # . . discard args 4424 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4425 # . clear-stream(_test-output-stream) 4426 # . . push args 4427 68/push _test-output-stream/imm32 4428 # . . call 4429 e8/call clear-stream/disp32 4430 # . . discard args 4431 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4432 # . clear-stream($_test-output-buffered-file->buffer) 4433 # . . push args 4434 68/push $_test-output-buffered-file->buffer/imm32 4435 # . . call 4436 e8/call clear-stream/disp32 4437 # . . discard args 4438 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4439 # initialize input 4440 # . write(_test-input-stream, "01/add 3/mod/direct 3/rm32/ebx 1/r32/ecx") 4441 # . . push args 4442 68/push "01/add 3/mod/direct 3/rm32/ebx 1/r32/ecx"/imm32 4443 68/push _test-input-stream/imm32 4444 # . . call 4445 e8/call write/disp32 4446 # . . discard args 4447 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4448 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4449 # . . push args 4450 68/push _test-output-buffered-file/imm32 4451 68/push _test-input-stream/imm32 4452 # . . call 4453 e8/call convert-instruction/disp32 4454 # . . discard args 4455 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4456 # . flush(_test-output-buffered-file) 4457 # . . push args 4458 68/push _test-output-buffered-file/imm32 4459 # . . call 4460 e8/call flush/disp32 4461 # . . discard args 4462 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4463 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4489 # check output 4490 # . check-stream-equal(_test-output-stream, "# abcd", msg) 4491 # . . push args 4492 68/push "F - test-convert-instruction-foo"/imm32 4493 68/push "01 cb # 01/add 3/mod/direct 3/rm32/ebx 1/r32/ecx"/imm32 4494 68/push _test-output-stream/imm32 4495 # . . call 4496 e8/call check-stream-equal/disp32 4497 # . . discard args 4498 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4499 # . epilogue 4500 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4501 5d/pop-to-ebp 4502 c3/return 4503 4504 test-convert-instruction-emits-modrm-byte-from-subop: 4505 # pack mod, rm32 and subop operands into ModR/M byte 4506 # . prologue 4507 55/push-ebp 4508 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4509 # setup 4510 # . clear-stream(_test-input-stream) 4511 # . . push args 4512 68/push _test-input-stream/imm32 4513 # . . call 4514 e8/call clear-stream/disp32 4515 # . . discard args 4516 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4517 # . clear-stream(_test-output-stream) 4518 # . . push args 4519 68/push _test-output-stream/imm32 4520 # . . call 4521 e8/call clear-stream/disp32 4522 # . . discard args 4523 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4524 # . clear-stream($_test-output-buffered-file->buffer) 4525 # . . push args 4526 68/push $_test-output-buffered-file->buffer/imm32 4527 # . . call 4528 e8/call clear-stream/disp32 4529 # . . discard args 4530 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4531 # initialize input 4532 # . write(_test-input-stream, "ff 6/subop/push 0/mod 0/rm32") 4533 # . . push args 4534 68/push "ff 6/subop/push 0/mod 0/rm32"/imm32 4535 68/push _test-input-stream/imm32 4536 # . . call 4537 e8/call write/disp32 4538 # . . discard args 4539 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4540 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4541 # . . push args 4542 68/push _test-output-buffered-file/imm32 4543 68/push _test-input-stream/imm32 4544 # . . call 4545 e8/call convert-instruction/disp32 4546 # . . discard args 4547 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4548 # check output 4549 # . flush(_test-output-buffered-file) 4550 # . . push args 4551 68/push _test-output-buffered-file/imm32 4552 # . . call 4553 e8/call flush/disp32 4554 # . . discard args 4555 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4556 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4582 # . check-stream-equal(_test-output-stream, "ff 30 # ff 6/subop/push 0/mod 0/rm32", msg) 4583 # . . push args 4584 68/push "F - test-convert-instruction-emits-modrm-byte-from-subop"/imm32 4585 68/push "ff 30 # ff 6/subop/push 0/mod 0/rm32"/imm32 4586 68/push _test-output-stream/imm32 4587 # . . call 4588 e8/call check-stream-equal/disp32 4589 # . . discard args 4590 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4591 # . epilogue 4592 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4593 5d/pop-to-ebp 4594 c3/return 4595 4596 test-convert-instruction-emits-modrm-byte-with-missing-mod: 4597 # pack rm32 and r32 operands into ModR/M byte 4598 # . prologue 4599 55/push-ebp 4600 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4601 # setup 4602 # . clear-stream(_test-input-stream) 4603 # . . push args 4604 68/push _test-input-stream/imm32 4605 # . . call 4606 e8/call clear-stream/disp32 4607 # . . discard args 4608 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4609 # . clear-stream(_test-output-stream) 4610 # . . push args 4611 68/push _test-output-stream/imm32 4612 # . . call 4613 e8/call clear-stream/disp32 4614 # . . discard args 4615 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4616 # . clear-stream($_test-output-buffered-file->buffer) 4617 # . . push args 4618 68/push $_test-output-buffered-file->buffer/imm32 4619 # . . call 4620 e8/call clear-stream/disp32 4621 # . . discard args 4622 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4623 # initialize input 4624 # . write(_test-input-stream, "8b/copy 0/rm32 1/r32") 4625 # . . push args 4626 68/push "8b/copy 0/rm32 1/r32"/imm32 4627 68/push _test-input-stream/imm32 4628 # . . call 4629 e8/call write/disp32 4630 # . . discard args 4631 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4632 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4633 # . . push args 4634 68/push _test-output-buffered-file/imm32 4635 68/push _test-input-stream/imm32 4636 # . . call 4637 e8/call convert-instruction/disp32 4638 # . . discard args 4639 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4640 # check output 4641 # . flush(_test-output-buffered-file) 4642 # . . push args 4643 68/push _test-output-buffered-file/imm32 4644 # . . call 4645 e8/call flush/disp32 4646 # . . discard args 4647 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4648 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4674 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/rm32 1/r32", msg) 4675 # . . push args 4676 68/push "F - test-convert-instruction-emits-modrm-byte-with-missing-mod"/imm32 4677 68/push "8b 08 # 8b/copy 0/rm32 1/r32"/imm32 4678 68/push _test-output-stream/imm32 4679 # . . call 4680 e8/call check-stream-equal/disp32 4681 # . . discard args 4682 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4683 # . epilogue 4684 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4685 5d/pop-to-ebp 4686 c3/return 4687 4688 test-convert-instruction-emits-modrm-byte-with-missing-rm32: 4689 # pack mod and r32 operands into ModR/M byte 4690 # . prologue 4691 55/push-ebp 4692 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4693 # setup 4694 # . clear-stream(_test-input-stream) 4695 # . . push args 4696 68/push _test-input-stream/imm32 4697 # . . call 4698 e8/call clear-stream/disp32 4699 # . . discard args 4700 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4701 # . clear-stream(_test-output-stream) 4702 # . . push args 4703 68/push _test-output-stream/imm32 4704 # . . call 4705 e8/call clear-stream/disp32 4706 # . . discard args 4707 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4708 # . clear-stream($_test-output-buffered-file->buffer) 4709 # . . push args 4710 68/push $_test-output-buffered-file->buffer/imm32 4711 # . . call 4712 e8/call clear-stream/disp32 4713 # . . discard args 4714 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4715 # initialize input 4716 # . write(_test-input-stream, "8b/copy 0/mod 1/r32") 4717 # . . push args 4718 68/push "8b/copy 0/mod 1/r32"/imm32 4719 68/push _test-input-stream/imm32 4720 # . . call 4721 e8/call write/disp32 4722 # . . discard args 4723 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4724 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4725 # . . push args 4726 68/push _test-output-buffered-file/imm32 4727 68/push _test-input-stream/imm32 4728 # . . call 4729 e8/call convert-instruction/disp32 4730 # . . discard args 4731 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4732 # check output 4733 # . flush(_test-output-buffered-file) 4734 # . . push args 4735 68/push _test-output-buffered-file/imm32 4736 # . . call 4737 e8/call flush/disp32 4738 # . . discard args 4739 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4740 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4766 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/mod 1/r32", msg) 4767 # . . push args 4768 68/push "F - test-convert-instruction-emits-modrm-byte-with-missing-rm32"/imm32 4769 68/push "8b 08 # 8b/copy 0/mod 1/r32"/imm32 4770 68/push _test-output-stream/imm32 4771 # . . call 4772 e8/call check-stream-equal/disp32 4773 # . . discard args 4774 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4775 # . epilogue 4776 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4777 5d/pop-to-ebp 4778 c3/return 4779 4780 test-convert-instruction-emits-modrm-byte-with-missing-r32: 4781 # pack mod and rm32 operands into ModR/M byte 4782 # . prologue 4783 55/push-ebp 4784 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4785 # setup 4786 # . clear-stream(_test-input-stream) 4787 # . . push args 4788 68/push _test-input-stream/imm32 4789 # . . call 4790 e8/call clear-stream/disp32 4791 # . . discard args 4792 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4793 # . clear-stream(_test-output-stream) 4794 # . . push args 4795 68/push _test-output-stream/imm32 4796 # . . call 4797 e8/call clear-stream/disp32 4798 # . . discard args 4799 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4800 # . clear-stream($_test-output-buffered-file->buffer) 4801 # . . push args 4802 68/push $_test-output-buffered-file->buffer/imm32 4803 # . . call 4804 e8/call clear-stream/disp32 4805 # . . discard args 4806 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4807 # initialize input 4808 # . write(_test-input-stream, "8b/copy 0/mod 0/rm32") 4809 # . . push args 4810 68/push "8b/copy 0/mod 0/rm32"/imm32 4811 68/push _test-input-stream/imm32 4812 # . . call 4813 e8/call write/disp32 4814 # . . discard args 4815 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4816 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4817 # . . push args 4818 68/push _test-output-buffered-file/imm32 4819 68/push _test-input-stream/imm32 4820 # . . call 4821 e8/call convert-instruction/disp32 4822 # . . discard args 4823 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4824 # check output 4825 # . flush(_test-output-buffered-file) 4826 # . . push args 4827 68/push _test-output-buffered-file/imm32 4828 # . . call 4829 e8/call flush/disp32 4830 # . . discard args 4831 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4832 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4858 # . check-stream-equal(_test-output-stream, "8b 00 # 8b/copy 0/mod 0/rm32", msg) 4859 # . . push args 4860 68/push "F - test-convert-instruction-emits-modrm-byte-with-missing-r32"/imm32 4861 68/push "8b 00 # 8b/copy 0/mod 0/rm32"/imm32 4862 68/push _test-output-stream/imm32 4863 # . . call 4864 e8/call check-stream-equal/disp32 4865 # . . discard args 4866 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4867 # . epilogue 4868 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4869 5d/pop-to-ebp 4870 c3/return 4871 4872 test-convert-instruction-emits-sib-byte: 4873 # pack base, index and scale operands into SIB byte 4874 # . prologue 4875 55/push-ebp 4876 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4877 # setup 4878 # . clear-stream(_test-input-stream) 4879 # . . push args 4880 68/push _test-input-stream/imm32 4881 # . . call 4882 e8/call clear-stream/disp32 4883 # . . discard args 4884 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4885 # . clear-stream(_test-output-stream) 4886 # . . push args 4887 68/push _test-output-stream/imm32 4888 # . . call 4889 e8/call clear-stream/disp32 4890 # . . discard args 4891 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4892 # . clear-stream($_test-output-buffered-file->buffer) 4893 # . . push args 4894 68/push $_test-output-buffered-file->buffer/imm32 4895 # . . call 4896 e8/call clear-stream/disp32 4897 # . . discard args 4898 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4899 # initialize input 4900 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale") 4901 # . . push args 4902 68/push "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale"/imm32 4903 68/push _test-input-stream/imm32 4904 # . . call 4905 e8/call write/disp32 4906 # . . discard args 4907 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4908 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4909 # . . push args 4910 68/push _test-output-buffered-file/imm32 4911 68/push _test-input-stream/imm32 4912 # . . call 4913 e8/call convert-instruction/disp32 4914 # . . discard args 4915 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 4916 # check output 4917 # . flush(_test-output-buffered-file) 4918 # . . push args 4919 68/push _test-output-buffered-file/imm32 4920 # . . call 4921 e8/call flush/disp32 4922 # . . discard args 4923 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4924 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 4950 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale", msg) 4951 # . . push args 4952 68/push "F - test-convert-instruction-emits-sib-byte"/imm32 4953 68/push "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale"/imm32 4954 68/push _test-output-stream/imm32 4955 # . . call 4956 e8/call check-stream-equal/disp32 4957 # . . discard args 4958 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 4959 # . epilogue 4960 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 4961 5d/pop-to-ebp 4962 c3/return 4963 4964 test-convert-instruction-emits-scale: 4965 # pack base, index and scale operands into SIB byte 4966 # . prologue 4967 55/push-ebp 4968 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 4969 # setup 4970 # . clear-stream(_test-input-stream) 4971 # . . push args 4972 68/push _test-input-stream/imm32 4973 # . . call 4974 e8/call clear-stream/disp32 4975 # . . discard args 4976 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4977 # . clear-stream(_test-output-stream) 4978 # . . push args 4979 68/push _test-output-stream/imm32 4980 # . . call 4981 e8/call clear-stream/disp32 4982 # . . discard args 4983 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4984 # . clear-stream($_test-output-buffered-file->buffer) 4985 # . . push args 4986 68/push $_test-output-buffered-file->buffer/imm32 4987 # . . call 4988 e8/call clear-stream/disp32 4989 # . . discard args 4990 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 4991 # initialize input 4992 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/scale") 4993 # . . push args 4994 68/push "8b/copy 0/mod 4/rm32 1/scale"/imm32 4995 68/push _test-input-stream/imm32 4996 # . . call 4997 e8/call write/disp32 4998 # . . discard args 4999 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5000 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5001 # . . push args 5002 68/push _test-output-buffered-file/imm32 5003 68/push _test-input-stream/imm32 5004 # . . call 5005 e8/call convert-instruction/disp32 5006 # . . discard args 5007 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5008 # check output 5009 # . flush(_test-output-buffered-file) 5010 # . . push args 5011 68/push _test-output-buffered-file/imm32 5012 # . . call 5013 e8/call flush/disp32 5014 # . . discard args 5015 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5016 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5042 # . check-stream-equal(_test-output-stream, "8b 04 40 # 8b/copy 0/mod 4/rm32 1/scale", msg) 5043 # . . push args 5044 68/push "F - test-convert-instruction-emits-scale"/imm32 5045 68/push "8b 04 40 # 8b/copy 0/mod 4/rm32 1/scale"/imm32 5046 68/push _test-output-stream/imm32 5047 # . . call 5048 e8/call check-stream-equal/disp32 5049 # . . discard args 5050 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5051 # . epilogue 5052 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5053 5d/pop-to-ebp 5054 c3/return 5055 5056 test-convert-instruction-emits-sib-byte-with-missing-base: 5057 # pack index and scale operands into SIB byte 5058 # . prologue 5059 55/push-ebp 5060 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5061 # setup 5062 # . clear-stream(_test-input-stream) 5063 # . . push args 5064 68/push _test-input-stream/imm32 5065 # . . call 5066 e8/call clear-stream/disp32 5067 # . . discard args 5068 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5069 # . clear-stream(_test-output-stream) 5070 # . . push args 5071 68/push _test-output-stream/imm32 5072 # . . call 5073 e8/call clear-stream/disp32 5074 # . . discard args 5075 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5076 # . clear-stream($_test-output-buffered-file->buffer) 5077 # . . push args 5078 68/push $_test-output-buffered-file->buffer/imm32 5079 # . . call 5080 e8/call clear-stream/disp32 5081 # . . discard args 5082 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5083 # initialize input 5084 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale") 5085 # . . push args 5086 68/push "8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale"/imm32 5087 68/push _test-input-stream/imm32 5088 # . . call 5089 e8/call write/disp32 5090 # . . discard args 5091 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5092 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5093 # . . push args 5094 68/push _test-output-buffered-file/imm32 5095 68/push _test-input-stream/imm32 5096 # . . call 5097 e8/call convert-instruction/disp32 5098 # . . discard args 5099 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5100 # check output 5101 # . flush(_test-output-buffered-file) 5102 # . . push args 5103 68/push _test-output-buffered-file/imm32 5104 # . . call 5105 e8/call flush/disp32 5106 # . . discard args 5107 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5108 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5134 # . check-stream-equal(_test-output-stream, "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale", msg) 5135 # . . push args 5136 68/push "F - test-convert-instruction-emits-sib-byte-with-missing-base"/imm32 5137 68/push "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale"/imm32 5138 68/push _test-output-stream/imm32 5139 # . . call 5140 e8/call check-stream-equal/disp32 5141 # . . discard args 5142 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5143 # . epilogue 5144 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5145 5d/pop-to-ebp 5146 c3/return 5147 5148 test-convert-instruction-emits-sib-byte-with-missing-index: 5149 # pack base and scale operands into SIB byte 5150 # . prologue 5151 55/push-ebp 5152 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5153 # setup 5154 # . clear-stream(_test-input-stream) 5155 # . . push args 5156 68/push _test-input-stream/imm32 5157 # . . call 5158 e8/call clear-stream/disp32 5159 # . . discard args 5160 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5161 # . clear-stream(_test-output-stream) 5162 # . . push args 5163 68/push _test-output-stream/imm32 5164 # . . call 5165 e8/call clear-stream/disp32 5166 # . . discard args 5167 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5168 # . clear-stream($_test-output-buffered-file->buffer) 5169 # . . push args 5170 68/push $_test-output-buffered-file->buffer/imm32 5171 # . . call 5172 e8/call clear-stream/disp32 5173 # . . discard args 5174 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5175 # initialize input 5176 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale") 5177 # . . push args 5178 68/push "8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale"/imm32 5179 68/push _test-input-stream/imm32 5180 # . . call 5181 e8/call write/disp32 5182 # . . discard args 5183 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5184 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5185 # . . push args 5186 68/push _test-output-buffered-file/imm32 5187 68/push _test-input-stream/imm32 5188 # . . call 5189 e8/call convert-instruction/disp32 5190 # . . discard args 5191 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5192 # check output 5193 # . flush(_test-output-buffered-file) 5194 # . . push args 5195 68/push _test-output-buffered-file/imm32 5196 # . . call 5197 e8/call flush/disp32 5198 # . . discard args 5199 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5200 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5226 # . check-stream-equal(_test-output-stream, "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale", msg) 5227 # . . push args 5228 68/push "F - test-convert-instruction-emits-sib-byte-with-missing-index"/imm32 5229 68/push "8b 0c 00 # 8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale"/imm32 5230 68/push _test-output-stream/imm32 5231 # . . call 5232 e8/call check-stream-equal/disp32 5233 # . . discard args 5234 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5235 # . epilogue 5236 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5237 5d/pop-to-ebp 5238 c3/return 5239 5240 test-convert-instruction-emits-sib-byte-with-missing-scale: 5241 # pack base and index operands into SIB byte 5242 # . prologue 5243 55/push-ebp 5244 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5245 # setup 5246 # . clear-stream(_test-input-stream) 5247 # . . push args 5248 68/push _test-input-stream/imm32 5249 # . . call 5250 e8/call clear-stream/disp32 5251 # . . discard args 5252 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5253 # . clear-stream(_test-output-stream) 5254 # . . push args 5255 68/push _test-output-stream/imm32 5256 # . . call 5257 e8/call clear-stream/disp32 5258 # . . discard args 5259 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5260 # . clear-stream($_test-output-buffered-file->buffer) 5261 # . . push args 5262 68/push $_test-output-buffered-file->buffer/imm32 5263 # . . call 5264 e8/call clear-stream/disp32 5265 # . . discard args 5266 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5267 # initialize input 5268 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index") 5269 # . . push args 5270 68/push "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index"/imm32 5271 68/push _test-input-stream/imm32 5272 # . . call 5273 e8/call write/disp32 5274 # . . discard args 5275 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5276 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5277 # . . push args 5278 68/push _test-output-buffered-file/imm32 5279 68/push _test-input-stream/imm32 5280 # . . call 5281 e8/call convert-instruction/disp32 5282 # . . discard args 5283 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5284 # check output 5285 # . flush(_test-output-buffered-file) 5286 # . . push args 5287 68/push _test-output-buffered-file/imm32 5288 # . . call 5289 e8/call flush/disp32 5290 # . . discard args 5291 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5292 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5318 # . check-stream-equal(_test-output-stream, "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index", msg) 5319 # . . push args 5320 68/push "F - test-convert-instruction-emits-sib-byte-with-missing-scale"/imm32 5321 68/push "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index"/imm32 5322 68/push _test-output-stream/imm32 5323 # . . call 5324 e8/call check-stream-equal/disp32 5325 # . . discard args 5326 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5327 # . epilogue 5328 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5329 5d/pop-to-ebp 5330 c3/return 5331 5332 test-convert-instruction-handles-disp32-operand: 5333 # expand /disp32 operand into 4 bytes 5334 # . prologue 5335 55/push-ebp 5336 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5337 # setup 5338 # . clear-stream(_test-input-stream) 5339 # . . push args 5340 68/push _test-input-stream/imm32 5341 # . . call 5342 e8/call clear-stream/disp32 5343 # . . discard args 5344 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5345 # . clear-stream(_test-output-stream) 5346 # . . push args 5347 68/push _test-output-stream/imm32 5348 # . . call 5349 e8/call clear-stream/disp32 5350 # . . discard args 5351 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5352 # . clear-stream($_test-output-buffered-file->buffer) 5353 # . . push args 5354 68/push $_test-output-buffered-file->buffer/imm32 5355 # . . call 5356 e8/call clear-stream/disp32 5357 # . . discard args 5358 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5359 # initialize input 5360 # . write(_test-input-stream, "e8/call 20/disp32") 5361 # . . push args 5362 68/push "e8/call 20/disp32"/imm32 5363 68/push _test-input-stream/imm32 5364 # . . call 5365 e8/call write/disp32 5366 # . . discard args 5367 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5368 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5369 # . . push args 5370 68/push _test-output-buffered-file/imm32 5371 68/push _test-input-stream/imm32 5372 # . . call 5373 e8/call convert-instruction/disp32 5374 # . . discard args 5375 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5376 # check output 5377 # . flush(_test-output-buffered-file) 5378 # . . push args 5379 68/push _test-output-buffered-file/imm32 5380 # . . call 5381 e8/call flush/disp32 5382 # . . discard args 5383 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5384 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5410 # . check-stream-equal(_test-output-stream, "e8 20 00 00 00 # e8/call 20/disp32", msg) 5411 # . . push args 5412 68/push "F - test-convert-instruction-handles-disp32-operand"/imm32 5413 68/push "e8 20 00 00 00 # e8/call 20/disp32"/imm32 5414 68/push _test-output-stream/imm32 5415 # . . call 5416 e8/call check-stream-equal/disp32 5417 # . . discard args 5418 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5419 # . epilogue 5420 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5421 5d/pop-to-ebp 5422 c3/return 5423 5424 test-convert-instruction-handles-disp16-operand: 5425 # expand /disp16 operand into 2 bytes 5426 # . prologue 5427 55/push-ebp 5428 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5429 # setup 5430 # . clear-stream(_test-input-stream) 5431 # . . push args 5432 68/push _test-input-stream/imm32 5433 # . . call 5434 e8/call clear-stream/disp32 5435 # . . discard args 5436 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5437 # . clear-stream(_test-output-stream) 5438 # . . push args 5439 68/push _test-output-stream/imm32 5440 # . . call 5441 e8/call clear-stream/disp32 5442 # . . discard args 5443 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5444 # . clear-stream($_test-output-buffered-file->buffer) 5445 # . . push args 5446 68/push $_test-output-buffered-file->buffer/imm32 5447 # . . call 5448 e8/call clear-stream/disp32 5449 # . . discard args 5450 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5451 # initialize input 5452 # . write(_test-input-stream, "e8/call 20/disp16") 5453 # . . push args 5454 68/push "e8/call 20/disp16"/imm32 # not a valid instruction 5455 68/push _test-input-stream/imm32 5456 # . . call 5457 e8/call write/disp32 5458 # . . discard args 5459 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5460 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5461 # . . push args 5462 68/push _test-output-buffered-file/imm32 5463 68/push _test-input-stream/imm32 5464 # . . call 5465 e8/call convert-instruction/disp32 5466 # . . discard args 5467 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5468 # check output 5469 # . flush(_test-output-buffered-file) 5470 # . . push args 5471 68/push _test-output-buffered-file/imm32 5472 # . . call 5473 e8/call flush/disp32 5474 # . . discard args 5475 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5476 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5502 # . check-stream-equal(_test-output-stream, "e8 20 00 # e8/call 20/disp16", msg) 5503 # . . push args 5504 68/push "F - test-convert-instruction-handles-disp16-operand"/imm32 5505 68/push "e8 20 00 # e8/call 20/disp16"/imm32 5506 68/push _test-output-stream/imm32 5507 # . . call 5508 e8/call check-stream-equal/disp32 5509 # . . discard args 5510 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5511 # . epilogue 5512 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5513 5d/pop-to-ebp 5514 c3/return 5515 5516 test-convert-instruction-handles-disp8-operand: 5517 # expand /disp8 operand into 1 byte 5518 # . prologue 5519 55/push-ebp 5520 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5521 # setup 5522 # . clear-stream(_test-input-stream) 5523 # . . push args 5524 68/push _test-input-stream/imm32 5525 # . . call 5526 e8/call clear-stream/disp32 5527 # . . discard args 5528 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5529 # . clear-stream(_test-output-stream) 5530 # . . push args 5531 68/push _test-output-stream/imm32 5532 # . . call 5533 e8/call clear-stream/disp32 5534 # . . discard args 5535 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5536 # . clear-stream($_test-output-buffered-file->buffer) 5537 # . . push args 5538 68/push $_test-output-buffered-file->buffer/imm32 5539 # . . call 5540 e8/call clear-stream/disp32 5541 # . . discard args 5542 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5543 # initialize input 5544 # . write(_test-input-stream, "eb/jump 20/disp8") 5545 # . . push args 5546 68/push "eb/jump 20/disp8"/imm32 5547 68/push _test-input-stream/imm32 5548 # . . call 5549 e8/call write/disp32 5550 # . . discard args 5551 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5552 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5553 # . . push args 5554 68/push _test-output-buffered-file/imm32 5555 68/push _test-input-stream/imm32 5556 # . . call 5557 e8/call convert-instruction/disp32 5558 # . . discard args 5559 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5560 # check output 5561 # . flush(_test-output-buffered-file) 5562 # . . push args 5563 68/push _test-output-buffered-file/imm32 5564 # . . call 5565 e8/call flush/disp32 5566 # . . discard args 5567 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5568 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5594 # . check-stream-equal(_test-output-stream, "eb 20 # eb/jump 20/disp8", msg) 5595 # . . push args 5596 68/push "F - test-convert-instruction-handles-disp8-operand"/imm32 5597 68/push "eb 20 # eb/jump 20/disp8"/imm32 5598 68/push _test-output-stream/imm32 5599 # . . call 5600 e8/call check-stream-equal/disp32 5601 # . . discard args 5602 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5603 # . epilogue 5604 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5605 5d/pop-to-ebp 5606 c3/return 5607 5608 test-convert-instruction-handles-disp8-name: 5609 # pass /disp8 name directly through 5610 # . prologue 5611 55/push-ebp 5612 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5613 # setup 5614 # . clear-stream(_test-input-stream) 5615 # . . push args 5616 68/push _test-input-stream/imm32 5617 # . . call 5618 e8/call clear-stream/disp32 5619 # . . discard args 5620 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5621 # . clear-stream(_test-output-stream) 5622 # . . push args 5623 68/push _test-output-stream/imm32 5624 # . . call 5625 e8/call clear-stream/disp32 5626 # . . discard args 5627 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5628 # . clear-stream($_test-output-buffered-file->buffer) 5629 # . . push args 5630 68/push $_test-output-buffered-file->buffer/imm32 5631 # . . call 5632 e8/call clear-stream/disp32 5633 # . . discard args 5634 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5635 # initialize input 5636 # . write(_test-input-stream, "eb/jump xyz/disp8") 5637 # . . push args 5638 68/push "eb/jump xyz/disp8"/imm32 5639 68/push _test-input-stream/imm32 5640 # . . call 5641 e8/call write/disp32 5642 # . . discard args 5643 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5644 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5645 # . . push args 5646 68/push _test-output-buffered-file/imm32 5647 68/push _test-input-stream/imm32 5648 # . . call 5649 e8/call convert-instruction/disp32 5650 # . . discard args 5651 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5652 # check output 5653 # . flush(_test-output-buffered-file) 5654 # . . push args 5655 68/push _test-output-buffered-file/imm32 5656 # . . call 5657 e8/call flush/disp32 5658 # . . discard args 5659 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5660 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5686 # . check-stream-equal(_test-output-stream, "eb xyz/disp8 # eb/jump xyz/disp8", msg) 5687 # . . push args 5688 68/push "F - test-convert-instruction-handles-disp8-name"/imm32 5689 68/push "eb xyz/disp8 # eb/jump xyz/disp8"/imm32 5690 68/push _test-output-stream/imm32 5691 # . . call 5692 e8/call check-stream-equal/disp32 5693 # . . discard args 5694 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5695 # . epilogue 5696 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5697 5d/pop-to-ebp 5698 c3/return 5699 5700 test-convert-instruction-handles-imm32-operand: 5701 # expand /imm32 operand into 4 bytes 5702 # . prologue 5703 55/push-ebp 5704 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5705 # setup 5706 # . clear-stream(_test-input-stream) 5707 # . . push args 5708 68/push _test-input-stream/imm32 5709 # . . call 5710 e8/call clear-stream/disp32 5711 # . . discard args 5712 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5713 # . clear-stream(_test-output-stream) 5714 # . . push args 5715 68/push _test-output-stream/imm32 5716 # . . call 5717 e8/call clear-stream/disp32 5718 # . . discard args 5719 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5720 # . clear-stream($_test-output-buffered-file->buffer) 5721 # . . push args 5722 68/push $_test-output-buffered-file->buffer/imm32 5723 # . . call 5724 e8/call clear-stream/disp32 5725 # . . discard args 5726 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5727 # initialize input 5728 # . write(_test-input-stream, "68/push 0x20/imm32") 5729 # . . push args 5730 68/push "68/push 0x20/imm32"/imm32 5731 68/push _test-input-stream/imm32 5732 # . . call 5733 e8/call write/disp32 5734 # . . discard args 5735 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5736 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5737 # . . push args 5738 68/push _test-output-buffered-file/imm32 5739 68/push _test-input-stream/imm32 5740 # . . call 5741 e8/call convert-instruction/disp32 5742 # . . discard args 5743 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5744 # check output 5745 # . flush(_test-output-buffered-file) 5746 # . . push args 5747 68/push _test-output-buffered-file/imm32 5748 # . . call 5749 e8/call flush/disp32 5750 # . . discard args 5751 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5752 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5778 # . check-stream-equal(_test-output-stream, "68 20 00 00 00 # 68/push 0x20/imm32", msg) 5779 # . . push args 5780 68/push "F - test-convert-instruction-handles-imm32-operand"/imm32 5781 68/push "68 20 00 00 00 # 68/push 0x20/imm32"/imm32 5782 68/push _test-output-stream/imm32 5783 # . . call 5784 e8/call check-stream-equal/disp32 5785 # . . discard args 5786 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5787 # . epilogue 5788 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5789 5d/pop-to-ebp 5790 c3/return 5791 5792 test-convert-instruction-handles-imm16-operand: 5793 # expand /imm16 operand into 2 bytes 5794 # we don't have one of these at the moment, so this expands to an invalid instruction 5795 # . prologue 5796 55/push-ebp 5797 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5798 # setup 5799 # . clear-stream(_test-input-stream) 5800 # . . push args 5801 68/push _test-input-stream/imm32 5802 # . . call 5803 e8/call clear-stream/disp32 5804 # . . discard args 5805 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5806 # . clear-stream(_test-output-stream) 5807 # . . push args 5808 68/push _test-output-stream/imm32 5809 # . . call 5810 e8/call clear-stream/disp32 5811 # . . discard args 5812 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5813 # . clear-stream($_test-output-buffered-file->buffer) 5814 # . . push args 5815 68/push $_test-output-buffered-file->buffer/imm32 5816 # . . call 5817 e8/call clear-stream/disp32 5818 # . . discard args 5819 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5820 # initialize input 5821 # . write(_test-input-stream, "68/push 0x20/imm16") 5822 # . . push args 5823 68/push "68/push 0x20/imm16"/imm32 # not a valid instruction 5824 68/push _test-input-stream/imm32 5825 # . . call 5826 e8/call write/disp32 5827 # . . discard args 5828 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5829 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5830 # . . push args 5831 68/push _test-output-buffered-file/imm32 5832 68/push _test-input-stream/imm32 5833 # . . call 5834 e8/call convert-instruction/disp32 5835 # . . discard args 5836 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5837 # check output 5838 # . flush(_test-output-buffered-file) 5839 # . . push args 5840 68/push _test-output-buffered-file/imm32 5841 # . . call 5842 e8/call flush/disp32 5843 # . . discard args 5844 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5845 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5871 # . check-stream-equal(_test-output-stream, "68 20 00 # 68/push 0x20/imm16", msg) 5872 # . . push args 5873 68/push "F - test-convert-instruction-handles-imm16-operand"/imm32 5874 68/push "68 20 00 # 68/push 0x20/imm16"/imm32 5875 68/push _test-output-stream/imm32 5876 # . . call 5877 e8/call check-stream-equal/disp32 5878 # . . discard args 5879 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5880 # . epilogue 5881 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5882 5d/pop-to-ebp 5883 c3/return 5884 5885 test-convert-instruction-handles-imm8-operand: 5886 # expand /imm8 operand into 1 byte 5887 # we don't have one of these at the moment, so this expands to an invalid instruction 5888 # . prologue 5889 55/push-ebp 5890 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5891 # setup 5892 # . clear-stream(_test-input-stream) 5893 # . . push args 5894 68/push _test-input-stream/imm32 5895 # . . call 5896 e8/call clear-stream/disp32 5897 # . . discard args 5898 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5899 # . clear-stream(_test-output-stream) 5900 # . . push args 5901 68/push _test-output-stream/imm32 5902 # . . call 5903 e8/call clear-stream/disp32 5904 # . . discard args 5905 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5906 # . clear-stream($_test-output-buffered-file->buffer) 5907 # . . push args 5908 68/push $_test-output-buffered-file->buffer/imm32 5909 # . . call 5910 e8/call clear-stream/disp32 5911 # . . discard args 5912 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5913 # initialize input 5914 # . write(_test-input-stream, "68/push 0x20/imm8") 5915 # . . push args 5916 68/push "68/push 0x20/imm8"/imm32 5917 68/push _test-input-stream/imm32 5918 # . . call 5919 e8/call write/disp32 5920 # . . discard args 5921 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5922 # convert-instruction(_test-input-stream, _test-output-buffered-file) 5923 # . . push args 5924 68/push _test-output-buffered-file/imm32 5925 68/push _test-input-stream/imm32 5926 # . . call 5927 e8/call convert-instruction/disp32 5928 # . . discard args 5929 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 5930 # check output 5931 # . flush(_test-output-buffered-file) 5932 # . . push args 5933 68/push _test-output-buffered-file/imm32 5934 # . . call 5935 e8/call flush/disp32 5936 # . . discard args 5937 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 5938 +-- 26 lines: #? # dump output ------------------------------------------------------------------------------------------------------------------------------------------------------ 5964 # . check-stream-equal(_test-output-stream, "68 20 # 68/push 0x20/imm8", msg) 5965 # . . push args 5966 68/push "F - test-convert-instruction-handles-imm8-operand"/imm32 5967 68/push "68 20 # 68/push 0x20/imm8"/imm32 5968 68/push _test-output-stream/imm32 5969 # . . call 5970 e8/call check-stream-equal/disp32 5971 # . . discard args 5972 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 5973 # . epilogue 5974 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 5975 5d/pop-to-ebp 5976 c3/return 5977 5978 # shortcut for parse-hex-int-from-slice(next-token-from-slice(word->start, word->end, '/')) 5979 parse-datum-of-word: # word: (addr slice) -> value/eax: int 5980 # . prologue 5981 55/push-ebp 5982 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 5983 # . save registers 5984 51/push-ecx 5985 56/push-esi 5986 # esi = word 5987 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi 5988 # var slice/ecx: slice 5989 68/push 0/imm32/end 5990 68/push 0/imm32/start 5991 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 5992 # slice = next-token-from-slice(word->start, word->end, '/') 5993 # . . push args 5994 51/push-ecx 5995 68/push 0x2f/imm32/slash 5996 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) 5997 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi 5998 # . . call 5999 e8/call next-token-from-slice/disp32 6000 # . . discard args 6001 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 6002 # return parse-hex-int-from-slice(slice) 6003 # . . push args 6004 51/push-ecx 6005 # . . call 6006 e8/call parse-hex-int-from-slice/disp32 6007 # . . discard args 6008 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 6009 $parse-datum-of-word:end: 6010 # . reclaim locals 6011 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 6012 # . restore registers 6013 5e/pop-to-esi 6014 59/pop-to-ecx 6015 # . epilogue 6016 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 6017 5d/pop-to-ebp 6018 c3/return 6019 6020 # . . vim:nowrap:textwidth=0