From 1c06541a85fadbc5b9fc0a3bfee10cec3c8e5667 Mon Sep 17 00:00:00 2001 From: iximeow Date: Sat, 21 Aug 2021 19:58:19 -0700 Subject: improve relative branch offset formatting for DisplayStyle::C --- CHANGELOG | 1 + src/long_mode/display.rs | 107 ++++++++++++++++++++++++++++++++++++++++-- src/protected_mode/display.rs | 107 ++++++++++++++++++++++++++++++++++++++++-- src/real_mode/display.rs | 107 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 313 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0febd15..c5fcfd0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -16,6 +16,7 @@ this circumstance. * correct `rex.b` incorrectly applying to the `*ax` register - `4f91` is `xchg rax, r9`, not `xchg r8, r9`. * correct `nop` incorrectly ignoring `rex.b` - `4190` is `xchg rax, r8`, not `nop`. +* `DisplayStyle::C` now has rules to nicely display `jCC`, `jmp`, `call`, `loop*`, and `j*cxz` instructions. ## 1.0.4 diff --git a/src/long_mode/display.rs b/src/long_mode/display.rs index 7bbd83f..181217c 100644 --- a/src/long_mode/display.rs +++ b/src/long_mode/display.rs @@ -3463,7 +3463,7 @@ fn contextualize_intel(instr: &Instruction, colors: Ok(()) } -fn contextualize_c(instr: &Instruction, _colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { +fn contextualize_c(instr: &Instruction, colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { let mut brace_count = 0; let mut prefixed = false; @@ -3509,6 +3509,26 @@ fn contextualize_c(instr: &Instruction, _colors: &Y } } + fn write_jmp_operand(op: Operand, colors: &Y, out: &mut T) -> fmt::Result { + match op { + Operand::ImmediateI8(rel) => { + if rel >= 0 { + write!(out, "$+{}", colors.number(signed_i32_hex(rel as i32))) + } else { + write!(out, "${}", colors.number(signed_i32_hex(rel as i32))) + } + } + Operand::ImmediateI32(rel) => { + if rel >= 0 { + write!(out, "$+{}", colors.number(signed_i32_hex(rel))) + } else { + write!(out, "${}", colors.number(signed_i32_hex(rel))) + } + } + _ => { unreachable!() } + } + } + match instr.opcode { Opcode::Invalid => { out.write_str("invalid")?; }, Opcode::MOVS => { @@ -3662,9 +3682,90 @@ fn contextualize_c(instr: &Instruction, _colors: &Y write!(out, "{}--", instr.operand(0))?; } } + Opcode::JMP => { + out.write_str("jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JRCXZ => { + out.write_str("if rcx == 0 then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::LOOP => { + out.write_str("rcx--; if rcx != 0 then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::LOOPZ => { + out.write_str("rcx--; if rcx != 0 and zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::LOOPNZ => { + out.write_str("rcx--; if rcx != 0 and !zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JO => { + out.write_str("if _(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNO => { + out.write_str("if _(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JB => { + out.write_str("if /* unsigned */ below(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNB => { + out.write_str("if /* unsigned */ above_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JZ => { + out.write_str("if zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNZ => { + out.write_str("if !zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNA => { + out.write_str("if /* unsigned */ below_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JA => { + out.write_str("if /* unsigned */ above(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JS => { + out.write_str("if signed(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNS => { + out.write_str("if !signed(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JP => { + out.write_str("if parity(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNP => { + out.write_str("if !parity(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JL => { + out.write_str("if /* signed */ less(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JGE => { + out.write_str("if /* signed */ greater_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JLE => { + out.write_str("if /* signed */ less_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, Opcode::JG => { - write!(out, "if greater(rflags) then jmp {}", instr.operand(0))?; - } + out.write_str("if /* signed */ greater(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, Opcode::NOP => { write!(out, "nop")?; } diff --git a/src/protected_mode/display.rs b/src/protected_mode/display.rs index 33c0cda..dac3684 100644 --- a/src/protected_mode/display.rs +++ b/src/protected_mode/display.rs @@ -3476,7 +3476,7 @@ fn contextualize_intel(instr: &Instruction, colors: Ok(()) } -fn contextualize_c(instr: &Instruction, _colors: &Y, _address: u32, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { +fn contextualize_c(instr: &Instruction, colors: &Y, _address: u32, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { let mut brace_count = 0; let mut prefixed = false; @@ -3522,6 +3522,26 @@ fn contextualize_c(instr: &Instruction, _colors: &Y } } + fn write_jmp_operand(op: Operand, colors: &Y, out: &mut T) -> fmt::Result { + match op { + Operand::ImmediateI8(rel) => { + if rel >= 0 { + write!(out, "$+{}", colors.number(signed_i32_hex(rel as i32))) + } else { + write!(out, "${}", colors.number(signed_i32_hex(rel as i32))) + } + } + Operand::ImmediateI32(rel) => { + if rel >= 0 { + write!(out, "$+{}", colors.number(signed_i32_hex(rel))) + } else { + write!(out, "${}", colors.number(signed_i32_hex(rel))) + } + } + _ => { unreachable!() } + } + } + match instr.opcode { Opcode::Invalid => { out.write_str("invalid")?; }, Opcode::MOVS => { @@ -3675,9 +3695,90 @@ fn contextualize_c(instr: &Instruction, _colors: &Y write!(out, "{}--", instr.operand(0))?; } } + Opcode::JMP => { + out.write_str("jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JECXZ => { + out.write_str("if ecx == 0 then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::LOOP => { + out.write_str("ecx--; if ecx != 0 then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::LOOPZ => { + out.write_str("ecx--; if ecx != 0 and zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::LOOPNZ => { + out.write_str("ecx--; if ecx != 0 and !zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JO => { + out.write_str("if _(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNO => { + out.write_str("if _(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JB => { + out.write_str("if /* unsigned */ below(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNB => { + out.write_str("if /* unsigned */ above_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JZ => { + out.write_str("if zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNZ => { + out.write_str("if !zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNA => { + out.write_str("if /* unsigned */ below_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JA => { + out.write_str("if /* unsigned */ above(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JS => { + out.write_str("if signed(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNS => { + out.write_str("if !signed(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JP => { + out.write_str("if parity(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNP => { + out.write_str("if !parity(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JL => { + out.write_str("if /* signed */ less(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JGE => { + out.write_str("if /* signed */ greater_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JLE => { + out.write_str("if /* signed */ less_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, Opcode::JG => { - write!(out, "if greater(eflags) then jmp {}", instr.operand(0))?; - } + out.write_str("if /* signed */ greater(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, Opcode::NOP => { write!(out, "nop")?; } diff --git a/src/real_mode/display.rs b/src/real_mode/display.rs index 3a9fddc..1065255 100644 --- a/src/real_mode/display.rs +++ b/src/real_mode/display.rs @@ -3476,7 +3476,7 @@ fn contextualize_intel(instr: &Instruction, colors: Ok(()) } -fn contextualize_c(instr: &Instruction, _colors: &Y, _address: u32, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { +fn contextualize_c(instr: &Instruction, colors: &Y, _address: u32, _context: Option<&NoContext>, out: &mut T) -> fmt::Result { let mut brace_count = 0; let mut prefixed = false; @@ -3522,6 +3522,26 @@ fn contextualize_c(instr: &Instruction, _colors: &Y } } + fn write_jmp_operand(op: Operand, colors: &Y, out: &mut T) -> fmt::Result { + match op { + Operand::ImmediateI8(rel) => { + if rel >= 0 { + write!(out, "$+{}", colors.number(signed_i32_hex(rel as i32))) + } else { + write!(out, "${}", colors.number(signed_i32_hex(rel as i32))) + } + } + Operand::ImmediateI32(rel) => { + if rel >= 0 { + write!(out, "$+{}", colors.number(signed_i32_hex(rel))) + } else { + write!(out, "${}", colors.number(signed_i32_hex(rel))) + } + } + _ => { unreachable!() } + } + } + match instr.opcode { Opcode::Invalid => { out.write_str("invalid")?; }, Opcode::MOVS => { @@ -3675,9 +3695,90 @@ fn contextualize_c(instr: &Instruction, _colors: &Y write!(out, "{}--", instr.operand(0))?; } } + Opcode::JMP => { + out.write_str("jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JCXZ => { + out.write_str("if cx == 0 then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::LOOP => { + out.write_str("cx--; if cx != 0 then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::LOOPZ => { + out.write_str("cx--; if cx != 0 and zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::LOOPNZ => { + out.write_str("cx--; if cx != 0 and !zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JO => { + out.write_str("if _(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNO => { + out.write_str("if _(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JB => { + out.write_str("if /* unsigned */ below(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNB => { + out.write_str("if /* unsigned */ above_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JZ => { + out.write_str("if zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNZ => { + out.write_str("if !zero(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNA => { + out.write_str("if /* unsigned */ below_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JA => { + out.write_str("if /* unsigned */ above(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JS => { + out.write_str("if signed(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNS => { + out.write_str("if !signed(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JP => { + out.write_str("if parity(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JNP => { + out.write_str("if !parity(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JL => { + out.write_str("if /* signed */ less(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JGE => { + out.write_str("if /* signed */ greater_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, + Opcode::JLE => { + out.write_str("if /* signed */ less_or_equal(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, Opcode::JG => { - write!(out, "if greater(eflags) then jmp {}", instr.operand(0))?; - } + out.write_str("if /* signed */ greater(rflags) then jmp ")?; + write_jmp_operand(instr.operand(0), colors, out)?; + }, Opcode::NOP => { write!(out, "nop")?; } -- cgit v1.1