2012-04-24 40 views
-1

我建立使用gcc編譯一些英特爾式內聯彙編代碼上的Xcode 4 下面的內聯彙編代碼列表部分:如何在構建intel樣式的內聯彙編代碼時使gcc編譯器保留寄存器?

_asm 
{ 
    mov eax, esp 
    sub esp, 116 
    and esp, ~15 
    mov [esp+112], eax  
} 

在休眠模式下,GCC編譯上述4行彙編代碼到:

mov %esp,%eax 
sub $0x74,%esp 
and $0xfffffff0,%esp 
mov %eax,0x70(%esp) 

這正是我想要的。 然而,在調試模式GCC編譯器會該代碼

mov %esp,%eax 
mov %eax,%esp 
mov %esp,%eax 
mov %eax,-0x28(%ebp) 
mov %esp,%eax 
mov %eax,%esp 
sub $0x74,%esp 
mov %esp,%eax 
mov %eax,-0x24(%ebp) 
mov %esp,%eax 
mov %eax,%esp 
**and $0xfffffff0,%esp**   
**mov %esp,%eax**  **//changing the value of 「eax」** 
mov %eax,-0x24(%ebp) 
mov %esp,%ecx 
mov %ecx,%esp 
**mov %eax,0x70(%esp)** **//store a 「dirty」 value to address 0x70(%esp), which is not we want** 

一種方法來解決上述問題是使用AT & T型指令重寫內聯彙編代碼和寄存器添加到修飾列表。但是這種方式將是一項非常耗時的工作,因爲重寫代碼很長。

還有其他有效的方法來解決這個問題嗎?爲了讓gcc編譯器知道應該保留寄存器「eax」?

+0

斜線代碼使用寄存器eax來存儲重要值,但GCC使用「eax」作爲臨時寄存器並「污染」寄存器「eax」。如何避免這種情況? – behe 2012-04-24 10:26:53

+0

你是什麼意思保存? inline-asm聲明結束之後?這是沒有意義的;一旦你的彙編語句完成,編譯器再次擁有寄存器。如果你想讓函數返回你留在'eax'中的東西,你需要用C變量來實現。包含asm塊函數可以內聯到另一個函數中... – 2016-10-01 10:48:00

回答

2

有2種方式:

  1. ,最好的辦法來解決它使用GCC彙編模板 能力。然後你可以告訴編譯器你正在做什麼 寄存器分配器不會使用你的寄存器來處理其他任何東西 。

  2. 一個快捷方式就是使用「asm volatile」而不是「asm」,這樣gcc不會重新安排 該塊內的任何指令。您仍然必須告訴GCC 您正在使用該寄存器,因此它不會在其中存儲任何內容 。你還應該在clobber列表中列出「內存」,所以gcc 知道它不能信任它可能在你的代碼塊之前加載的值。

    asm volatile( 「Code goes here」 :::「eax」,「esp」,「memory」 );

順便說一句:你的代碼做了一些「壞事」,比如移動esp,這可能會導致問題,除非你確切知道你在做什麼。

+0

謝謝你的回答。 – behe 2012-04-24 11:29:39

+0

正如我所說的,代碼非常長且複雜,我在這裏發佈的只是原始代碼的一小部分。使用您提出的第二種方法重寫整個代碼將非常耗時。是否有其他方式來聲明寄存器eax已被保留? – behe 2012-04-24 11:32:31

+0

事實上,有後 MOV EAX許多其它指令,尤指 子ESP,116 和ESP,〜15 MOV [ESP + 112],EAX ,其不方便張貼在這裏。 – behe 2012-04-24 11:34:05

-2

英特爾風格的塊後空asm塊解決問題,這樣的:

__asm volatile { 
    mov eax, esp 
    sub esp, 116 
    and esp, ~15 
    mov [esp+112], eax  
}; 
__asm__ __volatile__ ("":::"eax", "memory"); 

但是,如果不恢復%esp,這將造成嚴重破壞。

相關問題