2013-10-24 52 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语句中。