2013-07-02 35 views
0

我認爲這是一個簡單的問題,但我找不到任何東西。 如果我寫GCC內聯ASM保證

void bar() 
{ 
    { 
     void *rax = 0/* ...*/, *rbx = 0/* ... */; 
     asm volatile ("movq %0, %%rax; movq %1, %%rbx;" : : "m"(rax), "m"(rbx)); 
     goto foo;  
    } 

    { 
     foo: 
     void* rax, *rbx; 
     asm volatile ("movq %%rax, %0; movq %%rbx, %1;" : "=m"(rax), "=m"(rbx)); 

     // LOTS OF CODE 
    } 
} 

是它保證我可以運行之前在所述第二塊中的任何其他代碼讀取操作RAX/RBX的值?

+1

看起來像一個XY問題 - 你真的想解決什麼? –

+0

我正在爲C++編寫一個函數鉤子庫。我想使用未被ABI使用的寄存器來將用戶數據指針傳遞給鉤子函數。 – Ethon

+2

那你爲什麼不寫一個調用實際函數的彙編封裝器呢?這是解決這個問題的傳統方法。 –

回答

1

在gcc中使用volatileasm將保證編譯器不會重新排序。但是,不能保證編譯器不會在foo:標籤和內聯asm語句之間添加額外的代碼。當然,這意味着你不能依賴於該部分保留的寄存器值 - 我還沒有設法得出一個明顯的例子,但我很確定編譯器不能保證這可以不會發生。

3

否 - 編譯器根據它在asm語句之前/之後分配的寄存器/存儲器位置的約束來掛鉤輸入/輸出值,並假定其他寄存器不受影響。所以在你的情況下,它可能會把一些重要的東西放在%%eax%%ebx這是你正在破壞(這可能會導致崩潰或其他不良行爲)。

任何時候您在asm語句中使用固定寄存器時,都必須在clobbers列表中列出這些寄存器(除非您使用映射到特定寄存器的約束)。因此,在最起碼,你將需要:

asm volatile ("movq %0, %%rax; movq %1, %%rbx;" : : "m"(rax), "m"(rbx) : "rax", "rbx"); 

爲您彙編語句 - 但即便如此,也沒有機制保障,編譯器不會把 東西進入%%eax%%ebx您的第一個ASM塊之後和之前的秒(破壞你正試圖保存的值)。

+0

感謝您的回覆 - 我認爲我必須更具體。我只包含第一個塊來顯示行爲 - 第一個塊是由編譯器創建的,而不是由編譯器創建的,但是我自己手動將指令字節寫入緩衝區並執行緩衝區。對於那個很抱歉。我只需要知道是否可以依賴第一個執行的第二個塊中的inline asm語句,並且在第二個塊中的後續代碼使用它們來執行其他操作之前。 – Ethon

+0

@Ethon:那麼聽起來你可能想要''a'',''b'',''c'',''d''','S''和''D''約束來綁定到特定的寄存器 –