有人可以解释__declspec(裸体)吗?

时间:2010-06-11 09:00:29

标签: c linux windows assembly calling-convention

我正在考虑将为Windows编写的脚本引擎移植到Linux;这是Winamp的可视化平台AVS。我不确定目前是否可能。据我所知,代码正在获取C函数nseel_asm_atannseel_asm_atan_end的地址,并将它们存储在一个可以在代码执行期间引用的表中。

我看过MS的文档,但我不确定__declspec(naked)到底做了什么。什么是文档中提到的prolog和epilog代码?这与Windows调用约定有关吗?这是便携式吗?了解使用类似技术的任何基于Linux的示例?

static double (*__atan)(double) = &atan;
__declspec ( naked ) void nseel_asm_atan(void)
{
  FUNC1_ENTER

  *__nextBlock = __atan(*parm_a);

  FUNC_LEAVE
}
__declspec ( naked ) void nseel_asm_atan_end(void) {}

2 个答案:

答案 0 :(得分:8)

基本上,函数序言为局部变量设置堆栈框架,结语负责清理它。这通常由编译器自动完成。如果您使用__declspec(naked),设置此堆栈框架将取决于您,因此它为您提供了更大的灵活性。

有很多参考文献:hereherealso here等。

GNU gcc编译器也支持裸,但显然不适用于x86:search for "naked" in the page(我还没试过看它是否适用于x86)

答案 1 :(得分:2)

来自wikipedia函数的序言和结尾:

  

在汇编语言编程中,函数序言只有几行   函数开头的代码段,它们准备堆栈并   注册以在功能内使用。同样,功能   结语出现在函数的末尾,并恢复堆栈   并注册到该功能之前的状态   叫。

为确保编译器不会在您的函数内自动生成额外的代码,请始终使用__declspec(naked)约定声明该函数。

让我们看一下这个功能:

void myTrampoline()
{
__asm {
  PUSHFD
  PUSHAD
  CALL jumpHookCallback
  POPAD
  POPFD
  POP EAX
  MOV AL, 1
  POP EDI
  POP ESI
  JMP [restoreJumpHook]
 }
}

现在,编译器将生成用于操纵函数的堆栈框架的代码,称为函数的序言和结语,结果将如下所示

;Prologue
push ebp
mov ebp, esp
sub esp, N

PUSHFD
PUSHAD
CALL jumpHookCallback
POPAD
POPFD
POP EAX
MOV AL, 1
POP EDI
POP ESI
JMP [restoreJumpHook]

;Epilogue
mov esp, ebp
pop ebp
ret

但是如果我们使用__declspec(naked),就不会有Prologue没有Epilogue

void __declspec(naked) myTrampoline()
{
__asm {
  PUSHFD
  PUSHAD
  CALL jumpHookCallback
  POPAD
  POPFD
  POP EAX
  MOV AL, 1
  POP EDI
  POP ESI
  JMP [restoreJumpHook]
 }
}

结果将如下所示:

    PUSHFD
    PUSHAD
    CALL jumpHookCallback
    POPAD
    POPFD
    POP EAX
    MOV AL, 1
    POP EDI
    POP ESI
    JMP [restoreJumpHook]