簡體   English   中英

理解裝配:-O2如果分支

[英]understanding assembly: -O2 if branching

我剛剛使用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指令基本上只執行兩個操作數的邏輯AND。 我還讀到,當前一條指令中的符號發生變化時, js指令會執行跳轉。 因此,用eax test eax將得到01 ,並且跳躍將取決於此。

我不明白它是如何用於分支的。 有人可以解釋這是如何工作的?

當符號發生變化時,JS不跳轉,如果符號標志為1則跳轉。

如果最后一次操作的結果為負,則符號位為on(2的補碼中的負數在1中具有最高有效位)。

因此,如果AND運算在兩個負整數(-1和-1)之間,則最后一位將為1(符號標志),因此跳轉。 如果數字為正,則最后一位為0,則不會進行跳轉。

好吧,我不知道您的期望,但你的程序未定義的行為,因為a未初始化。 所以匯編程序輸出可以是任何東西。

英特爾手冊對此非常有用。 這是它為TEST指令記錄的內容:

替代文字

SF是符號標志,由JS操作碼測試。 它被設置為這里最重要的eax位,即符號位。 因此,當eax包含負數時,將進行跳轉。

如果eax為負數,則標志將指示在test指令和跳轉之后。 這將PC推送到.L4進行打印。 否則,我們離開。

test eax, eax如果eax = 0 test eax, eax將設置零標志

js指令基本上會檢查符號標志(a <0)

看起來當你指定-O2時,編譯器會將你的“int a”放入寄存器中進行速度優化。

由於您從未初始化'int a',因此程序集不會顯示寫入eax的任何內容,而是具有上次分配給它的值。

其他答案解釋了測試如何作為分支機制。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM