This commit is contained in:
Kartik K. Agaram 2018-01-24 02:47:49 -08:00
parent 836d13dbc9
commit 3ecd66fb7c
6 changed files with 203 additions and 188 deletions

View File

@ -224,6 +224,20 @@ int32_t imm32() {
return result;
}
string rname(uint8_t r) {
switch (r) {
case 0: return "EAX";
case 1: return "ECX";
case 2: return "EDX";
case 3: return "EBX";
case 4: return "ESP";
case 5: return "EBP";
case 6: return "ESI";
case 7: return "EDI";
default: raise << "invalid register " << r << '\n' << end(); return "";
}
}
:(before "End Includes")
#include <iomanip>
#define HEXBYTE std::hex << std::setw(2) << std::setfill('0')

View File

@ -4,16 +4,17 @@
% Reg[0].i = 0x10;
% Reg[3].i = 1;
# op ModR/M SIB displacement immediate
01 d8 # add EBX (reg 3) to EAX (reg 0)
+run: add reg 3 to effective address
+run: effective address is reg 0
01 d8 # add EBX to EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: add EBX to effective address
+run: effective address is EAX
+run: storing 0x00000011
:(before "End Single-Byte Opcodes")
case 0x01: { // add r32 to r/m32
uint8_t modrm = next();
uint8_t arg2 = (modrm>>3)&0x7;
trace(2, "run") << "add reg " << NUM(arg2) << " to effective address" << end();
trace(2, "run") << "add " << rname(arg2) << " to effective address" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_ARITHMETIC_OP(+, *arg1, Reg[arg2].i);
break;
@ -31,7 +32,7 @@ int32_t* effective_address(uint8_t modrm) {
switch (mod) {
case 3:
// mod 3 is just register direct addressing
trace(2, "run") << "effective address is reg " << NUM(rm) << end();
trace(2, "run") << "effective address is " << rname(rm) << end();
result = &Reg[rm].i;
break;
// End Mod Special-cases
@ -48,16 +49,16 @@ int32_t* effective_address(uint8_t modrm) {
% Reg[0].i = 10;
% Reg[3].i = 1;
# op ModR/M SIB displacement immediate
29 d8 # subtract EBX (reg 3) from EAX (reg 0)
+run: subtract reg 3 from effective address
+run: effective address is reg 0
29 d8 # subtract EBX from EAX
+run: subtract EBX from effective address
+run: effective address is EAX
+run: storing 0x00000009
:(before "End Single-Byte Opcodes")
case 0x29: { // subtract r32 from r/m32
uint8_t modrm = next();
uint8_t arg2 = (modrm>>3)&0x7;
trace(2, "run") << "subtract reg " << NUM(arg2) << " from effective address" << end();
trace(2, "run") << "subtract " << rname(arg2) << " from effective address" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_ARITHMETIC_OP(-, *arg1, Reg[arg2].i);
break;
@ -69,16 +70,16 @@ case 0x29: { // subtract r32 from r/m32
% Reg[0].i = 0x0a0b0c0d;
% Reg[3].i = 0x000000ff;
# op ModR/M SIB displacement immediate
21 d8 # and EBX (reg 3) with destination EAX (reg 0)
+run: and reg 3 with effective address
+run: effective address is reg 0
21 d8 # and EBX with destination EAX
+run: and EBX with effective address
+run: effective address is EAX
+run: storing 0x0000000d
:(before "End Single-Byte Opcodes")
case 0x21: { // and r32 with r/m32
uint8_t modrm = next();
uint8_t arg2 = (modrm>>3)&0x7;
trace(2, "run") << "and reg " << NUM(arg2) << " with effective address" << end();
trace(2, "run") << "and " << rname(arg2) << " with effective address" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_BITWISE_OP(&, *arg1, Reg[arg2].u);
break;
@ -90,16 +91,16 @@ case 0x21: { // and r32 with r/m32
% Reg[0].i = 0x0a0b0c0d;
% Reg[3].i = 0xa0b0c0d0;
# op ModR/M SIB displacement immediate
09 d8 # or EBX (reg 3) with destination EAX (reg 0)
+run: or reg 3 with effective address
+run: effective address is reg 0
09 d8 # or EBX with destination EAX
+run: or EBX with effective address
+run: effective address is EAX
+run: storing 0xaabbccdd
:(before "End Single-Byte Opcodes")
case 0x09: { // or r32 with r/m32
uint8_t modrm = next();
uint8_t arg2 = (modrm>>3)&0x7;
trace(2, "run") << "or reg " << NUM(arg2) << " with effective address" << end();
trace(2, "run") << "or " << rname(arg2) << " with effective address" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_BITWISE_OP(|, *arg1, Reg[arg2].u);
break;
@ -111,16 +112,16 @@ case 0x09: { // or r32 with r/m32
% Reg[0].i = 0x0a0b0c0d;
% Reg[3].i = 0xaabbc0d0;
# op ModR/M SIB displacement immediate
31 d8 # xor EBX (reg 3) with destination EAX (reg 0)
+run: xor reg 3 with effective address
+run: effective address is reg 0
31 d8 # xor EBX with destination EAX
+run: xor EBX with effective address
+run: effective address is EAX
+run: storing 0xa0b0ccdd
:(before "End Single-Byte Opcodes")
case 0x31: { // xor r32 with r/m32
uint8_t modrm = next();
uint8_t arg2 = (modrm>>3)&0x7;
trace(2, "run") << "xor reg " << NUM(arg2) << " with effective address" << end();
trace(2, "run") << "xor " << rname(arg2) << " with effective address" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_BITWISE_OP(^, *arg1, Reg[arg2].u);
break;
@ -131,9 +132,9 @@ case 0x31: { // xor r32 with r/m32
:(scenario not_r32)
% Reg[3].i = 0x0f0f00ff;
# op ModR/M SIB displacement immediate
f7 c3 # not EBX (reg 3)
f7 c3 # not EBX
+run: 'not' of effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: storing 0xf0f0ff00
:(before "End Single-Byte Opcodes")
@ -155,16 +156,16 @@ case 0xf7: { // xor r32 with r/m32
% Reg[0].i = 0x0a0b0c0d;
% Reg[3].i = 0x0a0b0c07;
# op ModRM SIB displacement immediate
39 d8 # compare EBX (reg 3) with EAX (reg 0)
+run: compare reg 3 with effective address
+run: effective address is reg 0
39 d8 # compare EBX with EAX
+run: compare EBX with effective address
+run: effective address is EAX
+run: SF=0; ZF=0; OF=0
:(before "End Single-Byte Opcodes")
case 0x39: { // set SF if r/m32 < r32
uint8_t modrm = next();
uint8_t reg2 = (modrm>>3)&0x7;
trace(2, "run") << "compare reg " << NUM(reg2) << " with effective address" << end();
trace(2, "run") << "compare " << rname(reg2) << " with effective address" << end();
int32_t* arg1 = effective_address(modrm);
int32_t arg2 = Reg[reg2].i;
int32_t tmp1 = *arg1 - arg2;
@ -180,18 +181,18 @@ case 0x39: { // set SF if r/m32 < r32
% Reg[0].i = 0x0a0b0c07;
% Reg[3].i = 0x0a0b0c0d;
# op ModRM SIB displacement immediate
39 d8 # compare EBX (reg 3) with EAX (reg 0)
+run: compare reg 3 with effective address
+run: effective address is reg 0
39 d8 # compare EBX with EAX
+run: compare EBX with effective address
+run: effective address is EAX
+run: SF=1; ZF=0; OF=0
:(scenario compare_r32_with_r32_equal)
% Reg[0].i = 0x0a0b0c0d;
% Reg[3].i = 0x0a0b0c0d;
# op ModRM SIB displacement immediate
39 d8 # compare EBX (reg 3) with EAX (reg 0)
+run: compare reg 3 with effective address
+run: effective address is reg 0
39 d8 # compare EBX with EAX
+run: compare EBX with effective address
+run: effective address is EAX
+run: SF=0; ZF=1; OF=0
//:: copy (mov)
@ -199,16 +200,16 @@ case 0x39: { // set SF if r/m32 < r32
:(scenario copy_r32_to_r32)
% Reg[3].i = 0xaf;
# op ModRM SIB displacement immediate
89 d8 # copy EBX (reg 3) to EAX (reg 0)
+run: copy reg 3 to effective address
+run: effective address is reg 0
89 d8 # copy EBX to EAX
+run: copy EBX to effective address
+run: effective address is EAX
+run: storing 0x000000af
:(before "End Single-Byte Opcodes")
case 0x89: { // copy r32 to r/m32
uint8_t modrm = next();
uint8_t reg2 = (modrm>>3)&0x7;
trace(2, "run") << "copy reg " << NUM(reg2) << " to effective address" << end();
trace(2, "run") << "copy " << rname(reg2) << " to effective address" << end();
int32_t* arg1 = effective_address(modrm);
*arg1 = Reg[reg2].i;
trace(2, "run") << "storing 0x" << HEXWORD << *arg1 << end();
@ -221,23 +222,23 @@ case 0x89: { // copy r32 to r/m32
% Reg[3].i = 0xaf;
% Reg[0].i = 0x2e;
# op ModRM SIB displacement immediate
87 d8 # exchange EBX (reg 3) with EAX (reg 0)
+run: exchange reg 3 with effective address
+run: effective address is reg 0
87 d8 # exchange EBX with EAX
+run: exchange EBX with effective address
+run: effective address is EAX
+run: storing 0x000000af in effective address
+run: storing 0x0000002e in reg 3
+run: storing 0x0000002e in EBX
:(before "End Single-Byte Opcodes")
case 0x87: { // exchange r32 with r/m32
uint8_t modrm = next();
uint8_t reg2 = (modrm>>3)&0x7;
trace(2, "run") << "exchange reg " << NUM(reg2) << " with effective address" << end();
trace(2, "run") << "exchange " << rname(reg2) << " with effective address" << end();
int32_t* arg1 = effective_address(modrm);
int32_t tmp = *arg1;
*arg1 = Reg[reg2].i;
Reg[reg2].i = tmp;
trace(2, "run") << "storing 0x" << HEXWORD << *arg1 << " in effective address" << end();
trace(2, "run") << "storing 0x" << HEXWORD << Reg[reg2].i << " in reg " << NUM(reg2) << end();
trace(2, "run") << "storing 0x" << HEXWORD << Reg[reg2].i << " in " << rname(reg2) << end();
break;
}
@ -247,8 +248,8 @@ case 0x87: { // exchange r32 with r/m32
% Reg[ESP].u = 0x64;
% Reg[EBX].i = 0x0000000a;
# op ModRM SIB displacement immediate
53 # push EBX (reg 3) to stack
+run: push reg 3
53 # push EBX to stack
+run: push EBX
+run: decrementing ESP to 0x00000060
+run: pushing value 0x0000000a
@ -262,7 +263,7 @@ case 0x55:
case 0x56:
case 0x57: { // push r32 to stack
uint8_t reg = op & 0x7;
trace(2, "run") << "push reg " << NUM(reg) << end();
trace(2, "run") << "push " << rname(reg) << end();
push(Reg[reg].u);
break;
}
@ -280,8 +281,8 @@ void push(uint32_t val) {
% Reg[ESP].u = 0x60;
% SET_WORD_IN_MEM(0x60, 0x0000000a);
# op ModRM SIB displacement immediate
5b # pop stack to EBX (reg 3)
+run: pop into reg 3
5b # pop stack to EBX
+run: pop into EBX
+run: popping value 0x0000000a
+run: incrementing ESP to 0x00000064
@ -295,7 +296,7 @@ case 0x5d:
case 0x5e:
case 0x5f: { // pop stack into r32
uint8_t reg = op & 0x7;
trace(2, "run") << "pop into reg " << NUM(reg) << end();
trace(2, "run") << "pop into " << rname(reg) << end();
Reg[reg].u = pop();
break;
}

View File

@ -5,9 +5,9 @@
% Reg[0].i = 0x60;
% SET_WORD_IN_MEM(0x60, 1);
# op ModR/M SIB displacement immediate
01 18 # add EBX (reg 3) to *EAX (reg 0)
+run: add reg 3 to effective address
+run: effective address is mem at address 0x60 (reg 0)
01 18 # add EBX to *EAX
+run: add EBX to effective address
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x00000011
:(before "End Mod Special-cases")
@ -15,7 +15,7 @@ case 0:
// mod 0 is usually indirect addressing
switch (rm) {
default:
trace(2, "run") << "effective address is mem at address 0x" << std::hex << Reg[rm].u << " (reg " << NUM(rm) << ")" << end();
trace(2, "run") << "effective address is mem at address 0x" << std::hex << Reg[rm].u << " (" << rname(rm) << ")" << end();
assert(Reg[rm].u + sizeof(int32_t) <= Mem.size());
result = reinterpret_cast<int32_t*>(&Mem.at(Reg[rm].u)); // rely on the host itself being in little-endian order
break;
@ -30,16 +30,16 @@ case 0:
% Reg[3].i = 0x10;
% SET_WORD_IN_MEM(0x60, 1);
# op ModR/M SIB displacement immediate
03 18 # add *EAX (reg 0) to EBX (reg 3)
+run: add effective address to reg 3
+run: effective address is mem at address 0x60 (reg 0)
03 18 # add *EAX to EBX
+run: add effective address to EBX
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x00000011
:(before "End Single-Byte Opcodes")
case 0x03: { // add r/m32 to r32
uint8_t modrm = next();
uint8_t arg1 = (modrm>>3)&0x7;
trace(2, "run") << "add effective address to reg " << NUM(arg1) << end();
trace(2, "run") << "add effective address to " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_ARITHMETIC_OP(+, Reg[arg1].i, *arg2);
break;
@ -52,9 +52,9 @@ case 0x03: { // add r/m32 to r32
% SET_WORD_IN_MEM(0x60, 10);
% Reg[3].i = 1;
# op ModRM SIB displacement immediate
29 18 # subtract EBX (reg 3) from *EAX (reg 0)
+run: subtract reg 3 from effective address
+run: effective address is mem at address 0x60 (reg 0)
29 18 # subtract EBX from *EAX
+run: subtract EBX from effective address
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x00000009
//:
@ -64,16 +64,16 @@ case 0x03: { // add r/m32 to r32
% SET_WORD_IN_MEM(0x60, 1);
% Reg[3].i = 10;
# op ModRM SIB displacement immediate
2b 18 # subtract *EAX (reg 0) from EBX (reg 3)
+run: subtract effective address from reg 3
+run: effective address is mem at address 0x60 (reg 0)
2b 18 # subtract *EAX from EBX
+run: subtract effective address from EBX
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x00000009
:(before "End Single-Byte Opcodes")
case 0x2b: { // subtract r/m32 from r32
uint8_t modrm = next();
uint8_t arg1 = (modrm>>3)&0x7;
trace(2, "run") << "subtract effective address from reg " << NUM(arg1) << end();
trace(2, "run") << "subtract effective address from " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_ARITHMETIC_OP(-, Reg[arg1].i, *arg2);
break;
@ -86,9 +86,9 @@ case 0x2b: { // subtract r/m32 from r32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
% Reg[3].i = 0xff;
# op ModRM SIB displacement immediate
21 18 # and EBX (reg 3) with *EAX (reg 0)
+run: and reg 3 with effective address
+run: effective address is mem at address 0x60 (reg 0)
21 18 # and EBX with *EAX
+run: and EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x0000000d
//:
@ -98,16 +98,16 @@ case 0x2b: { // subtract r/m32 from r32
% SET_WORD_IN_MEM(0x60, 0x000000ff);
% Reg[3].i = 0x0a0b0c0d;
# op ModRM SIB displacement immediate
23 18 # and *EAX (reg 0) with EBX (reg 3)
+run: and effective address with reg 3
+run: effective address is mem at address 0x60 (reg 0)
23 18 # and *EAX with EBX
+run: and effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x0000000d
:(before "End Single-Byte Opcodes")
case 0x23: { // and r/m32 with r32
uint8_t modrm = next();
uint8_t arg1 = (modrm>>3)&0x7;
trace(2, "run") << "and effective address with reg " << NUM(arg1) << end();
trace(2, "run") << "and effective address with " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_BITWISE_OP(&, Reg[arg1].u, *arg2);
break;
@ -120,9 +120,9 @@ case 0x23: { // and r/m32 with r32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
% Reg[3].i = 0xa0b0c0d0;
# op ModRM SIB displacement immediate
09 18 # or EBX (reg 3) with *EAX (reg 0)
+run: or reg 3 with effective address
+run: effective address is mem at address 0x60 (reg 0)
09 18 # or EBX with *EAX
+run: or EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0xaabbccdd
//:
@ -132,16 +132,16 @@ case 0x23: { // and r/m32 with r32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
% Reg[3].i = 0xa0b0c0d0;
# op ModRM SIB displacement immediate
0b 18 # or *EAX (reg 0) with EBX (reg 3)
+run: or effective address with reg 3
+run: effective address is mem at address 0x60 (reg 0)
0b 18 # or *EAX with EBX
+run: or effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0xaabbccdd
:(before "End Single-Byte Opcodes")
case 0x0b: { // or r/m32 with r32
uint8_t modrm = next();
uint8_t arg1 = (modrm>>3)&0x7;
trace(2, "run") << "or effective address with reg " << NUM(arg1) << end();
trace(2, "run") << "or effective address with " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_BITWISE_OP(|, Reg[arg1].u, *arg2);
break;
@ -154,9 +154,9 @@ case 0x0b: { // or r/m32 with r32
% SET_WORD_IN_MEM(0x60, 0xaabb0c0d);
% Reg[3].i = 0xa0b0c0d0;
# op ModRM SIB displacement immediate
31 18 # xor EBX (reg 3) with *EAX (reg 0)
+run: xor reg 3 with effective address
+run: effective address is mem at address 0x60 (reg 0)
31 18 # xor EBX with *EAX
+run: xor EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x0a0bccdd
//:
@ -166,16 +166,16 @@ case 0x0b: { // or r/m32 with r32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
% Reg[3].i = 0xa0b0c0d0;
# op ModRM SIB displacement immediate
33 18 # xor *EAX (reg 0) with EBX (reg 3)
+run: xor effective address with reg 3
+run: effective address is mem at address 0x60 (reg 0)
33 18 # xor *EAX with EBX
+run: xor effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0xaabbccdd
:(before "End Single-Byte Opcodes")
case 0x33: { // xor r/m32 with r32
uint8_t modrm = next();
uint8_t arg1 = (modrm>>3)&0x7;
trace(2, "run") << "xor effective address with reg " << NUM(arg1) << end();
trace(2, "run") << "xor effective address with " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_BITWISE_OP(|, Reg[arg1].u, *arg2);
break;
@ -188,9 +188,9 @@ case 0x33: { // xor r/m32 with r32
# word at 0x60 is 0x0f0f00ff
% SET_WORD_IN_MEM(0x60, 0x0f0f00ff);
# op ModRM SIB displacement immediate
f7 03 # negate *EBX (reg 3)
f7 03 # negate *EBX
+run: 'not' of effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
+run: storing 0xf0f0ff00
//:: compare (cmp)
@ -200,9 +200,9 @@ case 0x33: { // xor r/m32 with r32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
% Reg[3].i = 0x0a0b0c07;
# op ModRM SIB displacement immediate
39 18 # compare EBX (reg 3) with *EAX (reg 0)
+run: compare reg 3 with effective address
+run: effective address is mem at address 0x60 (reg 0)
39 18 # compare EBX with *EAX
+run: compare EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: SF=0; ZF=0; OF=0
:(scenario compare_mem_at_r32_with_r32_lesser)
@ -210,9 +210,9 @@ case 0x33: { // xor r/m32 with r32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c07);
% Reg[3].i = 0x0a0b0c0d;
# op ModRM SIB displacement immediate
39 18 # compare EBX (reg 3) with *EAX (reg 0)
+run: compare reg 3 with effective address
+run: effective address is mem at address 0x60 (reg 0)
39 18 # compare EBX with *EAX
+run: compare EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: SF=1; ZF=0; OF=0
:(scenario compare_mem_at_r32_with_r32_equal)
@ -220,9 +220,9 @@ case 0x33: { // xor r/m32 with r32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
% Reg[3].i = 0x0a0b0c0d;
# op ModRM SIB displacement immediate
39 18 # compare EBX (reg 3) with *EAX (reg 0)
+run: compare reg 3 with effective address
+run: effective address is mem at address 0x60 (reg 0)
39 18 # compare EBX with *EAX
+run: compare EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: SF=0; ZF=1; OF=0
//:
@ -232,16 +232,16 @@ case 0x33: { // xor r/m32 with r32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c07);
% Reg[3].i = 0x0a0b0c0d;
# op ModRM SIB displacement immediate
3b 18 # compare *EAX (reg 0) with EBX (reg 3)
+run: compare effective address with reg 3
+run: effective address is mem at address 0x60 (reg 0)
3b 18 # compare *EAX with EBX
+run: compare effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: SF=0; ZF=0; OF=0
:(before "End Single-Byte Opcodes")
case 0x3b: { // set SF if r32 < r/m32
uint8_t modrm = next();
uint8_t reg1 = (modrm>>3)&0x7;
trace(2, "run") << "compare effective address with reg " << NUM(reg1) << end();
trace(2, "run") << "compare effective address with " << rname(reg1) << end();
int32_t arg1 = Reg[reg1].i;
int32_t* arg2 = effective_address(modrm);
int32_t tmp1 = arg1 - *arg2;
@ -258,9 +258,9 @@ case 0x3b: { // set SF if r32 < r/m32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
% Reg[3].i = 0x0a0b0c07;
# op ModRM SIB displacement immediate
3b 18 # compare *EAX (reg 0) with EBX (reg 3)
+run: compare effective address with reg 3
+run: effective address is mem at address 0x60 (reg 0)
3b 18 # compare *EAX with EBX
+run: compare effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: SF=1; ZF=0; OF=0
:(scenario compare_r32_with_mem_at_r32_equal)
@ -268,9 +268,9 @@ case 0x3b: { // set SF if r32 < r/m32
% SET_WORD_IN_MEM(0x60, 0x0a0b0c0d);
% Reg[3].i = 0x0a0b0c0d;
# op ModRM SIB displacement immediate
3b 18 # compare *EAX (reg 0) with EBX (reg 3)
+run: compare effective address with reg 3
+run: effective address is mem at address 0x60 (reg 0)
3b 18 # compare *EAX with EBX
+run: compare effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: SF=0; ZF=1; OF=0
//:: copy (mov)
@ -279,9 +279,9 @@ case 0x3b: { // set SF if r32 < r/m32
% Reg[3].i = 0xaf;
% Reg[0].i = 0x60;
# op ModRM SIB displacement immediate
89 18 # copy EBX (reg 3) to *EAX (reg 0)
+run: copy reg 3 to effective address
+run: effective address is mem at address 0x60 (reg 0)
89 18 # copy EBX to *EAX
+run: copy EBX to effective address
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x000000af
//:
@ -290,16 +290,16 @@ case 0x3b: { // set SF if r32 < r/m32
% Reg[0].i = 0x60;
% SET_WORD_IN_MEM(0x60, 0x000000af);
# op ModRM SIB displacement immediate
8b 18 # copy *EAX (reg 0) to EBX (reg 3)
+run: copy effective address to reg 3
+run: effective address is mem at address 0x60 (reg 0)
8b 18 # copy *EAX to EBX
+run: copy effective address to EBX
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x000000af
:(before "End Single-Byte Opcodes")
case 0x8b: { // copy r32 to r/m32
uint8_t modrm = next();
uint8_t reg1 = (modrm>>3)&0x7;
trace(2, "run") << "copy effective address to reg " << NUM(reg1) << end();
trace(2, "run") << "copy effective address to " << rname(reg1) << end();
int32_t* arg2 = effective_address(modrm);
Reg[reg1].i = *arg2;
trace(2, "run") << "storing 0x" << HEXWORD << *arg2 << end();
@ -312,12 +312,12 @@ case 0x8b: { // copy r32 to r/m32
% Reg[0].i = 0x60;
% SET_WORD_IN_MEM(0x60, 8);
# op ModRM SIB displacement immediate
ff 20 # jump to *EAX (reg 0)
ff 20 # jump to *EAX
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: effective address is mem at address 0x60 (EAX)
+run: jumping to 0x00000008
+run: inst: 0x00000008
-run: inst: 0x00000003
@ -346,9 +346,9 @@ case 0xff: {
% SET_WORD_IN_MEM(0x60, 0x000000af);
% Reg[ESP].u = 0x14;
# op ModRM SIB displacement immediate
ff 30 # push *EAX (reg 0) to stack
ff 30 # push *EAX to stack
+run: push effective address
+run: effective address is mem at address 0x60 (reg 0)
+run: effective address is mem at address 0x60 (EAX)
+run: decrementing ESP to 0x00000010
+run: pushing value 0x000000af
@ -367,9 +367,9 @@ case 6: { // push r/m32 to stack
% Reg[ESP].u = 0x10;
% SET_WORD_IN_MEM(0x10, 0x00000030);
# op ModRM SIB displacement immediate
8f 00 # pop stack into *EAX (reg 0)
8f 00 # pop stack into *EAX
+run: pop into effective address
+run: effective address is mem at address 0x60 (reg 0)
+run: effective address is mem at address 0x60 (EAX)
+run: popping value 0x00000030
+run: incrementing ESP to 0x00000014

View File

@ -3,9 +3,9 @@
:(scenario add_imm32_to_r32)
% Reg[3].i = 1;
# op ModRM SIB displacement immediate
81 c3 0a 0b 0c 0d # add 0x0d0c0b0a to EBX (reg 3)
81 c3 0a 0b 0c 0d # add 0x0d0c0b0a to EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: subop add
+run: storing 0x0d0c0b0b
@ -35,9 +35,9 @@ case 0x81: { // combine imm32 with r/m32
% Reg[3].i = 0x60;
% SET_WORD_IN_MEM(0x60, 1);
# op ModR/M SIB displacement immediate
81 03 0a 0b 0c 0d # add 0x0d0c0b0a to *EBX (reg 3)
81 03 0a 0b 0c 0d # add 0x0d0c0b0a to *EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
+run: subop add
+run: storing 0x0d0c0b0b
@ -46,14 +46,14 @@ case 0x81: { // combine imm32 with r/m32
:(scenario subtract_imm32_from_eax)
% Reg[EAX].i = 0x0d0c0baa;
# op ModR/M SIB displacement immediate
2d 0a 0b 0c 0d # subtract 0x0d0c0b0a from EAX (reg 0)
+run: subtract imm32 0x0d0c0b0a from reg EAX
2d 0a 0b 0c 0d # subtract 0x0d0c0b0a from EAX
+run: subtract imm32 0x0d0c0b0a from EAX
+run: storing 0x000000a0
:(before "End Single-Byte Opcodes")
case 0x2d: { // subtract imm32 from EAX
int32_t arg2 = imm32();
trace(2, "run") << "subtract imm32 0x" << HEXWORD << arg2 << " from reg EAX" << end();
trace(2, "run") << "subtract imm32 0x" << HEXWORD << arg2 << " from EAX" << end();
BINARY_ARITHMETIC_OP(-, Reg[EAX].i, arg2);
break;
}
@ -64,9 +64,9 @@ case 0x2d: { // subtract imm32 from EAX
% Reg[3].i = 0x60;
% SET_WORD_IN_MEM(0x60, 10);
# op ModRM SIB displacement immediate
81 2b 01 00 00 00 # subtract 1 from *EBX (reg 3)
81 2b 01 00 00 00 # subtract 1 from *EBX
+run: combine imm32 0x00000001 with effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
+run: subop subtract
+run: storing 0x00000009
@ -75,9 +75,9 @@ case 0x2d: { // subtract imm32 from EAX
:(scenario subtract_imm32_from_r32)
% Reg[3].i = 10;
# op ModRM SIB displacement immediate
81 eb 01 00 00 00 # subtract 1 from EBX (reg 3)
81 eb 01 00 00 00 # subtract 1 from EBX
+run: combine imm32 0x00000001 with effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: subop subtract
+run: storing 0x00000009
@ -93,14 +93,14 @@ case 5: {
:(scenario and_imm32_with_eax)
% Reg[EAX].i = 0xff;
# op ModR/M SIB displacement immediate
25 0a 0b 0c 0d # and 0x0d0c0b0a with EAX (reg 0)
+run: and imm32 0x0d0c0b0a with reg EAX
25 0a 0b 0c 0d # and 0x0d0c0b0a with EAX
+run: and imm32 0x0d0c0b0a with EAX
+run: storing 0x0000000a
:(before "End Single-Byte Opcodes")
case 0x25: { // and imm32 with EAX
int32_t arg2 = imm32();
trace(2, "run") << "and imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
trace(2, "run") << "and imm32 0x" << HEXWORD << arg2 << " with EAX" << end();
BINARY_BITWISE_OP(&, Reg[EAX].i, arg2);
break;
}
@ -111,9 +111,9 @@ case 0x25: { // and imm32 with EAX
% Reg[3].i = 0x60;
% SET_WORD_IN_MEM(0x60, 0x000000ff);
# op ModRM SIB displacement immediate
81 23 0a 0b 0c 0d # and 0x0d0c0b0a with *EBX (reg 3)
81 23 0a 0b 0c 0d # and 0x0d0c0b0a with *EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
+run: subop and
+run: storing 0x0000000a
@ -122,9 +122,9 @@ case 0x25: { // and imm32 with EAX
:(scenario and_imm32_with_r32)
% Reg[3].i = 0xff;
# op ModRM SIB displacement immediate
81 e3 0a 0b 0c 0d # and 0x0d0c0b0a with EBX (reg 3)
81 e3 0a 0b 0c 0d # and 0x0d0c0b0a with EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: subop and
+run: storing 0x0000000a
@ -140,14 +140,14 @@ case 4: {
:(scenario or_imm32_with_eax)
% Reg[EAX].i = 0xd0c0b0a0;
# op ModR/M SIB displacement immediate
0d 0a 0b 0c 0d # or 0x0d0c0b0a with EAX (reg 0)
+run: or imm32 0x0d0c0b0a with reg EAX
0d 0a 0b 0c 0d # or 0x0d0c0b0a with EAX
+run: or imm32 0x0d0c0b0a with EAX
+run: storing 0xddccbbaa
:(before "End Single-Byte Opcodes")
case 0x0d: { // or imm32 with EAX
int32_t arg2 = imm32();
trace(2, "run") << "or imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
trace(2, "run") << "or imm32 0x" << HEXWORD << arg2 << " with EAX" << end();
BINARY_BITWISE_OP(|, Reg[EAX].i, arg2);
break;
}
@ -158,9 +158,9 @@ case 0x0d: { // or imm32 with EAX
% Reg[3].i = 0x60;
% SET_WORD_IN_MEM(0x60, 0xd0c0b0a0);
# op ModRM SIB displacement immediate
81 0b 0a 0b 0c 0d # or 0x0d0c0b0a with *EBX (reg 3)
81 0b 0a 0b 0c 0d # or 0x0d0c0b0a with *EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
+run: subop or
+run: storing 0xddccbbaa
@ -174,9 +174,9 @@ case 1: {
:(scenario or_imm32_with_r32)
% Reg[3].i = 0xd0c0b0a0;
# op ModRM SIB displacement immediate
81 cb 0a 0b 0c 0d # or 0x0d0c0b0a with EBX (reg 3)
81 cb 0a 0b 0c 0d # or 0x0d0c0b0a with EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: subop or
+run: storing 0xddccbbaa
@ -185,14 +185,14 @@ case 1: {
:(scenario xor_imm32_with_eax)
% Reg[EAX].i = 0xddccb0a0;
# op ModR/M SIB displacement immediate
35 0a 0b 0c 0d # xor 0x0d0c0b0a with EAX (reg 0)
+run: xor imm32 0x0d0c0b0a with reg EAX
35 0a 0b 0c 0d # xor 0x0d0c0b0a with EAX
+run: xor imm32 0x0d0c0b0a with EAX
+run: storing 0xd0c0bbaa
:(before "End Single-Byte Opcodes")
case 0x35: { // xor imm32 with EAX
int32_t arg2 = imm32();
trace(2, "run") << "xor imm32 0x" << HEXWORD << arg2 << " with reg EAX" << end();
trace(2, "run") << "xor imm32 0x" << HEXWORD << arg2 << " with EAX" << end();
BINARY_BITWISE_OP(^, Reg[EAX].i, arg2);
break;
}
@ -203,9 +203,9 @@ case 0x35: { // xor imm32 with EAX
% Reg[3].i = 0x60;
% SET_WORD_IN_MEM(0x60, 0xd0c0b0a0);
# op ModRM SIB displacement immediate
81 33 0a 0b 0c 0d # xor 0x0d0c0b0a with *EBX (reg 3)
81 33 0a 0b 0c 0d # xor 0x0d0c0b0a with *EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
+run: subop xor
+run: storing 0xddccbbaa
@ -219,9 +219,9 @@ case 6: {
:(scenario xor_imm32_with_r32)
% Reg[3].i = 0xd0c0b0a0;
# op ModRM SIB displacement immediate
81 f3 0a 0b 0c 0d # xor 0x0d0c0b0a with EBX (reg 3)
81 f3 0a 0b 0c 0d # xor 0x0d0c0b0a with EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: subop xor
+run: storing 0xddccbbaa
@ -230,15 +230,15 @@ case 6: {
:(scenario compare_imm32_with_eax_greater)
% Reg[0].i = 0x0d0c0b0a;
# op ModRM SIB displacement immediate
3d 07 0b 0c 0d # compare 0x0d0c0b07 with EAX (reg 0)
+run: compare reg EAX and imm32 0x0d0c0b07
3d 07 0b 0c 0d # compare 0x0d0c0b07 with EAX
+run: compare EAX and imm32 0x0d0c0b07
+run: SF=0; ZF=0; OF=0
:(before "End Single-Byte Opcodes")
case 0x3d: { // subtract imm32 from EAX
int32_t arg1 = Reg[EAX].i;
int32_t arg2 = imm32();
trace(2, "run") << "compare reg EAX and imm32 0x" << HEXWORD << arg2 << end();
trace(2, "run") << "compare EAX and imm32 0x" << HEXWORD << arg2 << end();
int32_t tmp1 = arg1 - arg2;
SF = (tmp1 < 0);
ZF = (tmp1 == 0);
@ -251,15 +251,15 @@ case 0x3d: { // subtract imm32 from EAX
:(scenario compare_imm32_with_eax_lesser)
% Reg[0].i = 0x0d0c0b07;
# op ModRM SIB displacement immediate
3d 0a 0b 0c 0d # compare 0x0d0c0b0a with EAX (reg 0)
+run: compare reg EAX and imm32 0x0d0c0b0a
3d 0a 0b 0c 0d # compare 0x0d0c0b0a with EAX
+run: compare EAX and imm32 0x0d0c0b0a
+run: SF=1; ZF=0; OF=0
:(scenario compare_imm32_with_eax_equal)
% Reg[0].i = 0x0d0c0b0a;
# op ModRM SIB displacement immediate
3d 0a 0b 0c 0d # compare 0x0d0c0b0a with EAX (reg 0)
+run: compare reg EAX and imm32 0x0d0c0b0a
3d 0a 0b 0c 0d # compare 0x0d0c0b0a with EAX
+run: compare EAX and imm32 0x0d0c0b0a
+run: SF=0; ZF=1; OF=0
//:
@ -267,9 +267,9 @@ case 0x3d: { // subtract imm32 from EAX
:(scenario compare_imm32_with_r32_greater)
% Reg[3].i = 0x0d0c0b0a;
# op ModRM SIB displacement immediate
81 fb 07 0b 0c 0d # compare 0x0d0c0b07 with EBX (reg 3)
81 fb 07 0b 0c 0d # compare 0x0d0c0b07 with EBX
+run: combine imm32 0x0d0c0b07 with effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: SF=0; ZF=0; OF=0
:(before "End Op 81 Subops")
@ -287,35 +287,35 @@ case 7: {
:(scenario compare_imm32_with_r32_lesser)
% Reg[3].i = 0x0d0c0b07;
# op ModRM SIB displacement immediate
81 fb 0a 0b 0c 0d # compare 0x0d0c0b0a with EBX (reg 3)
81 fb 0a 0b 0c 0d # compare 0x0d0c0b0a with EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: SF=1; ZF=0; OF=0
:(scenario compare_imm32_with_r32_equal)
% Reg[3].i = 0x0d0c0b0a;
# op ModRM SIB displacement immediate
81 fb 0a 0b 0c 0d # compare 0x0d0c0b0a with EBX (reg 3)
81 fb 0a 0b 0c 0d # compare 0x0d0c0b0a with EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: SF=0; ZF=1; OF=0
:(scenario compare_imm32_with_mem_at_r32_greater)
% Reg[3].i = 0x60;
% SET_WORD_IN_MEM(0x60, 0x0d0c0b0a);
# op ModRM SIB displacement immediate
81 3b 07 0b 0c 0d # compare 0x0d0c0b07 with *EBX (reg 3)
81 3b 07 0b 0c 0d # compare 0x0d0c0b07 with *EBX
+run: combine imm32 0x0d0c0b07 with effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
+run: SF=0; ZF=0; OF=0
:(scenario compare_imm32_with_mem_at_r32_lesser)
% Reg[3].i = 0x60;
% SET_WORD_IN_MEM(0x60, 0x0d0c0b07);
# op ModRM SIB displacement immediate
81 3b 0a 0b 0c 0d # compare 0x0d0c0b0a with *EBX (reg 3)
81 3b 0a 0b 0c 0d # compare 0x0d0c0b0a with *EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
+run: SF=1; ZF=0; OF=0
:(scenario compare_imm32_with_mem_at_r32_equal)
@ -323,17 +323,17 @@ case 7: {
% Reg[3].i = 0x60;
% SET_WORD_IN_MEM(0x60, 0x0d0c0b0a);
# op ModRM SIB displacement immediate
81 3b 0a 0b 0c 0d # compare 0x0d0c0b0a with *EBX (reg 3)
81 3b 0a 0b 0c 0d # compare 0x0d0c0b0a with *EBX
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
+run: SF=0; ZF=1; OF=0
//:: copy (mov)
:(scenario copy_imm32_to_r32)
# op ModRM SIB displacement immediate
bb 0a 0b 0c 0d # copy 0x0d0c0b0a to EBX (reg 3)
+run: copy imm32 0x0d0c0b0a to reg 3
bb 0a 0b 0c 0d # copy 0x0d0c0b0a to EBX
+run: copy imm32 0x0d0c0b0a to EBX
:(before "End Single-Byte Opcodes")
case 0xb8:
@ -346,7 +346,7 @@ case 0xbe:
case 0xbf: { // copy imm32 to r32
uint8_t reg1 = op & 0x7;
int32_t arg2 = imm32();
trace(2, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to reg " << NUM(reg1) << end();
trace(2, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to " << rname(reg1) << end();
Reg[reg1].i = arg2;
break;
}
@ -356,9 +356,9 @@ case 0xbf: { // copy imm32 to r32
:(scenario copy_imm32_to_mem_at_r32)
% Reg[3].i = 0x60;
# op ModRM SIB displacement immediate
c7 03 0a 0b 0c 0d # copy 0x0d0c0b0a to *EBX (reg 3)
c7 03 0a 0b 0c 0d # copy 0x0d0c0b0a to *EBX
+run: copy imm32 0x0d0c0b0a to effective address
+run: effective address is mem at address 0x60 (reg 3)
+run: effective address is mem at address 0x60 (EBX)
:(before "End Single-Byte Opcodes")
case 0xc7: { // copy imm32 to r32
@ -375,7 +375,7 @@ case 0xc7: { // copy imm32 to r32
:(scenario push_imm32)
% Reg[ESP].u = 0x14;
# op ModRM SIB displacement immediate
68 af 00 00 00 # push *EAX (reg 0) to stack
68 af 00 00 00 # push *EAX to stack
+run: push imm32 0x000000af
+run: ESP is now 0x00000010
+run: contents at ESP: 0x000000af

View File

@ -5,11 +5,11 @@
% Reg[0].i = 0x60;
% SET_WORD_IN_MEM(0x60, 1);
# op ModR/M SIB displacement immediate
01 1c 20 # add EBX (reg 3) to *EAX (reg 0)
01 1c 20 # add EBX to *EAX
# SIB in binary: 00 (scale 1) 100 (no index) 000 (base EAX)
# See Table 2-3 of the Intel programming manual.
+run: add reg 3 to effective address
+run: effective address is mem at address 0x60 (reg 0)
+run: add EBX to effective address
+run: effective address is mem at address 0x60 (EAX)
+run: storing 0x00000011
:(before "End Mod 0 Special-cases")
@ -20,13 +20,13 @@ case 4:
uint8_t index = (sib>>3)&0x7;
if (index == ESP) {
// ignore index and scale
trace(2, "run") << "effective address is mem at address 0x" << std::hex << Reg[base].u << " (reg " << NUM(base) << ")" << end();
trace(2, "run") << "effective address is mem at address 0x" << std::hex << Reg[base].u << " (" << rname(base) << ")" << end();
result = reinterpret_cast<int32_t*>(&Mem.at(Reg[base].u));
}
else {
uint8_t scale = (1 << (sib>>6));
uint32_t addr = Reg[base].u + Reg[index].u*scale;
trace(2, "run") << "effective address is mem at address 0x" << std::hex << addr << " (reg " << NUM(base) << " + reg " << NUM(index) << " * " << NUM(scale) << ")" << end();
trace(2, "run") << "effective address is mem at address 0x" << std::hex << addr << " (" << rname(base) << " + " << rname(index) << "*" << NUM(scale) << ")" << end();
result = reinterpret_cast<int32_t*>(&Mem.at(addr));
}
break;
@ -37,9 +37,9 @@ case 4:
% Reg[1].i = 0x2; // dest index
% SET_WORD_IN_MEM(0x60, 1);
# op ModR/M SIB displacement immediate
01 1c 08 # add EBX (reg 3) to *(EAX+ECX)
01 1c 08 # add EBX to *(EAX+ECX)
# SIB in binary: 00 (scale 1) 001 (index ECX) 000 (base EAX)
# See Table 2-3 of the Intel programming manual.
+run: add reg 3 to effective address
+run: effective address is mem at address 0x60 (reg 0 + reg 1 * 1)
+run: add EBX to effective address
+run: effective address is mem at address 0x60 (EAX + ECX*1)
+run: storing 0x00000011

View File

@ -26,10 +26,10 @@ case 0xe8: { // call imm32 relative to next EIP
% Reg[ESP].u = 0x64;
% Reg[EBX].u = 0x000000a0;
# op ModRM SIB displacement immediate
ff d3 # call function offset at EBX (reg 3)
ff d3 # call function offset at EBX
# next EIP is 3
+run: call to effective address
+run: effective address is reg 3
+run: effective address is EBX
+run: decrementing ESP to 0x00000060
+run: pushing value 0x00000003
+run: jumping to 0x000000a3
@ -49,10 +49,10 @@ case 2: { // call function pointer at r/m32
% Reg[EBX].u = 0x10;
% SET_WORD_IN_MEM(0x10, 0x000000a0);
# op ModRM SIB displacement immediate
ff 13 # call function offset at *EBX (reg 3)
ff 13 # call function offset at *EBX
# next EIP is 3
+run: call to effective address
+run: effective address is mem at address 0x10 (reg 3)
+run: effective address is mem at address 0x10 (EBX)
+run: decrementing ESP to 0x00000060
+run: pushing value 0x00000003
+run: jumping to 0x000000a3