【问题标题】:How does XORing the A register clear the carry bit on the F register in the Z80?Z80中的A寄存器异或如何清除F寄存器的进位位?
【发布时间】:2016-09-27 15:43:45
【问题描述】:

我正在阅读一本关于 Zilog Z80 处理器的书,其中每当作者出于某种可能的原因想要清除进位位时,他都会执行以下任一操作:

XOR A
AND A
OR  A

这对 F 寄存器中的 C 位有何影响?换句话说,对某个寄存器 (A) 执行操作如何影响另一个寄存器 (F)?

【问题讨论】:

  • 我还是不明白你说的“如何”是什么意思。根据定义,这就是它的工作原理。这在硬件方面也不是什么奇怪的事情。
  • 但这对我来说没有意义,或者我就是不明白。我的意思是,当您LD A, 0 时,它会影响 A 寄存器,而不是 B 寄存器,而不是 F 寄存器,因为这是我选择执行操作的寄存器。那么为什么XOR A 是个例外呢?
  • “对某个寄存器 (A) 执行操作如何影响另一个寄存器 (F)”。这是一个常见的,通常是理想的属性。 F 毕竟是 flags 寄存器。例如,在执行 cp 之后,您可能想知道操作数是否相等(设置了 Z),在执行 add 之后,您可能想知道是否生成了进位,等等。
  • @Michael 哦,现在 "它如何影响另一个寄存器" 部分似乎是合乎逻辑的,尤其是您给出的第二个示例。但是在那个使用ADD的例子中,为了在进位/借位的情况下继续执行适当的过程,接下来影响C位是下一个合乎逻辑的事情,换句话说,A之间存在关系——例如—— - 和 F。虽然在 XOR A 示例中它对我来说仍然没有意义,因为它们之间仍然没有关系,也许这只是我对硬件的不了解。
  • @AbdelrahmanEid 实际上,Z80 ALU 和标志寄存器之间存在关系——标志寄存器从 ALU 操作接收标志——而不是寄存器和标志寄存器之间

标签: assembly xor microprocessors z80


【解决方案1】:

我想我理解你的担心。标志寄存器获取操作的结果,因此 AND、OR、XOR 都影响零标志、符号标志和奇偶校验标志是有意义的。这些都是结果的直接属性。但是这些运算不是算术运算,所以进位不是自然属性。

我认为答案在于 ALU 本身。作为程序员,我们将 ALU 视为一个多功能盒。您给它一个值和一个操作,它会在累加器设置标志上执行该操作作为副产品。在内部,我们怀疑它对每个操作都有一个单独的电路:加法、减法、与、或、异或。

实际上它更像是每个位的多用途功能,可以修改以执行所需的操作。在高层次上,我们可以通过 add 与 add with carry 看到这一点。在内部,这些指令的唯一区别是进位标志是否用于执行加法。同样,减法只不过是将数字的二进制补码相加。所以减法只有操作数的一些前端变化,并使用相同的加法电路。

现在考虑我们如何对单个位进行加法运算。忽略进位,请注意 0+0 = 0、0+1 = 1+0 = 1 和 1+1 = 0。那么进位呢?进位(0+0) = 进位(0+1) = 进位(1+0) = 0 和进位(1+1) = 1。

认识那些功能?两位的进位是它们的与。两个位相加的结果是它们的 XOR。如果你进一步扩展这个想法,你会看到一个简单的电路如何将两个位与一个进位输入相加,并产生结果位和一个进位输出。将它们中的 8 个链接在一起,您就是在添加数字。

如果您正在设计处理器,您可能还会注意到几乎可以免费获得 XOR。 XOR 只是将两个数字相加,但阻止了位到位的进位。类似的快捷方式可以提取您通常从进位计算中获得的 AND 值,我敢肯定还有一些其他技巧可以在其中找到 OR。细节在这里变得非常重要,因为 Z-80 的设计者没有使用 AND 和 XOR 门,而是使用原始晶体管逻辑,它可以从电路中产生更加灵活的逻辑。

无论如何,现在有一个选择。我们的 XOR 将每个位之间的进位归零。第 8 位呢?好吧,我们也应该将其归零。否则,进位位将是符号位的与,这似乎会使汇编程序程序员感到困惑和烦恼,并且没有多大用处。但是,如果我们像其他所有操作一样将携带位归零,那么我们就有一个很好的对称电路,结果是清晰明确的。而且,我怀疑,将值归零比忽略它更容易。

因此,让零进位通过可以为我们节省一些晶体管。这种副作用在诸如“OR A,A”或“AND A,A”之类的操作中派上用场,否则不会做很多事情。现在,Z-80 继承了 8080 的这种行为,所以它确实是 8080 设计师的选择,而不是 Z-80。你可以看到他们在指令集中考虑了这一点,因为他们只给了我们两个直接影响进位的操作:SCF - 将进位标志设置为 1 和 CCF - 补充进位标志。他们明确避免给我们一个“明确的进位标志”,因为“OR A,A”已经免费做到了。因此,整个业务节省了整个指令。而且,我们只能假设,他们推断将逻辑操作上的进位标志归零对编程没有太大的阻碍。在大多数情况下,您要么进行逻辑计算,要么进行算术计算,因此切换进位的逻辑运算没什么大不了的。显然其他 CPU 设计人员不同意,但这是一个公平的选择。

底线:清除进位是电路的自然结果,8080 设计人员认为这是一个有用的副作用,并选择让它保留而不是添加电路来抑制它。

具体细节请看Z-80 ALU operates internally8085 ALU internals

