理解装配:-O2如果分支

2 c assembly disassembly

我刚刚使用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");
    }
}
Run Code Online (Sandbox Code Playgroud)

而相应的组装是: -

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"
Run Code Online (Sandbox Code Playgroud)

我读到该test指令基本上只执行两个操作数的逻辑AND.我还读到,当前js一条指令中的符号发生变化时,指令会执行跳转.因此,test使用eax的eax会给出0或者1跳跃将取决于此.

我不明白它是如何用于分支的.有人可以解释这是如何工作的?

San*_*dri 11

当符号发生变化时,JS不跳转,如果符号标志为1则跳转.

如果最后一次操作的结果为负,则符号位为on(2的补码中的负数在1中具有最高有效位).

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