Intel 8086 - Simulating Register to Register MOV instructions
The problem
In the previous blog post, I implemented the logic for immediate-to-register moves. However, I later realised that while the immediate-to-register move works correctly, the register-to-register move does not.
That is clearly false. It seems like the state doesn’t persist? I have no idea why this is happening. I’ll jump into CLion and investigate.
The question is, why is this code incorrect?
let reg = get_register_state(®_register, ®isters);
let rm = get_register_state(&rm_register, ®isters);
if reg_is_dest {
update_register_value(reg.register, rm.updated_value, &mut registers, instruction, memory_mode, mnemonic);
} else {
let rm = get_register_state(&rm_register, ®isters);
// in this branch we can just update the value with the immediate.
update_register_value(rm.register, reg.updated_value, &mut registers, instruction, memory_mode, mnemonic);
}
The branch jumps into the update_register_value
function, but it seems that this function does not correctly update the values. This is evident because once we exit the scope of the code snippet, the value does not persist.
I wonder why the value does not get updated when InstructionType
is RegisterMemory
.
pub fn update_register_value(register_to_update: &'static str, value: usize, registers: &mut Vec<Register>, instruction: InstructionType, memory_mode: MemoryModeEnum, mnemonic: &'static str) -> () {
for reg in registers.iter_mut() {
if reg.register == register_to_update {
match instruction {
ImmediateToAccumulatorADD => reg.updated_value += value,
ImmediateToAccumulatorSUB => reg.updated_value -= value,
ImmediateToRegisterMemory => {
match memory_mode {
MemoryModeEnum::RegisterMode => {
match mnemonic {
"mov" => reg.updated_value = value,
"add" => reg.updated_value += value,
"sub" => reg.updated_value -= value,
"cmp" => (),
_ => panic!("Unknown mnemonic {}", mnemonic),
}
}
MemoryModeEnum::MemoryModeNoDisplacement | MemoryModeEnum::MemoryMode8Bit | MemoryModeEnum::MemoryMode16Bit | MemoryModeEnum::DirectMemoryOperation => (),
}
return
},
ImmediateToRegisterMOV => reg.updated_value = value,
_ => () // Conditional jumps, CMP instructions.
}
return
}
}
panic!("Register not found, this should never happen. Register that was not found was {}", register_to_update);
}
BECAUSE IT DOES NOT HAVE A BRANCH FOR THAT CONDITION. No wonder it never updated the values. Let’s update that.
ImmediateToRegisterMemory => {
...
}
// Went into:
ImmediateToRegisterMemory | RegisterMemory => {
...
}
Let’s try that.
It worked.
Right, Listing_0044 is complete, where instead of an immediate-to-register move, you had to perform register-to-register operations. This is the reality of programming, and sometimes the problem can be as simple as a missing if statement.
See you in the next one!