理解rFlags寄存器OF标志位

Last Updated: 2023-09-30 09:27:03 Saturday

-- TOC --

x86-64的CPU,rFlags寄存器,有个OF标志,即Overflow标志位。正常情况下,我们对Overflow的理解,就是计算的结果目标寄存器装不下了,溢出了。但CPU是一板一眼工作的,它有自己的规则,简单说,OF是signed overflow, both positive and negative,且只能判断operand的MSB相同时溢出的情况,OF这个标志位很有误导性,在high level,它只能判断一部分的溢出情况,并不是全部!

下面是AMD64手册对Overflow标志的介绍:

Overflow Flag (OF). Bit 11. Hardware sets the overflow flag to 1 to indicate that the most-significant (sign) bit of the result of the last signed integer operation differed from the signs of both source operands. Otherwise, hardware clears the flag to 0. A set overflow flag means that the magnitude of the positive or negative result is too big (overflow) or too small (underflow) to fit its defined data type. The OF flag is undefined after the DIV instruction and after a shift of more than one bit. Logical instructions clear the overflow flag.

这段文字貌似与单纯的溢出理解没有什么冲突,但这里面有个约束:这个OF标志位,仅对signed integer operation有意义。也就是说,只有认为operand都是signed时,才有可能在结果的MSB与operand的MSB不一致时,出现OF=1。两个operand的MSB不一样,绝不会产生OF=1

ALU输出OF标志,其计算其实是很简单的,就是将两个operand都当做signed,用最高位与结果的最高位进行比较得到。CPU执行指令没有类型的概念。执行0xFFFFFFFF+2,没有OF=0,两个operand的MSB不同,此时要判断溢出,需要用到CF标志,即CF=1。那么,这条指令到底是执行signed,还是unsigned,CPU不关心,反正所有的信息都在rFlags寄存器内,C语言编译器根据代码中的类型信息,自行判断用哪些标志位做后续的判断。

比如计算0xFFFFFFFF+0xFFFFFFFF,计算结果为0xFFFFFFFE,此时有CF=1,但OF=0,因为结果的MSB与operand的MSB相同。(-1 + -1 = -2,没有溢出)

当计算0x80000000+0x80000000时,结果为0,同时产生CF=1和OF=1。

但当计算0x80000000-0x80000000时,CF=0,OF=0,而ZF=1。AMD64手册对sub指令的说明:

This instruction evaluates the result for both signed and unsigned data types and sets the OF and CF flags to indicate a borrow in a signed or unsigned result, respectively.

在C语言中判断整数计算的溢出

在汇编层面判断溢出,与在C语言层面判断溢出,方法不同!在汇编层面,每条语句执行后的flags变化,要查阅手册确定,这是机器内定死的。

本文链接:https://cs.pynote.net/hd/asm/202307021/

-- EOF --

-- MORE --