在上一part中,已经了解了实现一个新指令的流程,这一part,我们需要实现全部LD指令
目标:
- 实现全部LD指令,及其所需的全部寻址模式
- 继续体会寻址的过程、CPU取数据和执行指令的步骤
- 了解指令的性质,能够把参考资料翻译成指令的实现(寻址模式、具体逻辑、机器周期开销等)
知识点
- 原项目在指令实现上的一些的问题
- gbemu原项目的寻址模式里,没有考虑读取opcode需要的机器(2位16进制数的opcode=8位2进制数->一个机器周期),忽略了这一点。
- gbemu对于指令原理的讲解很缺失,开发过程中的实现也有问题。比如part4的bus_read16/bus_write16、proc_ld时钟周期开销不对
- 大家学习时注意抓大放小
- 不要太在意这部分,大多数细节最终会忘记的,挑一两个典型指令深入理解,能够在模拟器框架下对着参考资料实现出指令即可。
- 更重要的是理解指令、CPU、总线的关系,CPU执行指令的流程、指令具有哪些性质、一个CPU大概有哪些指令?为什么要这样设计?这些才是有用的问题
- 关于不同的指令参考资料
- 指令表里的周期数是时钟周期,4时钟周期=1机器周期
- gbctr是比较准确、包含伪代码的指令表。其中的周期是机器周期,并给出了每个周期做的事情
- 从零开始的Gameboy模拟器,关于指令性质也有不错的解说
成果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
(base) $ gbemu/gbemu ../../roms/cpu_instrs.gb
Opened: ../../roms/cpu_instrs.gb
Cartridge Loaded:
Title : CPU_INSTRS
Type : 01 (MBC1)
ROM Size : 64 KB
RAM Size : 00
LIC Code : 00 (None)
ROM Vers : 00
Checksum : 3B (PASSED)
Cart loaded..
SDL INIT
TTF INIT
0100: NOP (00 C3 37) A: 01 B: 00 C: 00
0101: JP (C3 37 06) A: 01 B: 00 C: 00
0637: JP (C3 30 04) A: 01 B: 00 C: 00
0430: DI (F3 31 FF) A: 01 B: 00 C: 00
0431: LD (31 FF DF) A: 01 B: 00 C: 00
0434: LD (EA 00 D6) A: 01 B: 00 C: 00
UNSIPPORTED bus_write(D600)
0437: LD (3E 00 E0) A: 01 B: 00 C: 00
0439: <NONE> (E0 07 3E) A: 00 B: 00 C: 00
INVALID INSTRUCTION!
|
可以看到,成功执行了31、EA、3E三种LD指令,并且通过debug输出,发现下一个应该支持的指令为E0
代码实现:
https://github.com/SimpleCodeJust4Fun/CBoy/pull/3