GameBoy模拟器0xCB 0x19指令实现异常求助
问题分析与修复
你的实现错误在于RR指令的逻辑顺序——GameBoy的RR r指令是将**指令执行前的进位标志(C)**移入寄存器的最高位(bit7),而不是你现在用的指令执行后更新的进位值。
错误原因拆解
当前你的代码流程:
- 取寄存器的bit0,将其设为新的进位标志
- 寄存器右移1位
- 用**新的进位值(原bit0)**设置寄存器的bit7
但正确的RR r指令流程(来自GameBoy官方文档):
- 先保存指令执行前的旧进位标志(old_carry)
- 将寄存器的bit0值设为新的进位标志
- 寄存器右移1位(逻辑右移,高位补0)
- 将
old_carry写入寄存器的bit7
你的测试案例中,执行RR C前:
- C寄存器值为
0x47(二进制01000111) - 进位标志为
0
按你的代码执行会得到错误的0xA3,但按正确逻辑执行后,最终结果就是日志里的0x23。
修复后的代码
pub fn rr_reg8(&mut self, register_name: RegisterName, register_byte: RegisterByteName) -> u64 { self.clear_flag(Flag::HalfCarry); self.clear_flag(Flag::Subtraction); // 保存指令执行前的旧进位标志 let old_carry = self.check_flag(Flag::Carry); // 将寄存器的bit0设为新的进位标志 let shifted_bit = utils::data::check_bit(self.registers[register_name][register_byte], 0); if shifted_bit { self.set_flag(Flag::Carry); } else { self.clear_flag(Flag::Carry); } // 寄存器右移1位 self.registers[register_name][register_byte] >>= 1; // 将旧进位写入寄存器的bit7 if old_carry { utils::data::set_bit(&mut self.registers[register_name][register_byte], 7); } else { utils::data::clear_bit(&mut self.registers[register_name][register_byte], 7); } // 更新零标志 if self.registers[register_name][register_byte] == 0 { self.set_flag(Flag::Zero); } else { self.clear_flag(Flag::Zero); } 8 }
额外验证点
可以测试另一种场景:执行前进位为1,寄存器值为0x00,执行RR r后应该得到0x80,进位设为0。用修复后的代码可以得到正确结果。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

