about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx')
-rw-r--r--subx/010core.cc2
-rw-r--r--subx/012indirect_addressing.cc32
-rw-r--r--subx/013immediate_addressing.cc46
3 files changed, 80 insertions, 0 deletions
diff --git a/subx/010core.cc b/subx/010core.cc
index 42445afd..8040a645 100644
--- a/subx/010core.cc
+++ b/subx/010core.cc
@@ -106,6 +106,7 @@ void run(const string& text_bytes) {
 // skeleton of how x86 instructions are decoded
 void run_one_instruction() {
   uint8_t op=0, op2=0, op3=0;
+  trace(2, "run") << "inst: 0x" << HEXWORD << EIP << end();
   switch (op = next()) {
   case 0xf4:  // hlt
     EIP = End_of_program;
@@ -185,6 +186,7 @@ char next_hex_byte(istream& in) {
         }
       }
     }
+    if (c == '\0') return c;
     if (c >= '0' && c <= '9') return c;
     if (c >= 'a' && c <= 'f') return c;
     if (c >= 'A' && c <= 'F') return tolower(c);
diff --git a/subx/012indirect_addressing.cc b/subx/012indirect_addressing.cc
index 3b2944b2..1bf5e378 100644
--- a/subx/012indirect_addressing.cc
+++ b/subx/012indirect_addressing.cc
@@ -305,3 +305,35 @@ case 0x8b: {  // copy r32 to r/m32
   trace(2, "run") << "storing 0x" << HEXWORD << *arg2 << end();
   break;
 }
+
+//:: jump
+
+:(scenario jump_mem_at_r32)
+% Reg[0].i = 0x60;
+% SET_WORD_IN_MEM(0x60, 8);
+# op  ModRM   SIB   displacement  immediate
+  ff  20                                      # jump to *EAX (reg 0)
+  05                              00 00 00 01
+  05                              00 00 00 02
++run: inst: 0x00000001
++run: jump to effective address
++run: effective address is mem at address 0x60 (reg 0)
++run: jumping to 0x00000008
++run: inst: 0x00000008
+-run: inst: 0x00000003
+
+:(before "End Single-Byte Opcodes")
+case 0xff: {  // jump to r/m32
+  uint8_t modrm = next();
+  uint8_t subop = (modrm>>3)&0x7;  // middle 3 'reg opcode' bits
+  switch (subop) {
+  case 4:
+    trace(2, "run") << "jump to effective address" << end();
+    int32_t* arg2 = effective_address(modrm);
+    EIP = *arg2;
+    trace(2, "run") << "jumping to 0x" << HEXWORD << EIP << end();
+    break;
+  // End Op ff Subops
+  }
+  break;
+}
diff --git a/subx/013immediate_addressing.cc b/subx/013immediate_addressing.cc
index dd1ce4c0..e97b9f6c 100644
--- a/subx/013immediate_addressing.cc
+++ b/subx/013immediate_addressing.cc
@@ -366,3 +366,49 @@ case 0xc7: {  // copy imm32 to r32
   *arg1 = arg2;
   break;
 }
+
+//:: jump
+
+:(scenario jump_rel8)
+# op  ModRM   SIB   displacement  immediate
+  eb                05                        # skip 1 instruction
+  05                              00 00 00 01
+  05                              00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x00000008
+-run: inst: 0x00000003
+
+:(before "End Single-Byte Opcodes")
+case 0xeb: {  // jump rel8
+  int8_t offset = static_cast<int>(next());
+  trace(2, "run") << "jump " << NUM(offset) << end();
+  EIP += offset;
+  break;
+}
+
+//:
+
+:(scenario jump_rel16)
+# op  ModRM   SIB   displacement  immediate
+  e9                05 00                     # skip 1 instruction
+  05                              00 00 00 01
+  05                              00 00 00 02
++run: inst: 0x00000001
++run: jump 5
++run: inst: 0x00000009
+-run: inst: 0x00000003
+
+:(before "End Single-Byte Opcodes")
+case 0xe9: {  // jump rel8
+  int16_t offset = imm16();
+  trace(2, "run") << "jump " << offset << end();
+  EIP += offset;
+  break;
+}
+:(code)
+int16_t imm16() {
+  int16_t result = next();
+  result |= (next()<<8);
+  return result;
+}