理解汇编:-O2 如果分支

发布于 2024-10-11 14:25:25 字数 833 浏览 7 评论 0原文

我只是使用 if 语句尝试了一个简单的 C 程序并分析了它的汇编。然而,当使用 -O2 标志进行编译时,其行为有很大不同。

相同的 C 代码是:-

#include<stdio.h>

int main(int argc, char **argv) {
    int a;

    if(a<0) {
        printf("A is less than 0\n");
    }
}

相应的汇编是:-

main:
    push    %ebp
    mov %ebp, %esp
    sub %esp, 8
    and %esp, -16
    sub %esp, 16
    test    %eax, %eax
    js  .L4
    leave
    ret
    .p2align 4,,15
.L4:
    sub %esp, 12
    push    OFFSET FLAT:.LC0
    call    puts
    add %esp, 16
    leave
    ret
    .size   main, .-main
    .section    .note.GNU-stack,"",@progbits
    .ident  "GCC: (GNU) 3.4.6"

我读到 test 指令基本上只是执行两个操作数的逻辑与。我还了解到,当前一条指令中的符号发生变化时,js 指令会执行跳转。因此,用 eax 测试 eax 将给出 0 或 1,跳转将取决于此。

我无法理解它是如何在这里用于分支的。 有人可以解释这是如何工作的吗?

I just tried out a simple C program using an if statement and analyzed its assembly. However, its behavior differs a lot when -O2 flag is used for compilation.

The C code for the same is :-

#include<stdio.h>

int main(int argc, char **argv) {
    int a;

    if(a<0) {
        printf("A is less than 0\n");
    }
}

And the corresponding assembly is:-

main:
    push    %ebp
    mov %ebp, %esp
    sub %esp, 8
    and %esp, -16
    sub %esp, 16
    test    %eax, %eax
    js  .L4
    leave
    ret
    .p2align 4,,15
.L4:
    sub %esp, 12
    push    OFFSET FLAT:.LC0
    call    puts
    add %esp, 16
    leave
    ret
    .size   main, .-main
    .section    .note.GNU-stack,"",@progbits
    .ident  "GCC: (GNU) 3.4.6"

I read that the test instruction basically just performs the logical AND of the two operands. I also read that the js instruction performs a jump when there is a change in sign in the previous instruction. So, testing eax with eax would give 0 or 1 and the jump would depend on this.

I fail to understand how it is being used here for branching.
Could someone explain how this works?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

此生挚爱伱 2024-10-18 14:25:25

JS 当符号改变时不跳转,如果符号标志为 1,则跳转。

如果最后一次运算结果为负,则符号位打开(2 的补数中的负数具有 1 中的最高位) 。

因此,如果 AND 运算是在两个负整数(-1 和 -1)之间,最后一位将为 1(符号标志),因此进行跳转。如果数字为正,最后一位将为 0,则不会进行跳转。

JS doesn't jump when there is a change in sign, it jumps if the sign flag is 1.

The sign bit is on if the result of the last operation was negative(negative numbers in 2's compliment have the most significant bit in 1).

So if the AND operation was between two negative integers(-1 & -1) the last bit will be 1(sign flag), so the jump is taken. In case the numbers were positive the last bit would be 0, the jump won't be taken.

一张白纸 2024-10-18 14:25:25

好吧,我不知道你期望什么,但你的程序有未定义的行为,因为 a 未初始化。所以汇编器的输出实际上可以是任何东西。

Well I don't know what you expect, but your program has undefined behavior since a is not initialized. So the assembler output could be literally anything.

偏爱自由 2024-10-18 14:25:25

英特尔手册对此很有帮助。这是 TEST 指令的文档:

alt text

SF 是符号标志,由 JS 操作码测试的标志。这里它被设置为 eax 的最高有效位,即符号位。因此,当 eax 包含负数时进行跳转。

The Intel manuals are good for this. This is what it documents for the TEST instruction:

alt text

SF is the sign flag, the one that's tested by the JS opcode. It is set to the most significant bit of eax here, the sign bit. The jump is thus taken when eax contains a negative number.

撧情箌佬 2024-10-18 14:25:25

如果eax为负,则标志将指示在test指令之后并且将进行跳转。这会将 PC 推送至执行打印的 .L4。否则,我们就离开。

If eax is negative, the flags will indicate that after the test instruction and the jump will be taken. That pushes the PC to .L4 which does the printing. Otherwise, we leave.

俯瞰星空 2024-10-18 14:25:25

test eax, eax 如果 eax = 0 则将设置零标志

js 指令将基本上检查符号标志(a<0)

test eax, eax will set zero flag if eax = 0

js instruction will check the sign flag basically (a<0)

§对你不离不弃 2024-10-18 14:25:25

看起来当您指定 -O2 时,编译器会将您的“int a”放入寄存器中以进行速度优化。

由于您从未初始化“int a”,因此程序集不会显示写入 eax 的任何内容,而是具有最后分配给它的值。

其他答案解释了测试如何作为分支机制工作。

Looks like when you specify -O2, the compiler is putting your "int a" into a register for speed optimization.

Since you never initialize 'int a', the assembly does not show anything written to eax and it instead has the value that was last assigned to it.

The other answers explain how test is working as a branching mechanism.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文