ADC和SBB的结合性

Associativity of ADC and SBB

ADC的运算是DEST ← DEST + SRC + CFSBB的运算是DEST ← (DEST – (SRC + CF))。令我困惑的是这些指令对 FLAGS 的影响。在 SBB 的情况下,结合性很明确,因此我假设 SBB 等同于(最后的寄存器状态)

    jnc label
    lea src, [src+1]
    sub dest, src
    lea src, [src-1]
    jmp label2
label:
    sub dest, src
label2:

但是在 ADC 的情况下,是否会先将 SRC 添加到 DEST,然后再添加 CF?这很重要,因为如果是这样,它会对 FLAGS 产生不同的影响。

ADC 和 SBB 的结转基于整个操作。
如果将 sbb 写为 dst -= CFdst -= src,如果其中 之一 产生借位,则应设置 CF。

伪代码中的括号 而不是 试图告诉您操作的哪一部分实际设置了 FLAGS。你对它读得太多了,模拟一个全加器(adcsbb 进位和进位并不是那么容易。这就是为什么拥有硬件支持指令非常有用的原因他们。)

你对 sbb 的仿真在 src+CF 换行到 0 的情况下是错误的。 你没有区分 src=-1 CF= 1 个案例(始终携带)来自 src=0,CF=0。 (dst-=0 总是产生 CF=0)。在带有调试器的真实 CPU 上尝试一下。


您可以将 ADC 视为 dst += src + CF(或 SBB 的 -=),其中 src+CF 临时值是在不截断的情况下计算的;例如32 位操作数大小的 33 位总和。 ADD / SUB / ADC / SBB的dst和CF输出也可以看做是一个33位的值。

简单示例:

mov al, 0xFF         ; AL=0xFF
stc                  ; CF=1
adc al, 0xFF         ; CF:AL = AL + (0xFF+CF) = AL + 0x100
; AL = 0xFF,  CF=1

它已经足够复杂了,可以模拟 adc IMO 只是从加法的进位和出位的角度理解它更有帮助。或者如果它有帮助,比如 full adder,或者实际上是 8、16、32 或 64 个全加器的链。 (当然,物理实现的延迟比纹波进位低)。

对我来说,根据 32 位固定宽度操作,计算出烦人的复杂分支序列或模拟 adcsbb 所需的任何东西对我来说都是零帮助了解他们的工作。它们足够简单,可以被视为原始操作,也足够难以模拟。