2014-10-28 57 views
1

我建立的項目之一,我期待在生成的列表文件。(目標:X86-64)我的代碼如下所示:編譯優化呼叫-RET VS JMP

int func_1(var1,var2){ 
     asm_inline_(
     ) 
     func_2(var1,var2); 
     return_1;  
} 
void func_2(var_1,var_2){ 
    asm __inline__(
    ) 
    func_3(); 
} 
/**** Jump to kernel ---> System call stub in assembly. This func in .S file***/ 
void func_3(){ 
} 

當我看到彙編代碼,我發現調用func_2和func_3時使用「jmp」指令而不是「call-return」對。我確信這是編譯器優化之一,我還沒有探索如何禁用它。 (GCC) 當我添加一些volatile變量到func_2和func_3並增加它們時,「jmp」被替換爲「call-ret」對。 我很困惑看到行爲,因爲這些變量是無用的,他們不起任何作用。 有人可以解釋行爲嗎?

感謝

回答

3

如果代碼跳到另一個函數的開始,而不是調用它,當躍升到函數返回時,它會返回到其中功能是從所謂的地步,忽略任何在那之後的第一個功能更多。假設行爲是正確的(第一個函數無論如何都沒有爲這個點之後的執行做任何其他貢獻),這是一個優化,因爲它將指令和堆棧操作的數量減少了一個級別。

在給出的例子中,行爲正確;沒有本地棧可以彈出,也沒有值返回,所以在調用之後沒有需要運行的代碼。 (return_1,假設它不是一個宏的東西,是一個純粹的表達式,因此不管它的值如何都不會做任何事情)。所以當沒有更多的事情可以爲事件做出貢獻時,沒有理由爲未來保留棧幀。

如果添加volatile變量的函數體,你不只是添加變量,其流動的編譯器可以分析 - 要添加插槽你已經明確告訴編譯器可外部訪問的可以預測的正常控制流量。 volatile限定符警告編譯器,即使沒有明顯的方法讓變量逃脫,外面的某個東西也可以隨時獲得它們的地址並寫入它。所以它不能減少它們的壽命,因爲有人告訴函數外部的代碼仍然可以嘗試寫入該堆棧空間;顯然這意味着堆棧框架需要在其整個聲明的壽命期間繼續存在。

+0

Gr8解釋。謝謝 – 2014-10-28 18:28:35