我一直在开发Game Boy模拟器,注意到有些操作码永远不会改变任何值,例如LD A, A
、LD B, B
等以及AND A
。前两个显然没有改变任何东西,因为它们将寄存器的值加载到相同的寄存器中,而由于AND
与A
寄存器进行比较,AND A
将始终返回A
。这些操作有什么目的,还是每个周期之后本质上与NOP
相同吗?
正如Jeffrey Bosboom和Hans Passant在他们的评论中指出的那样,原因是简单性。更具体地说,是硬件上的简单性。
LD r,r'
指令将源寄存器(r'
)的内容复制到目标寄存器(r
)。 LD r,r'
操作码遵循以下形式:
-------------------------------
BIT | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
-------------------------------
OPCODE | 0 | 1 | r | r' |
-------------------------------
目标寄存器和源寄存器可以具有以下值:
-----------
| BIT | REG |
-----------
| 111 | A |
-----------
| 000 | B |
-----------
| 001 | C |
-----------
| 010 | D |
-----------
| 011 | E |
-----------
| 100 | H |
-----------
| 101 | L |
-----------
为了在硬件中实现这些指令,我们只需要一个多路选择器来接收位0-2以选择源寄存器,还需要另一个多路选择器来接收位3-5以选择目的寄存器。LD A,A
、LD B,B
、LD C,C
、LD D,D
、LD E,E
、LD H,H
和LD L,L
这样的加载指令就像NOP
一样行为。但是AND A
和OR A
不会像NOP
一样行为,因为它们会影响标志寄存器,并且它们的执行可能会改变内部机器状态。类似于LD A,A
和AND A
这样的指令可能看起来像是NOP
,但它们也可能会改变处理器标志并用于测试寄存器的值。
一定要仔细检查指令集文档以了解此类副作用。
LD r,r'
不会改变标志位。 - Jongware在IT技术中,AND A
(以及OR A
)指令实际上有一定的用途--当A
为零时设置标志位Z
,否则清除。因此,AND A
和OR A
都经常被用于这个目的。
mov eax,eax
相同:没有必要为了使用那些编码来完成有用的事情而使编码空间变得复杂。 (抱歉,我对Game Boy或z80不够熟悉,无法确定这些指令是否具有任何隐藏的微架构副作用。) - Jeffrey Bosboom