14

在浏览 Gameboy 的指令集时,我遇到了如下指令:

LD A, A
LD B, B
LD C, C
LD D, D

...

这些指令中的每一个在此表中都有自己的操作码,这使我认为由于可能的操作码数量的限制,它们具有一定的重要性。

我首先认为它可能会取消引用该寄存器中的指针并将值存储在该指针处(就像在这个问题中一样),但在模拟器中,LD A, A实现为:

Z80._r.a = Z80._r.a

它们似乎对处理器的状态没有影响(只需将寄存器设置为它们自己的值),并且NOP执行的周期数与 a 相同。

为什么这些操作码包含在指令集中,它们的用途是什么?

4

2 回答 2

15

它们简化了解码单元,如果您要检查

7F LD A,A
78 LD A,B
79 LD A,C

对比

47 LD B,A
40 LD B,B
41 LD B,C

对比

4F LD C,A
48 LD C,B
49 LD C,C

您会注意到,底部 3 位保留给源寄存器(值 0-7 B,C,D,E,H,L,(HL),A),它们旁边的 3 位是目标寄存器,同样具有相同的 0-7 含义(因此 0 vs 0 创建LD B,B),顶部两位01选择LD,如果我完美地破译它,从快速浏览中不确定。

人们还期望 then76LD (HL),(HL),这甚至比 更没有意义LD A,A,因此有特殊的逻辑可以抓住那个然后做HALT

所以它是关于指令解码器的简单性,使用相同的位模式来选择源/目标寄存器,以及关于不添加更多晶体管来捕捉same,same情况,除了(HL),(HL)(这可能会在需要内存访问的源和目标上内部失败,所以也许额外的“逻辑”在硬件设计中相当简单。

请记住,早期的 CPU 通常是手工设计的,并且晶体管的总数量必须保持在较低水平,以适应芯片,并便于手工绘制电路并验证其正确性。

编辑:Z80 有大约 8500 个晶体管,您可能需要检查:https ://en.wikipedia.org/wiki/Transistor_count和https://en.wikipedia.org/wiki/Zilog_Z80 ... GameBoy 有一点修改后的 Z80,但总晶体管的数量将非常接近原始值,虽然我没有搜索确切的值,我不确定任天堂将它扩展到多远的未来,也许他们可以甚至已经负担得起20-50k之类的东西,但我对此表示怀疑。


附录:最近我读到了关于俄罗斯 Sinclair ZX Spectrum 克隆的文章,它们是经过大量修改的机器,增加了额外的功率、内存和功能......其中一些正在使用这些ld same,same操作码来控制 DMA 传输,所以这些机器代码使用它们因为nop可能无法正确执行。这与 GameBoy 无关,但如果您有二进制目标是“Sprinter”或类似的俄罗斯 ZX 克隆之一,并且您在反汇编中发现其中之一,请不要自动考虑它们nop,它们可能是实际执行的有效代码的一部分一些东西(很可能是 DMA)。

于 2018-05-05T09:37:18.993 回答
5

这些奇怪的 NOP 指令可以追溯到最初的祖先处理器 Intel 8008。在那个芯片中,它们只是执行寄存器移动指令的结果。允许 MOV A、A 等简化了指令解码器并节省了芯片空间。

从 8080 到 Z80(及更高版本),这些成为保持向后兼容性所必需的。他们甚至以形式幸存到 x86 世界

MOV AL、AL 等

所以大多数现代台式机仍然支持这些奇怪的指令。

注意:我在描述 Intel 机器时使用了 Intel 助记符。请放心,这些组合成与 Zilog 助记符相同的二进制代码。

于 2018-05-21T15:36:50.290 回答