fix: correctly parse jump bytes

Previously only a single byte was read and saved,
but the J-byte means, that the read signed-byte
must be added to the address of the next
instruction.
This commit is contained in:
2025-05-20 10:56:54 +09:00
parent 3fe58e8bac
commit ac78e9705c
2 changed files with 64 additions and 56 deletions

View File

@@ -103,6 +103,26 @@ impl Disassembler {
u16::from_le_bytes([byte1, byte2])
}
/// Parse a single byte of binary and advance the offset.
/// The returned IByte contains a relative offset to be added to the address
/// of the subsequent instruction.
pub fn parse_j_byte(&mut self) -> isize {
// first interpret as 2-complement, then cast for addition
let byte = self.parse_byte() as IByte as isize;
let next_addr = (self.offset + 1) as isize;
byte + next_addr
}
/// Parse a single byte of binary and advance the offset.
/// The returned IByte contains a relative offset to be added to the address
/// of the subsequent instruction.
pub fn parse_j_word(&mut self) -> isize {
// first interpret as 2-complement, then cast for addition
let word = self.parse_word() as IWord as isize;
let next_addr = (self.offset + 1) as isize;
word + next_addr
}
/// Takes in a modrm byte and returns mod, reg and r/m.
fn deconstruct_modrm_byte(modrm: u8) -> (u8, u8, u8) {
let mode = (modrm >> 6) & 0b11;
@@ -442,22 +462,22 @@ impl Disassembler {
0x60..=0x6F => return Err(DisasmError::OpcodeUndefined(opcode)),
0x70 => Mnemonic::JO(self.parse_byte() as IByte),
0x71 => Mnemonic::JNO(self.parse_byte() as IByte),
0x72 => Mnemonic::JB(self.parse_byte() as IByte),
0x73 => Mnemonic::JNB(self.parse_byte() as IByte),
0x74 => Mnemonic::JZ(self.parse_byte() as IByte),
0x75 => Mnemonic::JNZ(self.parse_byte() as IByte),
0x76 => Mnemonic::JBE(self.parse_byte() as IByte),
0x77 => Mnemonic::JA(self.parse_byte() as IByte),
0x78 => Mnemonic::JS(self.parse_byte() as IByte),
0x79 => Mnemonic::JNS(self.parse_byte() as IByte),
0x7A => Mnemonic::JPE(self.parse_byte() as IByte),
0x7B => Mnemonic::JPO(self.parse_byte() as IByte),
0x7C => Mnemonic::JL(self.parse_byte() as IByte),
0x7D => Mnemonic::JGE(self.parse_byte() as IByte),
0x7E => Mnemonic::JLE(self.parse_byte() as IByte),
0x7F => Mnemonic::JG(self.parse_byte() as IByte),
0x70 => Mnemonic::JO(self.parse_j_byte()),
0x71 => Mnemonic::JNO(self.parse_j_byte()),
0x72 => Mnemonic::JB(self.parse_j_byte()),
0x73 => Mnemonic::JNB(self.parse_j_byte()),
0x74 => Mnemonic::JZ(self.parse_j_byte()),
0x75 => Mnemonic::JNZ(self.parse_j_byte()),
0x76 => Mnemonic::JBE(self.parse_j_byte()),
0x77 => Mnemonic::JA(self.parse_j_byte()),
0x78 => Mnemonic::JS(self.parse_j_byte()),
0x79 => Mnemonic::JNS(self.parse_j_byte()),
0x7A => Mnemonic::JPE(self.parse_j_byte()),
0x7B => Mnemonic::JPO(self.parse_j_byte()),
0x7C => Mnemonic::JL(self.parse_j_byte()),
0x7D => Mnemonic::JGE(self.parse_j_byte()),
0x7E => Mnemonic::JLE(self.parse_j_byte()),
0x7F => Mnemonic::JG(self.parse_j_byte()),
// Group 1
0x80 => {
@@ -622,36 +642,24 @@ impl Disassembler {
0xD8..=0xDF => return Err(DisasmError::OpcodeUndefined(opcode)),
0xE0 => Mnemonic::LOOPNZ(self.parse_byte() as IByte),
0xE1 => Mnemonic::LOOPZ(self.parse_byte() as IByte),
0xE2 => Mnemonic::LOOP(self.parse_byte() as IByte),
0xE3 => Mnemonic::JCXZ(self.parse_byte() as IByte),
0xE0 => Mnemonic::LOOPNZ(self.parse_j_byte()),
0xE1 => Mnemonic::LOOPZ(self.parse_j_byte()),
0xE2 => Mnemonic::LOOP(self.parse_j_byte()),
0xE3 => Mnemonic::JCXZ(self.parse_j_byte()),
0xE4 => Mnemonic::IN_AL(self.parse_byte()),
0xE5 => Mnemonic::IN_AX(self.parse_byte()),
0xE6 => Mnemonic::OUT_AL(self.parse_byte()),
0xE7 => Mnemonic::OUT_AX(self.parse_byte()),
0xE8 => Mnemonic::CALL_v(self.parse_word()),
0xE8 => Mnemonic::CALL_v(self.parse_j_word()),
// add to address of next instruction
0xE9 => {
// first interpret as IByte, then cast for addition
let word = self.parse_word() as IByte as isize;
let next_addr = (self.offset + 1) as isize;
Mnemonic::JMP_v(next_addr + word)
}
0xE9 => Mnemonic::JMP_v(self.parse_j_word()),
0xEA => Mnemonic::JMP_p(Pointer {
segment: self.parse_word(),
offset: self.parse_word(),
}),
// add to address of next instruction
0xEB => {
// first interpret as IByte, then cast for addition
let byte = self.parse_byte() as IByte as isize;
let next_addr = (self.offset + 1) as isize;
Mnemonic::JMP_b(next_addr + byte)
}
0xEB => Mnemonic::JMP_b(self.parse_j_byte()),
0xEC => Mnemonic::IN_ALDX,
0xED => Mnemonic::IN_AXDX,

View File

@@ -165,26 +165,26 @@ pub enum Mnemonic {
DEC_Reg(Register),
DEC_Mod(ModRmTarget),
// Jumps
JO(IByte),
JNO(IByte),
JB(IByte),
JNB(IByte),
JZ(IByte),
JNZ(IByte),
JBE(IByte),
JA(IByte),
JS(IByte),
JNS(IByte),
JPE(IByte),
JPO(IByte),
JL(IByte),
JGE(IByte),
JLE(IByte),
JG(IByte),
LOOPNZ(IByte),
LOOPZ(IByte),
LOOP(IByte),
JCXZ(IByte),
JO(isize),
JNO(isize),
JB(isize),
JNB(isize),
JZ(isize),
JNZ(isize),
JBE(isize),
JA(isize),
JS(isize),
JNS(isize),
JPE(isize),
JPO(isize),
JL(isize),
JGE(isize),
JLE(isize),
JG(isize),
LOOPNZ(isize),
LOOPZ(isize),
LOOP(isize),
JCXZ(isize),
// TEST
TEST(ModRmTarget, Register),
@@ -231,7 +231,7 @@ pub enum Mnemonic {
CWD,
// CALL
CALL_p(Pointer),
CALL_v(Word),
CALL_v(isize),
CALL_Mod(ModRmTarget),
// JUMP
JMP_p(Pointer),