2011-05-25 46 views
0

在gcc中打開1級優化後,我有一個奇怪的問題。我所做的是將標籤和jmp保存在一個不同的函數中。優化後標籤移動gcc中打開

void 
UMS__suspend_procr(VirtProcr *animatingPr) 
{ 
    animatingPr->nextInstrPt = &&ResumePt; 


    [Some Code and inline volatile asm] 

    ResumePt: 
    return; 

}

我做一些跳躍的,他們都做工精細。 問題是,當我打開O1時,它不保存正確的標籤地址。相反,它這樣做:

804b14e:  8b 45 08    mov 0x8(%ebp),%eax 
804b151:  c7 40 14 4e b1 04 08 movl $0x804b14e,0x14(%eax) 
804b158:  8b 55 08    mov 0x8(%ebp),%edx 

所以程序甚至在分配前跳回來。

+0

您是否知道,獲取標籤的地址是非標準的語言擴展?因此完全不可移植。 – 2011-05-25 16:18:05

回答

6

此代碼無效GNU C.首先,計算得到的goto(&&label)是GNU C的特有功能,不是C語言的一部分,但如果您使用GNU C,則可以。但是,只有他們在GNU C中有效的地方是goto聲明。您不能將指針與inline asm用作間接跳轉/調用目標,因爲調整堆棧幀取決於編譯器,並且從內聯asm和標籤目標點開始的堆棧幀的當前邏輯視圖可能不匹配。通過明確的goto聲明,編譯器可以對此進行修補,但使用asm甚至不能說明它正在發生。至於更大的圖片,如果你正在編寫這樣的代碼,你應該真的重新考慮一些你的假設。當然有更好的方法來實現你想要的。

+0

是的,我知道這只是GNU C的一部分。堆棧很好,我總是跳回到相同的功能,每次我jmp保存我的堆棧幀並使所有寄存器無效。這是否有可能,這是移動標籤的原因? – merten 2011-05-25 16:28:36

+2

堆棧不正常。編譯器可以隨時調整它*,無論何時何地都可以*並且不在您的控制範圍之內。你根本不被允許做任何你想做的事情。它如果「有效」,它是純粹的運氣,並且它可以並且會破壞。 – 2011-05-25 16:29:52

+0

@merten:無論堆棧如何,你都會說「我所做的就是將標籤和jmp保存在不同的函數中。」 - GCC文檔非常明確地指出:「你可能不會使用這種機制跳轉到另一個函數中的代碼,如果你這樣做,完全不可預知的事情會發生。」 (請參閱[最新版本](http://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Labels-as-Values.html);在相同的語言已經很長一段時間。) – 2011-05-25 20:02:59