This commit is contained in:
Kartik K. Agaram 2018-01-24 21:01:47 -08:00
parent 631de5d981
commit 871ea368d1
5 changed files with 136 additions and 136 deletions

View File

@ -6,15 +6,15 @@
# op ModR/M SIB displacement immediate
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: add EBX to r/m32
+run: r/m32 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 " << rname(arg2) << " to effective address" << end();
trace(2, "run") << "add " << rname(arg2) << " to r/m32" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_ARITHMETIC_OP(+, *arg1, Reg[arg2].i);
break;
@ -32,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 " << rname(rm) << end();
trace(2, "run") << "r/m32 is " << rname(rm) << end();
result = &Reg[rm].i;
break;
// End Mod Special-cases
@ -51,15 +51,15 @@ int32_t* effective_address(uint8_t modrm) {
# op ModR/M SIB displacement immediate
29 d8 # subtract EBX from EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: subtract EBX from effective address
+run: effective address is EAX
+run: subtract EBX from r/m32
+run: r/m32 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 " << rname(arg2) << " from effective address" << end();
trace(2, "run") << "subtract " << rname(arg2) << " from r/m32" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_ARITHMETIC_OP(-, *arg1, Reg[arg2].i);
break;
@ -73,15 +73,15 @@ case 0x29: { // subtract r32 from r/m32
# op ModR/M SIB displacement immediate
21 d8 # and EBX with destination EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: and EBX with effective address
+run: effective address is EAX
+run: and EBX with r/m32
+run: r/m32 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 " << rname(arg2) << " with effective address" << end();
trace(2, "run") << "and " << rname(arg2) << " with r/m32" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_BITWISE_OP(&, *arg1, Reg[arg2].u);
break;
@ -95,15 +95,15 @@ case 0x21: { // and r32 with r/m32
# op ModR/M SIB displacement immediate
09 d8 # or EBX with destination EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: or EBX with effective address
+run: effective address is EAX
+run: or EBX with r/m32
+run: r/m32 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 " << rname(arg2) << " with effective address" << end();
trace(2, "run") << "or " << rname(arg2) << " with r/m32" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_BITWISE_OP(|, *arg1, Reg[arg2].u);
break;
@ -117,15 +117,15 @@ case 0x09: { // or r32 with r/m32
# op ModR/M SIB displacement immediate
31 d8 # xor EBX with destination EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: xor EBX with effective address
+run: effective address is EAX
+run: xor EBX with r/m32
+run: r/m32 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 " << rname(arg2) << " with effective address" << end();
trace(2, "run") << "xor " << rname(arg2) << " with r/m32" << end();
int32_t* arg1 = effective_address(modrm);
BINARY_BITWISE_OP(^, *arg1, Reg[arg2].u);
break;
@ -138,14 +138,14 @@ case 0x31: { // xor r32 with r/m32
# op ModR/M SIB displacement immediate
f7 c3 # not EBX
# ModR/M in binary: 11 (direct mode) 000 (unused) 011 (dest EBX)
+run: 'not' of effective address
+run: effective address is EBX
+run: 'not' of r/m32
+run: r/m32 is EBX
+run: storing 0xf0f0ff00
:(before "End Single-Byte Opcodes")
case 0xf7: { // xor r32 with r/m32
uint8_t modrm = next();
trace(2, "run") << "'not' of effective address" << end();
trace(2, "run") << "'not' of r/m32" << end();
int32_t* arg1 = effective_address(modrm);
*arg1 = ~(*arg1);
trace(2, "run") << "storing 0x" << HEXWORD << *arg1 << end();
@ -163,15 +163,15 @@ case 0xf7: { // xor r32 with r/m32
# op ModR/M SIB displacement immediate
39 d8 # compare EBX with EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: compare EBX with effective address
+run: effective address is EAX
+run: compare EBX with r/m32
+run: r/m32 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 " << rname(reg2) << " with effective address" << end();
trace(2, "run") << "compare " << rname(reg2) << " with r/m32" << end();
int32_t* arg1 = effective_address(modrm);
int32_t arg2 = Reg[reg2].i;
int32_t tmp1 = *arg1 - arg2;
@ -189,8 +189,8 @@ case 0x39: { // set SF if r/m32 < r32
# op ModR/M SIB displacement immediate
39 d8 # compare EBX with EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: compare EBX with effective address
+run: effective address is EAX
+run: compare EBX with r/m32
+run: r/m32 is EAX
+run: SF=1; ZF=0; OF=0
:(scenario compare_r32_with_r32_equal)
@ -199,8 +199,8 @@ case 0x39: { // set SF if r/m32 < r32
# op ModR/M SIB displacement immediate
39 d8 # compare EBX with EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: compare EBX with effective address
+run: effective address is EAX
+run: compare EBX with r/m32
+run: r/m32 is EAX
+run: SF=0; ZF=1; OF=0
//:: copy (mov)
@ -210,15 +210,15 @@ case 0x39: { // set SF if r/m32 < r32
# op ModR/M SIB displacement immediate
89 d8 # copy EBX to EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: copy EBX to effective address
+run: effective address is EAX
+run: copy EBX to r/m32
+run: r/m32 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 " << rname(reg2) << " to effective address" << end();
trace(2, "run") << "copy " << rname(reg2) << " to r/m32" << end();
int32_t* arg1 = effective_address(modrm);
*arg1 = Reg[reg2].i;
trace(2, "run") << "storing 0x" << HEXWORD << *arg1 << end();
@ -233,21 +233,21 @@ case 0x89: { // copy r32 to r/m32
# op ModR/M SIB displacement immediate
87 d8 # exchange EBX with EAX
# ModR/M in binary: 11 (direct mode) 011 (src EBX) 000 (dest EAX)
+run: exchange EBX with effective address
+run: effective address is EAX
+run: storing 0x000000af in effective address
+run: exchange EBX with r/m32
+run: r/m32 is EAX
+run: storing 0x000000af in r/m32
+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 " << rname(reg2) << " with effective address" << end();
trace(2, "run") << "exchange " << rname(reg2) << " with r/m32" << 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 << *arg1 << " in r/m32" << end();
trace(2, "run") << "storing 0x" << HEXWORD << Reg[reg2].i << " in " << rname(reg2) << end();
break;
}

View File

@ -7,15 +7,15 @@
# op ModR/M SIB displacement immediate
01 18 # add EBX to *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: add EBX to effective address
+run: effective address is mem at address 0x60 (EAX)
+run: add EBX to r/m32
+run: effective address is 0x60 (EAX)
+run: storing 0x00000011
:(before "End Mod Special-cases")
case 0:
switch (rm) {
default: // mod 0 is usually indirect addressing
trace(2, "run") << "effective address is mem at address 0x" << std::hex << Reg[rm].u << " (" << rname(rm) << ")" << end();
trace(2, "run") << "effective address is 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;
@ -32,15 +32,15 @@ case 0:
# op ModR/M SIB displacement immediate
03 18 # add *EAX to EBX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: add effective address to EBX
+run: effective address is mem at address 0x60 (EAX)
+run: add r/m32 to EBX
+run: effective address is 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 " << rname(arg1) << end();
trace(2, "run") << "add r/m32 to " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_ARITHMETIC_OP(+, Reg[arg1].i, *arg2);
break;
@ -55,8 +55,8 @@ case 0x03: { // add r/m32 to r32
# op ModR/M SIB displacement immediate
29 18 # subtract EBX from *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: subtract EBX from effective address
+run: effective address is mem at address 0x60 (EAX)
+run: subtract EBX from r/m32
+run: effective address is 0x60 (EAX)
+run: storing 0x00000009
//:
@ -68,15 +68,15 @@ case 0x03: { // add r/m32 to r32
# op ModR/M SIB displacement immediate
2b 18 # subtract *EAX from EBX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: subtract effective address from EBX
+run: effective address is mem at address 0x60 (EAX)
+run: subtract r/m32 from EBX
+run: effective address is 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 " << rname(arg1) << end();
trace(2, "run") << "subtract r/m32 from " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_ARITHMETIC_OP(-, Reg[arg1].i, *arg2);
break;
@ -91,8 +91,8 @@ case 0x2b: { // subtract r/m32 from r32
# op ModR/M SIB displacement immediate
21 18 # and EBX with *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: and EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: and EBX with r/m32
+run: effective address is 0x60 (EAX)
+run: storing 0x0000000d
//:
@ -104,15 +104,15 @@ case 0x2b: { // subtract r/m32 from r32
# op ModR/M SIB displacement immediate
23 18 # and *EAX with EBX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: and effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: and r/m32 with EBX
+run: effective address is 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 " << rname(arg1) << end();
trace(2, "run") << "and r/m32 with " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_BITWISE_OP(&, Reg[arg1].u, *arg2);
break;
@ -127,8 +127,8 @@ case 0x23: { // and r/m32 with r32
# op ModR/M SIB displacement immediate
09 18 # or EBX with *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: or EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: or EBX with r/m32
+run: effective address is 0x60 (EAX)
+run: storing 0xaabbccdd
//:
@ -140,15 +140,15 @@ case 0x23: { // and r/m32 with r32
# op ModR/M SIB displacement immediate
0b 18 # or *EAX with EBX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: or effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: or r/m32 with EBX
+run: effective address is 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 " << rname(arg1) << end();
trace(2, "run") << "or r/m32 with " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_BITWISE_OP(|, Reg[arg1].u, *arg2);
break;
@ -163,8 +163,8 @@ case 0x0b: { // or r/m32 with r32
# op ModR/M SIB displacement immediate
31 18 # xor EBX with *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: xor EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: xor EBX with r/m32
+run: effective address is 0x60 (EAX)
+run: storing 0x0a0bccdd
//:
@ -176,15 +176,15 @@ case 0x0b: { // or r/m32 with r32
# op ModR/M SIB displacement immediate
33 18 # xor *EAX with EBX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: xor effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: xor r/m32 with EBX
+run: effective address is 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 " << rname(arg1) << end();
trace(2, "run") << "xor r/m32 with " << rname(arg1) << end();
const int32_t* arg2 = effective_address(modrm);
BINARY_BITWISE_OP(|, Reg[arg1].u, *arg2);
break;
@ -199,8 +199,8 @@ case 0x33: { // xor r/m32 with r32
# op ModR/M SIB displacement immediate
f7 03 # negate *EBX
# ModR/M in binary: 00 (indirect mode) 000 (unused) 011 (dest EBX)
+run: 'not' of effective address
+run: effective address is mem at address 0x60 (EBX)
+run: 'not' of r/m32
+run: effective address is 0x60 (EBX)
+run: storing 0xf0f0ff00
//:: compare (cmp)
@ -212,8 +212,8 @@ case 0x33: { // xor r/m32 with r32
# op ModR/M SIB displacement immediate
39 18 # compare EBX with *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: compare EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: compare EBX with r/m32
+run: effective address is 0x60 (EAX)
+run: SF=0; ZF=0; OF=0
:(scenario compare_mem_at_r32_with_r32_lesser)
@ -223,8 +223,8 @@ case 0x33: { // xor r/m32 with r32
# op ModR/M SIB displacement immediate
39 18 # compare EBX with *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: compare EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: compare EBX with r/m32
+run: effective address is 0x60 (EAX)
+run: SF=1; ZF=0; OF=0
:(scenario compare_mem_at_r32_with_r32_equal)
@ -234,8 +234,8 @@ case 0x33: { // xor r/m32 with r32
# op ModR/M SIB displacement immediate
39 18 # compare EBX with *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: compare EBX with effective address
+run: effective address is mem at address 0x60 (EAX)
+run: compare EBX with r/m32
+run: effective address is 0x60 (EAX)
+run: SF=0; ZF=1; OF=0
//:
@ -247,15 +247,15 @@ case 0x33: { // xor r/m32 with r32
# op ModR/M SIB displacement immediate
3b 18 # compare *EAX with EBX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: compare effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: compare r/m32 with EBX
+run: effective address is 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 " << rname(reg1) << end();
trace(2, "run") << "compare r/m32 with " << rname(reg1) << end();
int32_t arg1 = Reg[reg1].i;
int32_t* arg2 = effective_address(modrm);
int32_t tmp1 = arg1 - *arg2;
@ -274,8 +274,8 @@ case 0x3b: { // set SF if r32 < r/m32
# op ModR/M SIB displacement immediate
3b 18 # compare *EAX with EBX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: compare effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: compare r/m32 with EBX
+run: effective address is 0x60 (EAX)
+run: SF=1; ZF=0; OF=0
:(scenario compare_r32_with_mem_at_r32_equal)
@ -285,8 +285,8 @@ case 0x3b: { // set SF if r32 < r/m32
# op ModR/M SIB displacement immediate
3b 18 # compare *EAX with EBX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: compare effective address with EBX
+run: effective address is mem at address 0x60 (EAX)
+run: compare r/m32 with EBX
+run: effective address is 0x60 (EAX)
+run: SF=0; ZF=1; OF=0
//:: copy (mov)
@ -297,8 +297,8 @@ case 0x3b: { // set SF if r32 < r/m32
# op ModR/M SIB displacement immediate
89 18 # copy EBX to *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: copy EBX to effective address
+run: effective address is mem at address 0x60 (EAX)
+run: copy EBX to r/m32
+run: effective address is 0x60 (EAX)
+run: storing 0x000000af
//:
@ -309,15 +309,15 @@ case 0x3b: { // set SF if r32 < r/m32
# op ModR/M SIB displacement immediate
8b 18 # copy *EAX to EBX
# ModR/M in binary: 00 (indirect mode) 011 (src EAX) 000 (dest EAX)
+run: copy effective address to EBX
+run: effective address is mem at address 0x60 (EAX)
+run: copy r/m32 to EBX
+run: effective address is 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 " << rname(reg1) << end();
trace(2, "run") << "copy r/m32 to " << rname(reg1) << end();
int32_t* arg2 = effective_address(modrm);
Reg[reg1].i = *arg2;
trace(2, "run") << "storing 0x" << HEXWORD << *arg2 << end();
@ -335,8 +335,8 @@ case 0x8b: { // copy r32 to r/m32
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 (EAX)
+run: jump to r/m32
+run: effective address is 0x60 (EAX)
+run: jumping to 0x00000008
+run: inst: 0x00000008
-run: inst: 0x00000003
@ -347,7 +347,7 @@ case 0xff: {
uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits
switch (subop) {
case 4: { // jump to r/m32
trace(2, "run") << "jump to effective address" << end();
trace(2, "run") << "jump to r/m32" << end();
int32_t* arg2 = effective_address(modrm);
EIP = *arg2;
trace(2, "run") << "jumping to 0x" << HEXWORD << EIP << end();
@ -367,14 +367,14 @@ case 0xff: {
# op ModR/M SIB displacement immediate
ff 30 # push *EAX to stack
# ModR/M in binary: 00 (indirect mode) 110 (push r/m32) 000 (src EAX)
+run: push effective address
+run: effective address is mem at address 0x60 (EAX)
+run: push r/m32
+run: effective address is 0x60 (EAX)
+run: decrementing ESP to 0x00000010
+run: pushing value 0x000000af
:(before "End Op ff Subops")
case 6: { // push r/m32 to stack
trace(2, "run") << "push effective address" << end();
trace(2, "run") << "push r/m32" << end();
const int32_t* val = effective_address(modrm);
push(*val);
break;
@ -389,8 +389,8 @@ case 6: { // push r/m32 to stack
# op ModR/M SIB displacement immediate
8f 00 # pop stack into *EAX
# ModR/M in binary: 00 (indirect mode) 000 (pop r/m32) 000 (dest EAX)
+run: pop into effective address
+run: effective address is mem at address 0x60 (EAX)
+run: pop into r/m32
+run: effective address is 0x60 (EAX)
+run: popping value 0x00000030
+run: incrementing ESP to 0x00000014
@ -400,7 +400,7 @@ case 0x8f: { // pop stack into r/m32
uint8_t subop = (modrm>>3)&0x7;
switch (subop) {
case 0: {
trace(2, "run") << "pop into effective address" << end();
trace(2, "run") << "pop into r/m32" << end();
int32_t* dest = effective_address(modrm);
*dest = pop();
break;

View File

@ -5,8 +5,8 @@
# op ModR/M SIB displacement immediate
81 c3 0a 0b 0c 0d # add 0x0d0c0b0a to EBX
# ModR/M in binary: 11 (direct mode) 000 (add imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is EBX
+run: combine imm32 0x0d0c0b0a with r/m32
+run: r/m32 is EBX
+run: subop add
+run: storing 0x0d0c0b0b
@ -14,7 +14,7 @@
case 0x81: { // combine imm32 with r/m32
uint8_t modrm = next();
int32_t arg2 = imm32();
trace(2, "run") << "combine imm32 0x" << HEXWORD << arg2 << " with effective address" << end();
trace(2, "run") << "combine imm32 0x" << HEXWORD << arg2 << " with r/m32" << end();
int32_t* arg1 = effective_address(modrm);
uint8_t subop = (modrm>>3)&0x7; // middle 3 'reg opcode' bits
switch (subop) {
@ -38,8 +38,8 @@ case 0x81: { // combine imm32 with r/m32
# op ModR/M SIB displacement immediate
81 03 0a 0b 0c 0d # add 0x0d0c0b0a to *EBX
# ModR/M in binary: 00 (indirect mode) 000 (add imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (EBX)
+run: combine imm32 0x0d0c0b0a with r/m32
+run: effective address is 0x60 (EBX)
+run: subop add
+run: storing 0x0d0c0b0b
@ -68,8 +68,8 @@ case 0x2d: { // subtract imm32 from EAX
# op ModR/M SIB displacement immediate
81 2b 01 00 00 00 # subtract 1 from *EBX
# ModR/M in binary: 00 (indirect mode) 101 (subtract imm32) 011 (dest EBX)
+run: combine imm32 0x00000001 with effective address
+run: effective address is mem at address 0x60 (EBX)
+run: combine imm32 0x00000001 with r/m32
+run: effective address is 0x60 (EBX)
+run: subop subtract
+run: storing 0x00000009
@ -87,8 +87,8 @@ case 5: {
# op ModR/M SIB displacement immediate
81 eb 01 00 00 00 # subtract 1 from EBX
# ModR/M in binary: 11 (direct mode) 101 (subtract imm32) 011 (dest EBX)
+run: combine imm32 0x00000001 with effective address
+run: effective address is EBX
+run: combine imm32 0x00000001 with r/m32
+run: r/m32 is EBX
+run: subop subtract
+run: storing 0x00000009
@ -117,8 +117,8 @@ case 0x25: { // and imm32 with EAX
# op ModR/M SIB displacement immediate
81 23 0a 0b 0c 0d # and 0x0d0c0b0a with *EBX
# ModR/M in binary: 00 (indirect mode) 100 (and imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (EBX)
+run: combine imm32 0x0d0c0b0a with r/m32
+run: effective address is 0x60 (EBX)
+run: subop and
+run: storing 0x0000000a
@ -136,8 +136,8 @@ case 4: {
# op ModR/M SIB displacement immediate
81 e3 0a 0b 0c 0d # and 0x0d0c0b0a with EBX
# ModR/M in binary: 11 (direct mode) 100 (and imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is EBX
+run: combine imm32 0x0d0c0b0a with r/m32
+run: r/m32 is EBX
+run: subop and
+run: storing 0x0000000a
@ -166,8 +166,8 @@ case 0x0d: { // or imm32 with EAX
# op ModR/M SIB displacement immediate
81 0b 0a 0b 0c 0d # or 0x0d0c0b0a with *EBX
# ModR/M in binary: 00 (indirect mode) 001 (or imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (EBX)
+run: combine imm32 0x0d0c0b0a with r/m32
+run: effective address is 0x60 (EBX)
+run: subop or
+run: storing 0xddccbbaa
@ -183,8 +183,8 @@ case 1: {
# op ModR/M SIB displacement immediate
81 cb 0a 0b 0c 0d # or 0x0d0c0b0a with EBX
# ModR/M in binary: 11 (direct mode) 001 (or imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is EBX
+run: combine imm32 0x0d0c0b0a with r/m32
+run: r/m32 is EBX
+run: subop or
+run: storing 0xddccbbaa
@ -213,8 +213,8 @@ case 0x35: { // xor imm32 with EAX
# op ModR/M SIB displacement immediate
81 33 0a 0b 0c 0d # xor 0x0d0c0b0a with *EBX
# ModR/M in binary: 00 (indirect mode) 110 (xor imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (EBX)
+run: combine imm32 0x0d0c0b0a with r/m32
+run: effective address is 0x60 (EBX)
+run: subop xor
+run: storing 0xddccbbaa
@ -230,8 +230,8 @@ case 6: {
# op ModR/M SIB displacement immediate
81 f3 0a 0b 0c 0d # xor 0x0d0c0b0a with EBX
# ModR/M in binary: 11 (direct mode) 110 (xor imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is EBX
+run: combine imm32 0x0d0c0b0a with r/m32
+run: r/m32 is EBX
+run: subop xor
+run: storing 0xddccbbaa
@ -279,8 +279,8 @@ case 0x3d: { // subtract imm32 from EAX
# op ModR/M SIB displacement immediate
81 fb 07 0b 0c 0d # compare 0x0d0c0b07 with EBX
# ModR/M in binary: 11 (direct mode) 111 (compare imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b07 with effective address
+run: effective address is EBX
+run: combine imm32 0x0d0c0b07 with r/m32
+run: r/m32 is EBX
+run: SF=0; ZF=0; OF=0
:(before "End Op 81 Subops")
@ -300,8 +300,8 @@ case 7: {
# op ModR/M SIB displacement immediate
81 fb 0a 0b 0c 0d # compare 0x0d0c0b0a with EBX
# ModR/M in binary: 11 (direct mode) 111 (compare imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is EBX
+run: combine imm32 0x0d0c0b0a with r/m32
+run: r/m32 is EBX
+run: SF=1; ZF=0; OF=0
:(scenario compare_imm32_with_r32_equal)
@ -309,8 +309,8 @@ case 7: {
# op ModR/M SIB displacement immediate
81 fb 0a 0b 0c 0d # compare 0x0d0c0b0a with EBX
# ModR/M in binary: 11 (direct mode) 111 (compare imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is EBX
+run: combine imm32 0x0d0c0b0a with r/m32
+run: r/m32 is EBX
+run: SF=0; ZF=1; OF=0
:(scenario compare_imm32_with_mem_at_r32_greater)
@ -319,8 +319,8 @@ case 7: {
# op ModR/M SIB displacement immediate
81 3b 07 0b 0c 0d # compare 0x0d0c0b07 with *EBX
# ModR/M in binary: 00 (indirect mode) 111 (compare imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b07 with effective address
+run: effective address is mem at address 0x60 (EBX)
+run: combine imm32 0x0d0c0b07 with r/m32
+run: effective address is 0x60 (EBX)
+run: SF=0; ZF=0; OF=0
:(scenario compare_imm32_with_mem_at_r32_lesser)
@ -329,8 +329,8 @@ case 7: {
# op ModR/M SIB displacement immediate
81 3b 0a 0b 0c 0d # compare 0x0d0c0b0a with *EBX
# ModR/M in binary: 00 (indirect mode) 111 (compare imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (EBX)
+run: combine imm32 0x0d0c0b0a with r/m32
+run: effective address is 0x60 (EBX)
+run: SF=1; ZF=0; OF=0
:(scenario compare_imm32_with_mem_at_r32_equal)
@ -340,8 +340,8 @@ case 7: {
# op ModR/M SIB displacement immediate
81 3b 0a 0b 0c 0d # compare 0x0d0c0b0a with *EBX
# ModR/M in binary: 00 (indirect mode) 111 (compare imm32) 011 (dest EBX)
+run: combine imm32 0x0d0c0b0a with effective address
+run: effective address is mem at address 0x60 (EBX)
+run: combine imm32 0x0d0c0b0a with r/m32
+run: effective address is 0x60 (EBX)
+run: SF=0; ZF=1; OF=0
//:: copy (mov)
@ -374,14 +374,14 @@ case 0xbf: { // copy imm32 to r32
# op ModR/M SIB displacement immediate
c7 03 0a 0b 0c 0d # copy 0x0d0c0b0a to *EBX
# ModR/M in binary: 00 (indirect mode) 000 (unused) 011 (dest EBX)
+run: copy imm32 0x0d0c0b0a to effective address
+run: effective address is mem at address 0x60 (EBX)
+run: copy imm32 0x0d0c0b0a to r/m32
+run: effective address is 0x60 (EBX)
:(before "End Single-Byte Opcodes")
case 0xc7: { // copy imm32 to r32
uint8_t modrm = next();
int32_t arg2 = imm32();
trace(2, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to effective address" << end();
trace(2, "run") << "copy imm32 0x" << HEXWORD << arg2 << " to r/m32" << end();
int32_t* arg1 = effective_address(modrm);
*arg1 = arg2;
break;

View File

@ -8,8 +8,8 @@
01 1c 20 # add EBX to *EAX
# ModR/M in binary: 00 (indirect mode) 011 (src EBX) 100 (dest in SIB)
# SIB in binary: 00 (scale 1) 100 (no index) 000 (base EAX)
+run: add EBX to effective address
+run: effective address is mem at address 0x60 (EAX)
+run: add EBX to r/m32
+run: effective address is 0x60 (EAX)
+run: storing 0x00000011
:(before "End Mod 0 Special-cases")
@ -45,13 +45,13 @@ uint32_t effective_address_from_sib(uint8_t mod) {
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 << " (" << rname(base) << ")" << end();
trace(2, "run") << "effective address is 0x" << std::hex << Reg[base].u << " (" << rname(base) << ")" << end();
return Reg[base].u;
}
else {
uint8_t scale = (1 << (sib>>6));
uint32_t addr = Reg[base].u + Reg[index].i*scale; // treat index register as signed. Maybe base as well? But we'll always ensure it's non-negative.
trace(2, "run") << "effective address is mem at address 0x" << std::hex << addr << " (" << rname(base) << " + " << rname(index) << "*" << NUM(scale) << ")" << end();
trace(2, "run") << "effective address is 0x" << std::hex << addr << " (" << rname(base) << " + " << rname(index) << "*" << NUM(scale) << ")" << end();
return addr;
}
}
@ -65,6 +65,6 @@ uint32_t effective_address_from_sib(uint8_t mod) {
01 1c 08 # add EBX to *(EAX+ECX)
# ModR/M in binary: 00 (indirect mode) 011 (src EBX) 100 (dest in SIB)
# SIB in binary: 00 (scale 1) 001 (index ECX) 000 (base EAX)
+run: add EBX to effective address
+run: effective address is mem at address 0x60 (EAX + ECX*1)
+run: add EBX to r/m32
+run: effective address is 0x60 (EAX + ECX*1)
+run: storing 0x00000011

View File

@ -28,15 +28,15 @@ case 0xe8: { // call imm32 relative to next EIP
# op ModR/M SIB displacement immediate
ff d3 # call function offset at EBX
# next EIP is 3
+run: call to effective address
+run: effective address is EBX
+run: call to r/m32
+run: r/m32 is EBX
+run: decrementing ESP to 0x00000060
+run: pushing value 0x00000003
+run: jumping to 0x000000a3
:(before "End Op ff Subops")
case 2: { // call function pointer at r/m32
trace(2, "run") << "call to effective address" << end();
trace(2, "run") << "call to r/m32" << end();
int32_t* offset = effective_address(modrm);
push(EIP);
EIP += *offset;
@ -51,8 +51,8 @@ case 2: { // call function pointer at r/m32
# op ModR/M SIB displacement immediate
ff 13 # call function offset at *EBX
# next EIP is 3
+run: call to effective address
+run: effective address is mem at address 0x10 (EBX)
+run: call to r/m32
+run: effective address is 0x10 (EBX)
+run: decrementing ESP to 0x00000060
+run: pushing value 0x00000003
+run: jumping to 0x000000a3