ADC 和 SBB 的关联性

1 x86 assembly x86-64 carryflag

的运算ADCDEST ? DEST + SRC + CF, 的运算SBBDEST ? (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:
Run Code Online (Sandbox Code Playgroud)

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

Pet*_*des 5

ADC 和 SBB 的执行都基于整个操作。
如果您写sbbdst -= CF, dst -= src,如果其中任何一个产生借用,则应设置 CF。

伪代码中的括号并没有试图告诉您操作的哪一部分实际上设置了 FLAGS。你读得太多了,模拟全加器(adcsbb进位和进位。这就是为什么为它们提供硬件支持的指令非常有帮助的原因。)

对于换行为 0sbb的情况,您的仿真有问题。src+CF 您无法区分 src=-1 CF=1 情况(始终进位)与 src=0, CF=0。(dst-=0 总是产生 CF=0)。在带有调试器的真实 CPU 上尝试一下。


您可以将 ADC 视为dst += src + CF(或-=对于 SBB),其中src+CF临时计算没有截断;例如,32 位操作数大小的 33 位总和。dstADD / SUB / ADC / SBB的和 CF 输出也可以视为 33 位值。

简单的例子:

mov al, 0xFF         ; AL=0xFF
stc                  ; CF=1
adc al, 0xFF         ; CF:AL = AL + (0xFF+CF) = AL + 0x100
; AL = 0xFF,  CF=1
Run Code Online (Sandbox Code Playgroud)

它足够复杂,可以模拟adc它对 IMO 更有帮助,仅从加法的结转和结转方面来理解它。或者如果它有帮助,比如一个全加器,或者实际上是一个由 8、16、32 或 64 个全加器组成的链。(当然,物理实现的延迟低于波纹进位)。

对我来说,计算出令人讨厌的复杂分支序列或任何需要模拟的东西,adc或者sbb根据 32 位固定宽度操作来理解它们的作用将是零帮助。它们很简单,可以认为是原始操作,也很难模拟。