Sco*_*ott 9 c linux windows assembly calling-convention
我正在考虑将为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) {}
Run Code Online (Sandbox Code Playgroud)
来自维基百科功能序言和结语:
在汇编语言编程中,函数序言是函数开头的几行代码,它准备堆栈和寄存器以供在函数内使用。类似地,函数结尾出现在函数末尾,并将堆栈和寄存器恢复到它们在调用函数之前所处的状态。
为确保编译器不会在您的函数中自动生成额外的代码,请始终使用__declspec(naked)
约定声明函数。
让我们来看看这个函数:
void myTrampoline()
{
__asm {
PUSHFD
PUSHAD
CALL jumpHookCallback
POPAD
POPFD
POP EAX
MOV AL, 1
POP EDI
POP ESI
JMP [restoreJumpHook]
}
}
Run Code Online (Sandbox Code Playgroud)
现在编译器将生成代码来操作称为函数的序言和结尾的函数的堆栈帧,结果将如下所示
;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
Run Code Online (Sandbox Code Playgroud)
但如果我们使用 __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]
}
}
Run Code Online (Sandbox Code Playgroud)
结果将如下所示:
PUSHFD
PUSHAD
CALL jumpHookCallback
POPAD
POPFD
POP EAX
MOV AL, 1
POP EDI
POP ESI
JMP [restoreJumpHook]
Run Code Online (Sandbox Code Playgroud)
基本上,函数序言为局部变量设置了一个堆栈框架,结语负责清理它.这通常由编译器自动完成.如果您使用__declspec(naked)
,设置此堆栈框架将取决于您,因此它为您提供了更大的灵活性.
GNU gcc编译器也支持裸,但显然不适用于x86:在页面中搜索"naked" (我还没试过看它是否适用于x86)