https://github.com/akkartik/mu/blob/master/021byte_addressing.cc
  1 //: SubX mostly deals with instructions operating on 32-bit operands, but we
  2 //: still need to deal with raw bytes for strings and so on.
  3 
  4 //: Unfortunately the register encodings when dealing with bytes are a mess.
  5 //: We need a special case for them.
  6 :(code)
  7 string rname_8bit(uint8_t r) {
  8   switch (r) {
  9   case 0: return "AL";  // lowest byte of EAX
 10   case 1: return "CL";  // lowest byte of ECX
 11   case 2: return "DL";  // lowest byte of EDX
 12   case 3: return "BL";  // lowest byte of EBX
 13   case 4: return "AH";  // second lowest byte of EAX
 14   case 5: return "CH";  // second lowest byte of ECX
 15   case 6: return "DH";  // second lowest byte of EDX
 16   case 7: return "BH";  // second lowest byte of EBX
 17   default: raise << "invalid 8-bit register " << r << '\n' << end();  return "";
 18   }
 19 }
 20 
 21 uint8_t* effective_byte_address(uint8_t modrm) {
 22   uint8_t mod = (modrm>>6);
 23   uint8_t rm = modrm & 0x7;
 24   if (mod == 3) {
 25     // select an 8-bit register
 26     trace(Callstack_depth+1, "run") << "r/m8 is " << rname_8bit(rm) << end();
 27     return reg_8bit(rm);
 28   }
 29   // the rest is as usual
 30   return mem_addr_u8(effective_address_number(modrm));
 31 }
 32 
 33 uint8_t* reg_8bit(uint8_t rm) {
 34   uint8_t* result = reinterpret_cast<uint8_t*>(&Reg[rm & 0x3].i);  // _L register
 35   if (rm & 0x4)
 36     ++result;  // _H register;  assumes host is little-endian
 37   return result;
 38 }
 39 
 40 :(before "End Initialize Op Names")
 41 put_new(Name, "88", "copy r8 to r8/m8-at-r32");
 42 
 43 :(code)
 44 void test_copy_r8_to_mem_at_r32() {
 45   Reg[EBX].i = 0x224488ab;
 46   Reg[EAX].i = 0x2000;
 47   run(
 48       "== code 0x1\n"
 49       // op     ModR/M  SIB   displacement  immediate
 50       "  88     18                                      \n"  // copy BL to the byte at *EAX
 51       // ModR/M in binary: 00 (indirect mode) 011 (src BL) 000 (dest EAX)
 52       "== data 0x2000\n"
 53       "f0 cc bb aa\n"
 54   );
 55   CHECK_TRACE_CONTENTS(
 56       "run: copy BL to r8/m8-at-r32\n"
 57       "run: effective address is 0x00002000 (EAX)\n"
 58       "run: storing 0xab\n"
 59   );
 60   CHECK_EQ(0xaabbccab, read_mem_u32(0x2000));
 61 }
 62 
 63 :(before "End Single-Byte Opcodes")
 64 case 0x88: {  // copy r8 to r/m8
 65   const uint8_t modrm = next();
 66   const uint8_t rsrc = (modrm>>3)&0x7;
 67   trace(Callstack_depth+1, "run") << "copy " << rname_8bit(rsrc) << " to r8/m8-at-r32" << end();
 68   // use unsigned to zero-extend 8-bit value to 32 bits
 69   uint8_t* dest = effective_byte_address(modrm);
 70   const uint8_t* src = reg_8bit(rsrc);
 71   *dest = *src;  // Read/write multiple elements of vector<uint8_t> at once. Assumes sizeof(int) == 4 on the host as well.
 72   trace(Callstack_depth+1, "run") << "storing 0x" << HEXBYTE << NUM(*dest) << end();
 73   break;
 74 }
 75 
 76 //:
 77 
 78 :(before "End Initialize Op Names")
 79 put_new(Name, "8a", "copy r8/m8-at-r32 to r8");
 80 
 81 :(code)
 82 void test_copy_mem_at_r32_to_r8() {
 83   Reg[EBX].i = 0xaabbcc0f;  // one nibble each of lowest byte set to all 0s and all 1s, to maximize value of this test
 84   Reg[EAX].i = 0x2000;
 85   run(
 86       "== code 0x1\n"
 87       // op     ModR/M  SIB   displacement  immediate
 88       "  8a     18                                      \n"  // copy just the byte at *EAX to BL
 89       // ModR/M in binary: 00 (indirect mode) 011 (dest EBX) 000 (src EAX)
 90       "== data 0x2000\n"
 91       "ab ff ff ff\n"  // 0xab with more data in following bytes
 92   );
 93   CHECK_TRACE_CONTENTS(
 94       "run: copy r8/m8-at-r32 to BL\n"
 95       "run: effective address is 0x00002000 (EAX)\n"
 96       "run: storing 0xab\n"
 97       // remaining bytes of EBX are *not* cleared
 98       "run: EBX now contains 0xaabbccab\n"
 99   );
100 }
101 
102 :(before "End Single-Byte Opcodes")
103 case 0x8a: {  // copy r/m8 to r8
104   const uint8_t modrm = next();
105   const uint8_t rdest = (modrm>>3)&366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Mu - 038---literal_strings.cc</title>
<meta name="Generator" content="Vim/8.1">
<meta name="plugin-version" content="vim8.1_v1">
<meta name="syntax" content="cpp">
<meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy=">
<meta name="colorscheme" content="minimal-light">
<style type="text/css">
<!--
pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #c6c6c6; }
body { font-size:12pt; font-family: monospace; color: #000000; background-color: #c6c6c6; }
a { color:inherit; }
* { font-size:12pt; font-size: 1em; }
.CommentedCode { color: #8a8a8a; }
.LineNr { }
.Constant { color: #008787; }
.Comment { color: #005faf; }
.Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; }
.Special { color: #d70000; }
.Identifier { color: #af5f00; }
.Delimiter { color: #c000c0; }
.cSpecial { color: #008000; }
-->
</style>

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

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

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

-->
</script>
</head>
<body onload='JumpToLine();'>
<a href='https://github.com/akkartik/mu/blob/master/038---literal_strings.cc'>https://github.com/akkartik/mu/blob/master/038---literal_strings.cc</a>
<pre id='vimCodeElement'>
<span id="L1" class="LineNr">  1 </span><span class="Comment">//: Allow instructions to mention literals directly.</span>
<span id="L2" class="LineNr">  2 </span><span class="Comment">//:</span>
<span id="L3" class="LineNr">  3 </span><span class="Comment">//: This layer will transparently move them to the global segment (assumed to</span>
<span id="L4" class="LineNr">  4 </span><span class="Comment">//: always be the second segment).</span>
<span id="L5" class="LineNr">  5 </span>
<span id="L6" class="LineNr">  6 </span><span class="Normal">void</span> <a href='038---literal_strings.cc.html#L6'>test_transform_literal_string</a><span class="Delimiter">()</span> <span class="Delimiter">{</span>
<span id="L7" class="LineNr">  7 </span>  <a href='011run.cc.html#L82'>run</a><span class="Delimiter">(</span>
<span id="L8" class="LineNr">  8 </span>      <span class="Constant">&quot;== code 0x1\n&quot;</span>
<span id="L9" class="LineNr">  9 </span>      <span class="Constant">&quot;b8/copy  \&quot;</span>test\<span class="Constant">&quot;/imm32\n&quot;</span>
<span id="L10" class="LineNr"> 10 </span>      <span class="Constant">&quot;== data 0x2000\n&quot;</span>  <span class="Comment">// need an empty segment</span>
<span id="L11" class="LineNr"> 11 </span>  <span class="Delimiter">);</span>
<span id="L12" class="LineNr"> 12 </span>  <a href='003trace.cc.html#L292'>CHECK_TRACE_CONTENTS</a><span class="Delimiter">(</span>
<span id="L13" class="LineNr"> 13 </span>      <span class="Constant">&quot;transform: -- move literal strings to data segment\n&quot;</span>
<span id="L14" class="LineNr"> 14 </span>      <span class="Constant">&quot;transform: adding global variable '__subx_global_1' containing \&quot;</span>test\<span class="Constant">&quot;\n&quot;</span>
<span id="L15" class="LineNr"> 15 </span>      <span class="Constant">&quot;transform: <a href='011run.cc.html#L121'>line</a> after transform: 'b8 __subx_global_1'\n&quot;</span>
<span id="L16" class="LineNr"> 16 </span>  <span class="Delimiter">);</span>
<span id="L17" class="LineNr"> 17 </span><span class="Delimiter">}</span>
<span id="L18" class="LineNr"> 18 </span>
<span id="L19" class="LineNr"> 19 </span><span class="Comment">//: We don't rely on any transforms running in previous layers, but this layer</span>
<span id="L20" class="LineNr"> 20 </span><span class="Comment">//: knows about labels and global variables and will emit them for previous</span>
<span id="L21" class="LineNr"> 21 </span><span class="Comment">//: layers to transform.</span>
<span id="L22" class="LineNr"> 22 </span><span class="Delimiter">:(after &quot;Begin Transforms&quot;)</span>
<span id="L23" class="LineNr"> 23 </span><span class="Special"><a href='031transforms.cc.html#L4'>Transform</a></span><span class="Delimiter">.</span>push_back<span class="Delimiter">(</span><a href='038---literal_strings.cc.html#L30'>transform_literal_strings</a><span class="Delimiter">);</span>
<span id="L24" class="LineNr"> 24 </span>
<span id="L25" class="LineNr"> 25 </span><span class="Delimiter">:(before &quot;End Globals&quot;)</span>
<span id="L26" class="LineNr"> 26 </span><span class="Normal">int</span> <span class="Special">Next_auto_global</span> = <span class="Constant">1</span><span class="Delimiter">;</span>
<span id="L27" class="LineNr"> 27 </span><span class="Delimiter">:(before &quot;End Reset&quot;)</span>
<span id="L28" class="LineNr"> 28 </span><span class="Special">Next_auto_global</span> = <span class="Constant">1</span><span class="Delimiter">;</span>
<span id="L29" class="LineNr"> 29 <