aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/long_mode/display.rs28
-rw-r--r--src/protected_mode/display.rs28
-rw-r--r--src/real_mode/display.rs28
-rw-r--r--test/long_mode/mod.rs17
-rw-r--r--test/protected_mode/mod.rs17
-rw-r--r--test/real_mode/mod.rs17
6 files changed, 111 insertions, 24 deletions
diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs
index 68189f0..59efe38 100644
--- a/src/long_mode/display.rs
+++ b/src/long_mode/display.rs
@@ -3338,6 +3338,34 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:
out.write_str(" ")?;
let x = Operand::from_spec(instr, instr.operands[0]);
+
+ const RELATIVE_BRANCHES: [Opcode; 21] = [
+ Opcode::JMP, Opcode::JRCXZ,
+ Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,
+ Opcode::JO, Opcode::JNO,
+ Opcode::JB, Opcode::JNB,
+ Opcode::JZ, Opcode::JNZ,
+ Opcode::JNA, Opcode::JA,
+ Opcode::JS, Opcode::JNS,
+ Opcode::JP, Opcode::JNP,
+ Opcode::JL, Opcode::JGE,
+ Opcode::JLE, Opcode::JG,
+ ];
+
+ if instr.operands[0] == OperandSpec::ImmI8 || instr.operands[0] == OperandSpec::ImmI32 {
+ if RELATIVE_BRANCHES.contains(&instr.opcode) {
+ return match x {
+ Operand::ImmediateI8(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel as i32)))
+ }
+ Operand::ImmediateI32(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel)))
+ }
+ _ => { unreachable!() }
+ };
+ }
+ }
+
if x.is_memory() {
out.write_str(MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?;
out.write_str(" ")?;
diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs
index 987221e..72bfcb4 100644
--- a/src/protected_mode/display.rs
+++ b/src/protected_mode/display.rs
@@ -3351,6 +3351,34 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:
out.write_str(" ")?;
let x = Operand::from_spec(instr, instr.operands[0]);
+
+ const RELATIVE_BRANCHES: [Opcode; 21] = [
+ Opcode::JMP, Opcode::JECXZ,
+ Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,
+ Opcode::JO, Opcode::JNO,
+ Opcode::JB, Opcode::JNB,
+ Opcode::JZ, Opcode::JNZ,
+ Opcode::JNA, Opcode::JA,
+ Opcode::JS, Opcode::JNS,
+ Opcode::JP, Opcode::JNP,
+ Opcode::JL, Opcode::JGE,
+ Opcode::JLE, Opcode::JG,
+ ];
+
+ if instr.operands[0] == OperandSpec::ImmI8 || instr.operands[0] == OperandSpec::ImmI32 {
+ if RELATIVE_BRANCHES.contains(&instr.opcode) {
+ return match x {
+ Operand::ImmediateI8(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel as i32)))
+ }
+ Operand::ImmediateI32(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel)))
+ }
+ _ => { unreachable!() }
+ };
+ }
+ }
+
if x.is_memory() {
out.write_str(MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?;
out.write_str(" ")?;
diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs
index 9ba8284..f514974 100644
--- a/src/real_mode/display.rs
+++ b/src/real_mode/display.rs
@@ -3351,6 +3351,34 @@ fn contextualize_intel<T: fmt::Write, Y: YaxColors>(instr: &Instruction, colors:
out.write_str(" ")?;
let x = Operand::from_spec(instr, instr.operands[0]);
+
+ const RELATIVE_BRANCHES: [Opcode; 21] = [
+ Opcode::JMP, Opcode::JCXZ,
+ Opcode::LOOP, Opcode::LOOPZ, Opcode::LOOPNZ,
+ Opcode::JO, Opcode::JNO,
+ Opcode::JB, Opcode::JNB,
+ Opcode::JZ, Opcode::JNZ,
+ Opcode::JNA, Opcode::JA,
+ Opcode::JS, Opcode::JNS,
+ Opcode::JP, Opcode::JNP,
+ Opcode::JL, Opcode::JGE,
+ Opcode::JLE, Opcode::JG,
+ ];
+
+ if instr.operands[0] == OperandSpec::ImmI8 || instr.operands[0] == OperandSpec::ImmI32 {
+ if RELATIVE_BRANCHES.contains(&instr.opcode) {
+ return match x {
+ Operand::ImmediateI8(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel as i32)))
+ }
+ Operand::ImmediateI32(rel) => {
+ write!(out, "$+{}", colors.number(signed_i32_hex(rel)))
+ }
+ _ => { unreachable!() }
+ };
+ }
+ }
+
if x.is_memory() {
out.write_str(MEM_SIZE_STRINGS[instr.mem_size as usize - 1])?;
out.write_str(" ")?;
diff --git a/test/long_mode/mod.rs b/test/long_mode/mod.rs
index bfe21bd..61ea63d 100644
--- a/test/long_mode/mod.rs
+++ b/test/long_mode/mod.rs
@@ -1208,10 +1208,10 @@ fn test_prefixes() {
#[test]
fn test_control_flow() {
- test_display(&[0x73, 0x31], "jnb 0x31");
- test_display(&[0x72, 0x5a], "jb 0x5a");
- test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna 0x18b");
- test_display(&[0x74, 0x47], "jz 0x47");
+ test_display(&[0x73, 0x31], "jnb $+0x31");
+ test_display(&[0x72, 0x5a], "jb $+0x5a");
+ test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna $+0x18b");
+ test_display(&[0x74, 0x47], "jz $+0x47");
test_display(&[0xff, 0x15, 0x7e, 0x72, 0x24, 0x00], "call qword [rip + 0x24727e]");
test_display(&[0xff, 0x24, 0xcd, 0x70, 0xa0, 0xbc, 0x01], "jmp qword [rcx * 8 + 0x1bca070]");
test_display(&[0xff, 0xe0], "jmp rax");
@@ -1219,10 +1219,11 @@ fn test_control_flow() {
test_display(&[0x67, 0xff, 0xe0], "jmp rax");
test_invalid(&[0xff, 0xd8]);
test_display(&[0xff, 0x18], "callf mword [rax]");
- test_display(&[0xe0, 0x12], "loopnz 0x12");
- test_display(&[0xe1, 0x12], "loopz 0x12");
- test_display(&[0xe2, 0x12], "loop 0x12");
- test_display(&[0xe3, 0x12], "jrcxz 0x12");
+ test_display(&[0xe0, 0x12], "loopnz $+0x12");
+ test_display(&[0xe1, 0x12], "loopz $+0x12");
+ test_display(&[0xe2, 0x12], "loop $+0x12");
+ test_display(&[0xe3, 0x12], "jrcxz $+0x12");
+ test_display(&[0xe3, 0xf0], "jrcxz $+-0x10");
test_display(&[0xc3], "ret");
}
diff --git a/test/protected_mode/mod.rs b/test/protected_mode/mod.rs
index c03a19d..5ed69ed 100644
--- a/test/protected_mode/mod.rs
+++ b/test/protected_mode/mod.rs
@@ -1094,10 +1094,10 @@ fn test_prefixes() {
#[test]
fn test_control_flow() {
- test_display(&[0x73, 0x31], "jnb 0x31");
- test_display(&[0x72, 0x5a], "jb 0x5a");
- test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna 0x18b");
- test_display(&[0x74, 0x47], "jz 0x47");
+ test_display(&[0x73, 0x31], "jnb $+0x31");
+ test_display(&[0x72, 0x5a], "jb $+0x5a");
+ test_display(&[0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00], "jna $+0x18b");
+ test_display(&[0x74, 0x47], "jz $+0x47");
test_display(&[0xff, 0x15, 0x7e, 0x72, 0x24, 0x00], "call dword [0x24727e]");
test_display(&[0xff, 0x24, 0xcd, 0x70, 0xa0, 0xbc, 0x01], "jmp dword [ecx * 8 + 0x1bca070]");
test_display(&[0xff, 0xe0], "jmp eax");
@@ -1105,10 +1105,11 @@ fn test_control_flow() {
test_display(&[0x67, 0xff, 0xe0], "jmp eax");
test_invalid(&[0xff, 0xd8]);
test_display(&[0xff, 0x18], "callf far [eax]");
- test_display(&[0xe0, 0x12], "loopnz 0x12");
- test_display(&[0xe1, 0x12], "loopz 0x12");
- test_display(&[0xe2, 0x12], "loop 0x12");
- test_display(&[0xe3, 0x12], "jecxz 0x12");
+ test_display(&[0xe0, 0x12], "loopnz $+0x12");
+ test_display(&[0xe1, 0x12], "loopz $+0x12");
+ test_display(&[0xe2, 0x12], "loop $+0x12");
+ test_display(&[0xe3, 0x12], "jecxz $+0x12");
+ test_display(&[0xe3, 0xf0], "jecxz $+-0x10");
test_display(&[0xc3], "ret");
}
diff --git a/test/real_mode/mod.rs b/test/real_mode/mod.rs
index 82ccfab..6005f07 100644
--- a/test/real_mode/mod.rs
+++ b/test/real_mode/mod.rs
@@ -262,7 +262,7 @@ fn test_real_mode() {
test_display(&[0x0f, 0x7e, 0xcf], "movd edi, mm1");
test_display(&[0x0f, 0x7f, 0x0f], "movq qword [bx], mm1");
test_display(&[0x0f, 0x7f, 0xcf], "movq mm7, mm1");
- test_display(&[0x0f, 0x86, 0x8b, 0x01], "jna 0x18b");
+ test_display(&[0x0f, 0x86, 0x8b, 0x01], "jna $+0x18b");
test_display(&[0x0f, 0x97, 0x00], "seta byte [bx + si]");
test_display(&[0x0f, 0x97, 0x08], "seta byte [bx + si]");
test_display(&[0x0f, 0x97, 0xc0], "seta al");
@@ -16924,9 +16924,9 @@ fn test_real_mode() {
test_display(&[0x67, 0xff, 0xe0], "jmp ax");
test_display(&[0x68, 0x7f, 0x63], "push 0x637f");
test_display(&[0x6b, 0x43, 0x6f, 0x6d], "imul ax, word [bp + di + 0x6f], 0x6d");
- test_display(&[0x72, 0x5a], "jb 0x5a");
- test_display(&[0x73, 0x31], "jnb 0x31");
- test_display(&[0x74, 0x47], "jz 0x47");
+ test_display(&[0x72, 0x5a], "jb $+0x5a");
+ test_display(&[0x73, 0x31], "jnb $+0x31");
+ test_display(&[0x74, 0x47], "jz $+0x47");
test_display(&[0x81, 0xec, 0x10, 0x03], "sub sp, 0x310");
test_display(&[0x66, 0x81, 0xec, 0x10, 0x03, 0x00, 0x00], "sub esp, 0x310");
test_display(&[0x83, 0xf8, 0xff], "cmp ax, -0x1");
@@ -17752,10 +17752,11 @@ fn test_real_mode() {
test_display(&[0xdf, 0xe0], "fnstsw ax");
test_display(&[0xdf, 0xeb], "fucomip st(0), st(3)");
test_display(&[0xdf, 0xf3], "fcomip st(0), st(3)");
- test_display(&[0xe0, 0x12], "loopnz 0x12");
- test_display(&[0xe1, 0x12], "loopz 0x12");
- test_display(&[0xe2, 0x12], "loop 0x12");
- test_display(&[0xe3, 0x12], "jcxz 0x12");
+ test_display(&[0xe0, 0x12], "loopnz $+0x12");
+ test_display(&[0xe1, 0x12], "loopz $+0x12");
+ test_display(&[0xe2, 0x12], "loop $+0x12");
+ test_display(&[0xe3, 0x12], "jcxz $+0x12");
+ test_display(&[0xe3, 0xf0], "jcxz $+-0x10");
test_display(&[0xe4, 0x99], "in al, 0x99");
test_display(&[0xe5, 0x99], "in ax, 0x99");
test_display(&[0xe6, 0x99], "out 0x99, al");