2013-10-24 102 views
1

我可以使用Visual Studio 2012跳轉到一個地址。當涉及到gcc/mingw時,我無法判斷我的跳轉是否正確。gcc內聯彙編jmp地址;裸函數

如何跳轉到gcc中的地址?

我想:

__declspec(naked) void DXHook_D3DPERF_BeginEvent() 
{ 
    #ifdef _MSC_VER //If using visual studio.. 
    __asm{jmp[Addr]} //Jump to: Address stored in Addr. 
    #else   //else using gcc.. 
    __asm("jmp *%0" 
      : /*No Outputs*/ 
      : "r" (Addr) 
      : "%eax"); 
    #endif 
} 

這是正確的嗎?另外,有沒有辦法讓海灣合作委員會停止打擾我:

warning: 'naked' attribute directive ignored. 

爲什麼它忽略我的裸體屬性?

+1

可能會有幫助[裸(C++)](http://msdn.microsoft.com/en-us/library/h5w10wxs.aspx)和[有人可以解釋__declspec(裸體)請]?(http:// stackoverflow.com/questions/3021513/could-someone-explain-declspecnaked-please) –

+1

裸體屬性被忽略,因爲它不適用於x86。正在嘗試做什麼?寄存器的值應該發生什麼?在跳轉之前變量是否應該寫回內存? –

+0

你有沒有試過叮叮聲?它應該支持與GCC相同的語法,我認爲它們也支持MVC支持...... – nonsensickle

回答

1

TL; DR在GCC,這是only available on: ARM, AVR, MCORE, MSP430, NDS32, RL78, RX and SPU ports

它是NOT available on x86

Workaround (proposed by Brendon in the comments)

完整的答案

(這個答案的其餘部分假定您使用的是支持的目標)

那是因爲你使用的是Windows屬性語法,__declspec與海灣合作委員會。從MSDN reference on __declspec

引用:

擴展屬性語法簡化和標準化Microsoft特定擴展到C和C++語言。

您應該使用GCC function attribute syntax代替或並行。

也請注意,從this GCC article以下報價:

注:語義並不Windows和該GCC 功能之間的相同 - 例如,__declspec(dllexport)的無效(* FOO)(無效)和 void(__declspec(dllexport)* foo)(void)意味着完全不同的東西 而這會產生警告,表明無法將 屬性應用於GCC上的非類型。

因此,在GCC中使用__declspec語法的方式也可能存在問題(如果它甚至支持的話)。

你還應該注意到,它支持的GCC狀態只有__declspec屬性是__declspec(dllexport)(如已經提到的GCC attribute syntax link中所述)。

那麼讓我們來看看一個通用的解決您的問題,但首先我們需要了解實際GCC attribute syntax,找到以下內容:

的屬性說明符列表可以說明符 之前立即出現(除第一個)在 聲明多個標識符的逗號分隔的聲明列表中,使用單個列表 指定符和限定符。這些屬性說明符僅適用於其聲明符出現前的 標識符。例如,在

__attribute__((noreturn)) void d0 (void), 
    __attribute__((format(printf, 1, 2))) d1 (const char *, ...), 
     d2 (void) 

noreturn屬性適用於聲明的所有函數;格式屬性 只適用於d1。

所以解決您的問題會像下面這樣:

#ifdef __GNUC__ 
#define ATTRIBUTE_NAKED __attribute__((naked)) 
#else 
#define ATTRIBUTE_NAKED __declspec(naked) 
#endif 

ATTRIBUTE_NAKED void DXHook_D3DPERF_BeginEvent() 
{ 
    #ifdef _MSC_VER //If using visual studio.. 
    __asm{jmp[Addr]} //Jump to: Address stored in Addr. 
    #else   //else using gcc.. 
    __asm("jmp *%0" 
      : /*No Outputs*/ 
      : "r" (Addr) 
      : "%eax"); 
    #endif 
} 

編輯:

重要的是要注意,這個屬性是platform specific是很重要的。我引述:

該屬性可在ARM,AVR,MCORE,MSP430,NDS32,RL78,RX和SPU端口。它允許編譯器構造必要的函數聲明,同時允許函數的主體爲彙編代碼。指定的函數不會有由編譯器生成的序列/尾聲序列。只有基本的asm 語句可以安全地包含在裸函數中(請參見Basic Asm)。 雖然使用擴展的asm或基本asm和C代碼的混合可能似乎工作,但它們不能依賴於可靠地工作,並且不支持 。

引自GCC documentation on function attributes

邊註上clang attributes

可能進一步閱讀可以幫助(大多與GCC兼容),但these comments似乎表明匹配GCC行爲的願望。

+0

http://i.imgur.com/IfZsecR.png和http://i.imgur.com/hIzpIsW.png你有沒有測試你的代碼,因爲我確實沒有...... GCC 4.9.2 – Brandon

+0

感嘆,你似乎在使用不受支持的目標。我認爲你正在與ARM合作,似乎我錯誤地認爲。它在[documentation](https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html)中清楚地表明x86在naked屬性旁邊不受支持。這裏還有一個[bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50242)。我已經更新了我的答案來解釋這一點。 – nonsensickle

+0

@Brandon看着你的內聯彙編很顯然,這是x86 ...哎呀,不知道我以前錯過了它。 – nonsensickle

0

要執行Visual C++代碼的等效操作,請在彙編中將其完全實現爲單獨的文件或頂級(而不是函數)asm語句中。