[英]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將得到0
或1
,並且跳躍將取決於此。
我不明白它是如何用於分支的。 有人可以解釋這是如何工作的?
當符號發生變化時,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.