我遇到过两种设置进位标志的方法:
0x00_00_00_00_00_00_00_00 - 0x80_00_00_00_00_00_00_00
(下划线表示字节)
如果我用减法来做这个,我们必须借用一个我们没有的位,它应该把CF
设置为1
。
然而,我的印象是ALU不做减法,而只是把2的补码相加。0x80_00_00_00_00_00_00_00
的2的补码是0x80_00_00_00_00_00_00_00
。所以,0x00_00_00_00_00_00_00_00 - 0x80_00_00_00_00_00_00_00
不携带63位中的任何位,这将把CF
设置为0
。
以下哪种情况对x86中的64位值有效?
ALU实际上是执行减法还是将其转换为2的补码并将转换后的值进行减法运算?
1条答案
按热度按时间olmpazwi1#
请参阅Understanding Carry vs. Overflow conditions/flags以了解有关进位的更多信息。
是的,当然SUB的任何实现仍然必须保留相同的体系结构可见的行为,包括标志结果。
ALU内部如何工作并不重要,重要的是结果是什么,零减去非零产生进位,所以任何x86 CPU都会在这种情况下设置CF,任何不这样做的CPU都不是x86。
查看x86标签wiki,获取英特尔x86手册的链接(以及许多其他有用的链接);我敢肯定,在官方手册的某个地方有一节关于升旗行为的。
实际上,是的,大概x86 CPU使用的是普通的binary adder-subtractor,其中sub / cmp是通过对一个输入进行“否”操作并将
1
的进位输入送入低位来完成的。(因此只有一次加法,因此0
的输入变为FFFFFFFF
,进位输入为1
,保证了ALU加法器的进位输出)。由于x86希望CF的语义是减法时的借位,因此它必须在执行减法时反转ALU加法器的进位输出信号,并且x86
sbb
必须将其反转回来。其他一些ISA(如ARM)的进位标志表示不借位,因此ARM的
sbc
可以像adc
一样将C标志直接送入ALU。另请参阅 * 算术恒等式和EFLAGS*:用
not
/stc
/adc
模拟sub
。我猜是一个cmc
来补充CF。我还没有检查它是否会为OF符号溢出给予正确的输出。