【发布时间】:2013-04-19 09:20:35
【问题描述】:
我有一个程序,它的功能只能通过内联汇编实现。
此函数用于调用我们可变参数(数字和类型)的其他函数。
我所有的程序都在调试模式下运行良好,但是当我在发布版中测试它时,我有这个错误:
SomeThing.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x0A4B2FFC).
这是我的汇编函数:
__declspec( naked ) void Player_dummyFunction( dvrFunction* iFunc )
{
__asm push ebp
__asm mov ebp,esp
__asm sub esp,0C0h
__asm push ebx
__asm push esi
__asm push edi
__asm lea edi,[ebp-0C0h]
__asm mov ecx,30h
__asm mov eax,0CCCCCCCCh
__asm rep stos dword ptr es:[edi]
/* Need the number of params. */
__asm mov ecx, dword ptr [iFunc] /* Use the calling convention of VC */
__asm call dvrFunction::GetParamsNumber /* this->m_ParamsData.size() */
__asm mov edx, eax /* Save the return value */
__asm cmp edx, 0 /* Condition to know if the GL function has params (edx == 0) */
__asm jz body /* Jump to the body label if the previous condition is true */
push_loop:
/* Push the parameters in the reverse order on the stack */
__asm mov ecx, dword ptr [iFunc] /* Another use of the calling convention */
__asm push edx
__asm call dvrFunction::GetParamsAddress /* this->m_ParamsData[i]->GetAddress() */
__asm push [eax] /* Push the dereferenced address (the value) on the stack */
/* edx is automatically decremented by GetParamsAddress */
__asm cmp edx, 0 /* Is edx == 0 ? */
__asm jnz push_loop /* If no, go back push_loop label */
body:
__asm mov ecx, dword ptr [iFunc] /* Use the thiscall convention */
__asm call dvrFunction::GetCName /* Call GetCName to have a const char* */
__asm push eax /* Push the name into the stack */
__asm lea ecx, g_PlatBuiltin /* Use another convention for the structs */
__asm call [ecx]g_PlatBuiltin.wglGetProcAddress /* Call the real wglGetProcAddress to have the pointer to the GL function */
__asm mov ecx, eax /* Save the result -> TODO Is this operation needed ? */
__asm call ecx /* Call the original open GL function */
__asm pop edi
__asm pop esi
__asm pop ebx
__asm add esp,0C0h
__asm cmp ebp,esp
//__asm call __RTC_CheckEsp (0125114Fh)
__asm mov esp,ebp
__asm pop ebp
__asm ret /* Call the ret asm command */
}
【问题讨论】:
-
由于优化,程序可能不再有帧指针。堆栈布局的其他更改也可能发生。我建议你让编译器处理堆栈(使用参数和局部变量),并且只在汇编程序中做最小的需要的东西(如果需要的话!)。与 C++ 中的汇编函数相比,您是否实际测量过汇编函数的性能?优化和不优化?
-
我没有看代码但是,你使用什么编译器以及优化参数是什么(在发布和调试模式下)?
-
@JoachimPileborg 谢谢,也许我可以让编译器做序言和结语,但其他的东西必须在汇编中完成......
-
@Sharpie 我正在开发 VS2012。调试中没有优化。 /O2 和 /Ob2 正在发布中。
-
我很确定帧指针不是问题。即使在没有帧指针的情况下编译代码,“想要”这样做的函数也可以通过压入帧指针寄存器(上面代码中的 EBP)来使用帧指针。我认为“必须在汇编程序中完成”的原因是您不知道参数的数量?
标签: c++ assembly stack-overflow inline-assembly