1 x86 assembly x86-64 carryflag
的运算ADC是DEST ? DEST + SRC + CF, 的运算SBB是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:
Run Code Online (Sandbox Code Playgroud)
但是,在 , 的情况下ADC,将SRC首先添加到DEST,然后在其之上CF添加?这很重要,因为如果是这样,它会对 FLAGS 产生不同的影响。
ADC 和 SBB 的执行都基于整个操作。
如果您写sbb为dst -= CF, dst -= src,如果其中任何一个产生借用,则应设置 CF。
伪代码中的括号并没有试图告诉您操作的哪一部分实际上设置了 FLAGS。你读得太多了,模拟全加器(adc或sbb进位和进位。这就是为什么为它们提供硬件支持的指令非常有帮助的原因。)
对于换行为 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 位固定宽度操作来理解它们的作用将是零帮助。它们很简单,可以认为是原始操作,也很难模拟。