【讨论】:

  • 我原以为构建单独的布尔逻辑单元所需的晶体管比在二进制加法器中禁用/启用进位传播所需的晶体管更少。如果它是一个carry-lookahead 加法器,而不仅仅是波纹进位,那么需要禁用几个额外的信号。或者您可以为每个信号使用单个晶体管对它们进行门控,而不会在加法器的正常操作中引入额外的门延迟?
  • 我对晶体管级结构的了解不够,无法判断设计的选择。我确实知道 6502 设计人员确实选择为 ALU 操作使用单独的逻辑,并简单地从所有输出中选择所需的结果。事实上,如果 Z-80 使用(或需要)运载,他们很可能不得不改变他们的方法。
  • 我应该看看你的 Z-80 ALU 内部链接,这似乎回答了我的问题。它显示了通过 NOR 门的进位信号与 R 控制信号。作者还提供了晶体管级 PDF,但我并不好奇自己去挖掘答案。与现代 ALU 相比,通过 4 位 ALU 进行 2 次 ADD 显示晶体管预算必须是多么狭窄。 (例如,几乎每个流水线 CPU 执行 32 位加法运算,延迟时间为 1 个周期。英特尔 Sandybridge 系列 CPU 执行 64 位乘法运算,延迟时间为 3 个周期!)
  • 第四段肯定有错字0+0=1应该是0+0=0...不是吗?
【解决方案2】:

addsubtract 指令(或类似的,incdec 属于同一类别)借位或进位时,每个定义都会影响进位位进入寄存器“上方”的下一个更高位。

影响标志的基于 ALU 的命令(即除了 LD x,y 和分支指令之外的大多数命令)根据此“借用”行为设置或清除 C 位。纯逻辑(AND、OR、XOR)指令没有借位或进位行为,因为它们只影响寄存器中的 8 位,从而清除进位标志。

编辑:如果您想知道“这是如何完成的”-因为 CPU 是这样构建的,并且内部“接线”迫使 C 位成为 ALU 操作后逻辑上溢/下溢的结果.这不是您似乎理解的“副作用”,而是非常重要的一个,因为标志是在 Z80 程序集中做出逻辑决策(即“IF”子句)的唯一方法。

【讨论】:

  • 我确实了解 C 位是如何/何时设置的,我的问题是:“对寄存器 (A) 执行操作如何影响另一个寄存器 (F)?
  • 嗯。恐怕我不太明白。因为 CPU 是这样连线的?
  • 有趣的是,如果没有清除 C 标志,您就不能拥有“IF”子句。 6502 不会更改逻辑操作上的 C 标志,它会影响 Z,因此您将知道结果是否为零。但是 C 一个人呆着。
  • @AlexisWilke 再次阅读 - “没有标志的无 IF”与所有标志有关,而不仅仅是 C。对于 XOR A 指令,C 是否受到影响并不重要。指令是否影响 all 标志或仅影响一些标志是设计决定 - 我认为 all 更容易学习。
【解决方案3】:

应用于A 寄存器本身的这 3 个逻辑运算不会修改 A(除了将其清零的 XOR)。

但是,作为副作用,所有这些指令都保证清除进位位,如 Z80 参考手册中所述。

这个副作用就是这里想要的效果。 OR A 不会做任何其他清除 C 的操作,也会影响其他标志(取决于 A 的初始值是否为零,寄存器 Z 也被设置/清除)

来自OR instruction description

效果:清除 C 和 N 标志,P/V 检测奇偶校验,...

进位位在加法或减法溢出/下溢(ADD、SUB、ADC、SBC)时置位。例如,您可以通过执行零 + 零的加法来清除 C 标志,但这需要比 OR AAND AXOR A 更多的指令,从而使后者更高效。

其他一些 8 位处理器(如 6502)具有特定的 CLC/SEC 指令来清除进位,并且不需要这种副作用来执行此操作。

【讨论】:

  • 我的问题在你回答的第二行。这种“副作用”是如何发生的?
  • @AbdelrahmanEid 你说的“如何”是什么意思?它只是清除标志
  • @harold 对不起,如果我解释得不好。请查看我的编辑。
【解决方案4】:

大多数处理器都是使用我们所说的微码创建的。一条微码指令只做一件非常小的事情。

所以我们可以证明OR A 指令做了这样的事情:

OR A     tmp ← A              modify register "tmp"
         tmp ← tmp | A        apply OR and save result in "tmp"
         A ← tmp              copy "tmp" back to A
         F[C] ← 0             clear C flag
         F[Z] ← A == 0        set Z to 1 if A == 0, zero otherwise
         F[N] ← A[7]          set N to sign bit of A

请注意,由于这对 A 没有影响,因此他们可以将指令重命名为 CLC(清除进位)。

正如其他人所提到的,清除 C 标志是 z80 设计人员决定的选择。大多数处理器不会影响逻辑运算(AND、OR、XOR、NAND...)上的 C 标志

【讨论】:

  • 这不是微码。我认为您将它与微操作(即英特尔 CPU 将 x86 指令解码成的类似 RISC 的内部操作)混为一谈。但即使是微操作也不是那么小。 add reg, reg 在所有 Intel CPU,甚至是 Pentium 4 上总是解码为单个 uop。Core2 和 Sandybridge 系列 CPU 将最常见的指令解码为单个 uop(不像 P4,其中更多指令是多个 uop)。
  • 你描述的那些内部操作在解码/执行指令时控制电路必须单独做的所有事情,只是微码或微操作不正确为他们命名。请参阅Agner Fog's microarch pdf and instruction tables 和/或David Kanter's Sandybridge writeup 了解更多关于 CPU 内部的好东西。
猜你喜欢
  • 2011-01-15
  • 1970-01-01
  • 2014-11-18
  • 2017-07-15
  • 2012-01-22
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多