You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GameBoy模拟器0xCB 0x19指令实现异常求助

问题分析与修复

你的实现错误在于RR指令的逻辑顺序——GameBoy的RR r指令是将**指令执行前的进位标志(C)**移入寄存器的最高位(bit7),而不是你现在用的指令执行后更新的进位值。

错误原因拆解

当前你的代码流程:

  1. 取寄存器的bit0,将其设为新的进位标志
  2. 寄存器右移1位
  3. 用**新的进位值(原bit0)**设置寄存器的bit7

但正确的RR r指令流程(来自GameBoy官方文档):

  1. 先保存指令执行前的旧进位标志(old_carry)
  2. 将寄存器的bit0值设为新的进位标志
  3. 寄存器右移1位(逻辑右移,高位补0)
  4. 将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 03:30:28