循环索引比较未按预期组装

loop index comparison is not assembled as expected

我正在尝试使用 GDB 理解 C,我正在调试的程序是:

#include <stdio.h>

int main() 
{
    int i;
    for(i=0; i < 10; i++) {
      puts("Hello, world!\n");
    }
    return 0;
}

当我调试它时,我看到在汇编中 i 的值与 10 而不是 9 进行比较,我认为它应该与 9 进行比较,因为我的循环间隔中没有包括 10。这是 GDB 输出:

(gdb) x/i $rip
=> 0x100000f36 <main+22>:   cmp    DWORD PTR [rbp-0x8],0xa

rbp-0x8指向的值是i值,rbp-0x8现在如预期的那样等于0

来自 Wikipedia 关于 cmp 指令:

Performs a comparison operation between arg1 and arg2. The comparison is performed by a (signed) subtraction of arg2 from arg1, the results of which can be called Temp. Temp is then discarded. If arg2 is an immediate value it will be sign extended to the length of arg1. The EFLAGS register is set in the same manner as a sub instruction.

所以 cmp 指令在左边的值小于、大于或等于右边的值时设置一个标志。如果检查下一条指令,您可能会发现它是 jge,这意味着它会在 i <= 10

时跳出循环

如果等于或大于 jge,下一条指令可能是跳转。 编译器通常会进行这些类型的更改。没有什么可担心的。例如,在这种情况下,编译器将(人类预期的)"jump to the loop head" 更改为 "jump out of the loop"。我认为最好将代码编译为第一种,以使优化步骤更容易。

如果与9比较,不小于等于则跳转下一条指令jnle

因为你是从0开始的。0,最低限是循环中的第一个元素和9,最高限是第十个。因此 i 与 10 进行比较。

如果你做i=1,i<=10,那么你就会得到你想要的。虽然这两种方法的意思是一样的。

希望对您有所帮助。