Game Boy:不修改任何内容的指令(例如AND A)有什么作用?

13

我一直在开发Game Boy模拟器,注意到有些操作码永远不会改变任何值,例如LD A, ALD B, B等以及AND A。前两个显然没有改变任何东西,因为它们将寄存器的值加载到相同的寄存器中,而由于ANDA寄存器进行比较,AND A将始终返回A。这些操作有什么目的,还是每个周期之后本质上与NOP相同吗?


6
我想它们存在的原因与你可以在x86中编写mov eax,eax相同:没有必要为了使用那些编码来完成有用的事情而使编码空间变得复杂。 (抱歉,我对Game Boy或z80不够熟悉,无法确定这些指令是否具有任何隐藏的微架构副作用。) - Jeffrey Bosboom
3
这可以追溯到1970年的8008处理器。简单性很重要,它只有3500个晶体管。后来的8080和Z80复制了指令集设计。这并不是它们的目的,而只是为了保持指令解码逻辑的简单性。 - Hans Passant
3个回答

13

正如Jeffrey BosboomHans 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以选择目的寄存器。
如果您想验证位0-2和位3-5是否指向同一个寄存器,则需要向CPU添加更多逻辑。众所周知,80年代的资源更为有限 :P
请注意,像LD A,ALD B,BLD C,CLD D,DLD E,ELD H,HLD L,L这样的加载指令就像NOP一样行为。但是AND AOR A不会NOP一样行为,因为它们会影响标志寄存器,并且它们的执行可能会改变内部机器状态。

4
从软件的角度来看,很容易忽略原始系统中需要存在的硬件。 这正是我要找的,谢谢。 - Zach Brantmeier
1
实际上(至少在Z80上,Gameboy的CPU不是Z80,可能只是类似于Z80或8080...缺少许多Z80的特性),唯一的例外是使用LD指令时的(HL),LD (HL),(HL)组合不存在,它代表的是HALT(因此完全不同)。但是,即使在正常的LD r1,r2块操作码中,(HL)引用也是有点特殊的。 - LGB

7

类似于LD A,AAND A这样的指令可能看起来像是NOP,但它们也可能会改变处理器标志并用于测试寄存器的值。

一定要仔细检查指令集文档以了解此类副作用。


如果我没记错的话,“AND A”是比较零的惯用方式;它只有一个字节而不是两个字节,因此循环次数更少。 - Tommy
1
LD r,r' 不会改变标志位。 - Jongware

3

在IT技术中,AND A(以及OR A)指令实际上有一定的用途--当A为零时设置标志位Z,否则清除。因此,AND AOR A都经常被用于这个目的。


1
他们还无条件地清除进位标志,如果您正在使用它来返回结果(例如,通过设置进位来信号错误或异常条件的函数返回值),这将非常有用。 - Simon Sellick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接