我正在考虑将为Windows编写的脚本引擎移植到Linux;这是Winamp的可视化平台AVS。我不确定目前是否可能。据我所知,代码正在获取C函数nseel_asm_atan
和nseel_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) {}
答案 0 :(得分:8)
基本上,函数序言为局部变量设置堆栈框架,结语负责清理它。这通常由编译器自动完成。如果您使用__declspec(naked)
,设置此堆栈框架将取决于您,因此它为您提供了更大的灵活性。
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]