Assembly 向寄存器自身加载指令的目的是什么?

Assembly 向寄存器自身加载指令的目的是什么?,assembly,memory,emulation,z80,gameboy,Assembly,Memory,Emulation,Z80,Gameboy,在浏览Gameboy的指令集时,我遇到了如下指令: LD A, A LD B, B LD C, C LD D, D ... 这些指令中的每一条都有自己的操作码,这让我觉得它们很重要,因为可能的操作码数量受到限制 我首先想到的可能是取消对该寄存器中的指针的引用,并在该指针处存储值,但在一个,LD a中,a实现为: Z80._r.a = Z80._r.a 它们似乎对处理器的状态没有影响,只是将寄存器设置为它们自己的值,并采用与NOP相同的周期数来执行 为什么这些操作码包含在指令集中?它们有什么

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

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

...
这些指令中的每一条都有自己的操作码,这让我觉得它们很重要,因为可能的操作码数量受到限制

我首先想到的可能是取消对该寄存器中的指针的引用,并在该指针处存储值,但在一个,LD a中,a实现为:

Z80._r.a = Z80._r.a
它们似乎对处理器的状态没有影响,只是将寄存器设置为它们自己的值,并采用与NOP相同的周期数来执行


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

如果您愿意检查的话,它们简化了解码单元

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

vs

您可以注意到,底部的3位是为源寄存器值0-7保留的,B、C、D、E、H、L、HL、A,它们旁边的3位是目标寄存器,同样具有相同的0-7含义,因此0对0创建LD B、B,顶部的两位01选择LD,从快速浏览中不确定我是否完全破译了它

人们也会认为76是LD-HL,HL,这比LD-A,A更不合理,所以有特殊的逻辑来捕捉那个,然后停下来

因此,它是关于指令解码器的简单性,使用相同的位模式选择源/目标寄存器,并且关于不添加更多晶体管来捕获相同的情况,除了HL,HL可能会在需要内存访问的源和目标上内部失效,因此,在硬件设计中,额外的逻辑可能相当简单

请记住,早期的CPU通常是手工设计的,总晶体管的数量必须保持在较低的水平,才能安装在芯片上,并且可以手动绘制电路并验证其正确性

编辑:Z80大约有8500个晶体管,您可能需要检查:和。。。GameBoy对Z80做了一些修改,但晶体管总量将非常接近原始值,尽管我没有寻找确切的值,我也不确定任天堂会将其扩展到多远的未来,也许他们甚至可以负担得起20-50k的价格,但我对此表示怀疑


增编:最近我读到了关于俄罗斯辛克莱ZX频谱克隆的报道,这些克隆是经过大量修改的机器,增加了额外的能量、内存和功能。。。他们中的一些人使用这些相同的操作码来控制DMA传输,所以在这些机器上,使用它们作为nop的代码可能无法正确执行。这不是游戏迷相关的,但是如果你有二分之一的短跑运动员或类似的俄罗斯ZX克隆,你发现其中之一在拆卸,不要认为他们自动NOP,它们可能是有效代码的一部分,实际上很可能与DMA有关。

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

从8080到Z80以及更高版本,这些都是保持向后兼容性所必需的。他们甚至以这种形式进入了x86世界

莫夫·艾尔、艾尔等

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


注意:我在描述英特尔计算机时使用了英特尔助记符。请确保这些代码与Zilog助记符的二进制代码相同。

我想它们的唯一目的是通过避免特殊情况使指令解码器更易于实现。有些位总是表示A,就是这样。nop和这些位的操作码是一样的吗?在x86上,单字节NOP 0x90是xchg ax,ax单字节xchg的特例,带有ax短格式,0x90..0x97。@PeterCordes No NOP操作码是0x00,其他所有操作码都是唯一的。要澄清一点,在eZ80上,向后兼容,这些指令实际上是用于特殊目的的,基本上是在指令应该以特殊模式从例程的其余部分使用时发出信号。@PeterCordes将00设为NOP是很重要的:在某些机器(如ZX80)中,视频逻辑使用CPU作为地址生成器,只需强制数据总线降低CPU的电平即可执行NOPs。
47 LD B,A
40 LD B,B
41 LD B,C
4F LD C,A
48 LD C,B
49 LD C,C