和很多其他人一样,我正在编写一个游戏男孩模拟器,我有几个关于0xE8指令的问题(ADD SP, n有一个8位的即时指令)。
这里声称,在16位指令中,如果从第7位到第8位出现进位,则设置半进位标志,而这里则说半进位标志表示从第11位到第12位的进位。在这个Reddit线程中,这个问题似乎有点混乱,(我听说) 游戏男孩CPU手册似乎也没有什么可说的。
我的问题如下:
发布于 2019-09-17 20:52:28
游戏男孩使用的SM83 CPU核心几乎肯定有一个8位的ALU,这意味着16位ALU操作实际上是由两个8位操作组成的。和普通的Z80 CPU一样,它还有一个专用的16位增量/递减/加载单元,它可以快速处理某些16位操作,但不能更新标志。基本上:
因此,每当您处理标志时,如果您想对操作进行推理,请尝试考虑8位操作(首先是低字节,然后是高字节)。
正如在另一个答案中指出的,H是在第3位有进位时设置的,C是在第7位有进位时设置的。
下面是一个有趣的思考练习:如果SP=$FFFF和您执行ADD SP, -1,您将得到SP=$FFFE,并且设置了H和C。你能理解为什么吗?
由于有符号数字的工作方式,低字节操作在这种情况下基本上只是一个正常的加法。
-1=$FF,所以它正在计算$FF+$FF。
↑上方的提示
我们还没有完全理解它在最低可能的水平,但我知道有两个8位操作。在我的系统中,我已经确认,首先有一个ALU操作更新标志(H,C),而不是SP,然后是其他一些操作,最后SP是一次原子更新。这表明ADD SP, e可能实际上在两个单独的8位操作中将结果计算到某个临时寄存器中(例如,一个真实的Z80有一个用于某些ALU操作的不可见的WZ临时寄存器),然后从其中加载SP。
我认为ADD HL, BC更有趣一些--我的测试平台--我已经确认它首先更新L,然后更新H,标志被更新了两次。这意味着它实际上执行了类似于
ADD L, C
ADC H, B后一个8位操作更新标志,因此我们从未看到ADD L, C的结果标志。但是,如果L位3有一个进位,则可以暂时设置半进位标志!
这取决于指令,但是这些标志总是基于相同的位位置更新的,如果您认为从8位values...it的角度来看,无论我们谈论的是16位值的高字节还是低字节,都会有所不同。位11只是高字节的第3位。
ADD SP, e:h来自位3,C来自位7(标志来自低字节op)LD HL, SP+e:h来自位3,C来自位7(标志来自低字节op)ADD HL, rr:h来自位11,C来自位15 (标志来自高字节op)INC rr:没有标志更新(由16位inc/dec单元执行)DEC rr:没有标志更新(由16位inc/dec单元执行)发布于 2019-09-17 16:36:40
TL;DR:对于,当进位从第3位到第4位时设置H标志。**
我决定在真正的硬件上测试这一点,所以我用GB-Z80程序集编写了一个简单的测试ROM,测试以下场景:
SP =$2000 F
ADD SP,$01
SP = $00F0
ADD SP,$10
SP = $0FF0
ADD SP,$10
对于每种情况,我都将寄存器F的值存储在内存中的ADD之后,然后在屏幕上显示每个字节的位5(H标志)。
我在3种不同的型号(Gameboy Pocket、Gameboy Color和Gameboy Advance )上运行了这个程序,并在所有3种设备上获得了以下输出:1 0 0。因此,第3->4位的进位导致H的设定,而从7->8或11->12的进位则没有。
对于ADD HL,rr ( rr是BC/DE/HL/SP)来说,这似乎是另一个故事。根据我的测试,如果从第11位到第12位发生进位,则设置H。
https://stackoverflow.com/questions/57958631
复制相似问题