Intel 8080模拟器LHLD指令未正确赋值HL寄存器问题
Intel 8080模拟器LHLD指令异常排查思路
问题明确
开发Intel 8080模拟器时,TST8080.COM、CPUTEST.COM、8080PRE.COM三个测试文件均正常执行,但8080EXM.COM中LHLD指令出现异常:执行LHLD前PC值为0x0006,nextWord函数返回0,导致HL寄存器被错误赋值为0x0000。手动在lhld函数中重复调用一次readWord(s, nextWord(s))后,8080EXM.COM可部分执行,但前序测试文件报错。
排查步骤
1. 验证8080EXM.COM内存加载正确性
- 检查0x0006、0x0007地址的内存值:LHLD是3字节指令(1字节操作码+2字节目标地址),
nextWord读取的是PC指向的两个连续字节(即指令后的目标地址)。若这两个字节均为0,nextWord返回0是逻辑结果,但不符合测试文件的预期行为,需确认8080EXM.COM加载后,0x0005(操作码地址)、0x0006、0x0007的内存值是否与原始文件一致。 - 排查内存加载逻辑:确认COM文件的加载起始地址是否正确(Altair平台COM文件通常加载至0x0000或0x0100),是否存在文件截断、地址偏移或内存初始化错误,导致目标地址区域的字节被意外置0。
2. 校验字节序处理逻辑
8080为小端序架构,16位数据的低字节存储在低地址,高字节存储在高地址:
- 检查
readWord实现:当前代码(readByte(s, addr + 1) << 8 | readByte(s, addr))是将addr+1作为高字节、addr作为低字节,符合小端序的16位数据读取规则。但需确认8080EXM.COM中LHLD指令后的目标地址字节是否被正确解析——若字节序处理反向,会导致读取错误的内存地址,进而返回0。
3. 确认指令执行的PC时序逻辑
模拟器主循环的指令fetch流程直接影响PC的正确性:
- 通常主循环逻辑应为:读取当前PC的操作码 → PC加1 → 调用对应指令处理函数。若执行
lhld时PC未先加1(仍指向操作码地址),则nextWord会错误读取操作码+下一字节作为目标地址,导致地址无效返回0。需核对主循环的PC更新时机是否正确:// 正确的主循环示例 uint8_t opcode = readByte(s, s->pc); s->pc++; execute_instruction(s, opcode); - LHLD指令的PC总增量应为3(1字节操作码+2字节地址),当前
lhld中nextWord会将PC加2,加上主循环的PC加1,总增量为3,符合指令长度要求,需确认该逻辑未被破坏。
4. 排查内存访问的边界与正确性
- 若
nextWord返回0,说明readWord读取的两个字节均为0,需检查readByte函数是否正确处理所有64KB内存地址(0x0000-0xFFFF):是否存在未初始化的内存区域、地址越界访问时默认返回0的逻辑,导致读取目标地址时得到错误值。 - 跟踪内存修改记录:确认在执行LHLD前,0x0006、0x0007地址的内存是否被其他指令意外修改。
5. 分析临时修复的矛盾点
手动重复调用readWord(s, nextWord(s))后,8080EXM.COM可部分执行,但前序测试报错,说明该操作实际让PC多偏移了2字节,刚好跳过了错误的地址区域,但破坏了正常指令的执行流程。这提示:
- 8080EXM.COM中LHLD指令的位置或后续字节可能存在与前序测试文件不同的结构,需对比两个测试文件中LHLD指令的上下文差异。
- 模拟器的指令长度处理可能存在特殊场景的bug,仅在8080EXM.COM的指令序列中触发。
内容的提问来源于stack exchange,提问作者cdunku
相关产品推荐
相关产品推荐

