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 位和。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 更有帮助,仅从加法的进位和进位方面理解它。或者如果它有帮助,比如一个全加器,或者实际上是一个由 8、16、32 或 64 个全加器组成的链。(当然,物理实现的延迟低于波纹进位)。
对我来说,计算出烦人的复杂分支序列或任何需要模拟的东西,adc
或者sbb
就 32 位固定宽度操作而言,对于理解它们的作用是零帮助。它们很简单,可以认为是原始操作,但很难模仿。