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,