条件代码--CF和OF

条件代码--CF和OF,c,assembly,x86,flags,C,Assembly,X86,Flags,我阅读了CS:APP(第三版)一书和第3.6.1节条件代码。它说: CF:携带旗帜。最近的操作生成最高有效位的进位。用于检测未签名操作的溢出 OF:溢出标志。最近的操作导致2的补码溢出——要么是负的,要么是正的 但我有以下代码。我编译并执行了它。发生了一些不同的事情 int main() { char x = 0x66; char y = 0x39; char x_bit_not = ~x; char x_not = !x; char x_bit_an

我阅读了CS:APP(第三版)一书和第3.6.1节条件代码。它说:

CF:携带旗帜。最近的操作生成最高有效位的进位。用于检测未签名操作的溢出

OF:溢出标志。最近的操作导致2的补码溢出——要么是负的,要么是正的

但我有以下代码。我编译并执行了它。发生了一些不同的事情

int main() {
    char x  = 0x66;
    char y =  0x39;
    char x_bit_not = ~x;
    char x_not = !x;
    char x_bit_and_y = x & y;
    char x_and_y = x  && y;
    char  x_bit_or_y = x | y;
    char x_or_y = x || y;


    int x1 = (1<<31)-1;
    int y1 = 1;
    int sum_x1_y1 = x1 + y1;
    int diff_x1_y1 = x1 - y1;
    int diff_y1_x1 = y1 - x1;


    unsigned int x2 = (1<<31)-1;
    unsigned int y2 = 1;
    unsigned int sum_x2_y2 = x2 + y2;
    unsigned int diff_x2_y2   = x2 - y2;
    unsigned int diff_y2_x2   = y2 - x2;
}
intmain(){
字符x=0x66;
字符y=0x39;
char x_bit_not=~x;
char x_not=!x;
字符x_位和y=x&y;
char x_和_y=x&&y;
字符x_位_或_y=x | y;
char x_或_y=x | | y;

int-x1=(1我的答案是假设x86。其他架构的行为可能不同

在x86上,CF和OF标志都会受到有符号和无符号操作的影响(因为CPU不知道有符号性)。哪些标志相关取决于特定的用例。通常,CF标志会检查无符号算术,而OF标志会检查有符号算术。另请参阅:

具体针对您的观察结果:

  • 这意味着,当从较小的数字中减去较大的数字(如
    y1-x1
    )时,将设置该值,因为这需要从MSB借用。另请参见:
  • 类似地,这意味着,将两个加起来超过MAX_INT(如
    x2+y2
    )的数字相加时,将设置

当两个正数相减产生负数(
x1-y1=0x8000002
)时,应设置进位标志(与笔和铅笔相减时的进位标志相同)。当两个正数相减产生负数(
x2+y2=0x8000000
)时,则符合溢出条件(因为正确的结果超出了有符号32位整数的范围)。您不同意吗?标记设置是在不考虑操作数符号的情况下进行的(处理器不知道操作数是有符号的还是无符号的),但程序员或编译器随后会根据操作数类型生成相应的条件,测试各种标志组合。C没有标志。我假设您使用禁用优化的某些编译器为x86编译代码,然后使用调试器单步执行?请注意,编译器可能使用了
le一条
(不设置标志)而不是一条
添加指令。你应该真正关注你正在执行的asm,而不是假设你的代码是如何编译的。(除非你已经完全熟悉你的编译器是如何在禁用优化的情况下生成代码的…)您的C代码不显示任何CF/OF。x86机器指令
add
将在添加两个值(8、16、32或64位)时同时更新CF和OF。前面/后面的代码是否将这些位视为有符号整数或无符号整数与
add
本身无关,后者在这两种情况下的操作方式完全相同,因此CF和of标志对于有符号和无符号C数学都设置为某个值,下面的代码必须使用正确的值。标志具有“correct”值在“正确”上下文中使用时,否则它们的值“错误”(但定义良好)。
-3+-4
设置CF,但谁在乎“添加”呢?实际上没有“已签名”和“未签名”x86上的操作。这只是一个加法操作,只有结果标志的解释起作用。有符号整数的2s补码表示使这成为可能。@Ctx:编辑了我的答案以明确说明这一点。
-1--2=>+1
未设置of,但MSB已更改。有关输入/输出标志的表格,请参阅对于减法,有两种情况标记。@PeterCordes:我的答案假设该语句加上2个无符号值。为了避免混淆,我对其进行了澄清。为了计算的目的,您必须将输入和输出解释为有符号。这就是整点:OF告诉您有符号操作是否已包装;CF告诉您,如果将无符号操作wrapped.OF的输入解释为无符号0xFFFFFF和0xFFFFFE,则无符号操作wrapped.OF是否会非常奇怪:如果有,则添加将与这些输入一起设置,这是无意义的:
-1+-2
不会溢出。(您的编辑已经修复了此问题。)