Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 仅在版本中出现内联程序集错误_C++_Assembly_Stack Overflow_Inline Assembly - Fatal编程技术网

C++ 仅在版本中出现内联程序集错误

C++ 仅在版本中出现内联程序集错误,c++,assembly,stack-overflow,inline-assembly,C++,Assembly,Stack Overflow,Inline Assembly,我有一个只有内联汇编才能实现的程序 此函数用于调用我们使用变量参数(数字和类型)的其他函数 我的所有程序在调试模式下都工作得很好,但当我在发行版中测试它时,出现以下错误: SomeThing.exe: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x0A4B2FFC). 下面是我的汇编函数: __declspec( naked ) void Player_dummyFunction( dvrFunction* iFunc ) {

我有一个只有内联汇编才能实现的程序

此函数用于调用我们使用变量参数(数字和类型)的其他函数

我的所有程序在调试模式下都工作得很好,但当我在发行版中测试它时,出现以下错误:

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 */
}

尝试在发行版中添加/Oy-


检查其他优化选项:

这不是一个真正的答案,但是注释中的代码变得非常混乱,汇编代码更糟糕,因为它比C/C++更依赖换行符进行格式化

__asm lea edi,[ebp-0C0h]  
__asm mov ecx,30h  
__asm mov eax,0CCCCCCCCh  
__asm rep stos dword ptr es:[edi]  
这是“调试模式”代码,您真的不应该在发布模式下这样做。我很确定,事实上,大部分的epilog和prolog代码根本不需要你的功能——它只是“调试”的东西

现在有一些可能是答案: 我感觉崩溃是由
getparamsumber
在非调试模式下返回的数字大于在调试模式下返回的数字引起的。我绝对不确定,这对我来说才是最有意义的。或者,
getParamsMember
是否返回负数


您的代码还依赖于
edx
未被
GetParamsAddress
更改,这可能不是真的?特别是,它可能会根据优化模式而改变

我的猜测是,在ret指令之后,管道将运行到某些代码中。我看到您已经非常仔细地恢复了堆栈,高于正常需要。(事实上,如果这些函数中的某些函数破坏了ebp呢?注释?uu asm mov esp,ebp?)我认为应该以各种组合尝试以下内容:

  • 在最后的
    ret
    之后添加16个
    nop
    s
  • 删除
    esp
    恢复<代码>/\u asm mov esp,ebp
  • 降低堆栈指针以包围代码,这样,如果某些代码弹出过多,顶部不会损坏:(esp在此保存)
    sub esp,1000
    ,code here,
    mov esp,ebp
    (假设堆栈已恢复到位)
  • 移动堆栈还原内容,
    \u asm push ebp
    __asm mov ebp,esp
    ,以后的
    \uu asm mov esp,ebp
    __asm pop ebp
    /在/您的注册表中还原内容。若堆栈确实在代码中损坏,那个么恢复代码将不会像现在那个样保存esi、edi和ebx寄存器
  • 注释掉你的函数调用,看看哪个函数破坏了它,然后逐步找出如何恢复以前的状态

由于优化,程序可能不再具有帧指针。堆栈布局也可能发生其他更改。我建议您让编译器处理堆栈(带有参数和局部变量),并且只在汇编程序中执行所需的最小操作(如果需要的话!)。与C++中的汇编程序相比,你是否真正衡量了汇编程序的性能?有优化和没有优化?我没有读代码,但是,你使用的编译器和优化参数是什么(在发行版和调试模式上)?@JoachimPileborg谢谢你,也许我可以让编译器做序言和尾声,但其他的事情必须在汇编中完成…@Sharpie我在VS2012上工作。在调试中没有优化/O2和/Ob2在发布中。我非常确定帧指针不是问题。即使在没有帧指针的情况下编译代码,“想要”这样做的函数也可以通过按下帧指针寄存器(上面代码中的EBP)来使用帧指针。我认为“必须在汇编程序中完成”的原因是你不知道参数的数量?只是做了,但我有同样的问题。通过添加一些优化选项(/O1)进行调试,我也遇到了同样的问题。但在调试模式下,它指向GetParamsAddress:
push[eax]
之后的那一行。您可以尝试逐行调试(使用/O1)以查看此时eax中的内容。。试着找出它的值是否正确。(调试汇编总是很有趣的--)我很确定情况并非如此。x86是一致的体系结构,这意味着依赖于其他指令的指令将暂停,直到其依赖关系完成。您可以编写任何您喜欢的内容,以任何顺序在x86中生成正确的结果,并且它将实现您期望的功能[根据处理器勘误表,但我100%确定这不是处理器勘误表]。我越是看它,我就觉得它是“被其他东西使用后再使用寄存器”。这是正确的答案,我刚刚看到我的edx在调用GetParamsAddress后是假的。我通过在函数调用后添加pop-edx解决了这个问题。我知道epilog和prolog是不需要的,但实际上我添加了它,因为我正在探索能够解决这个问题的各种可能性:-)但感谢您的帮助。为了提高效率,您可以尝试使用“被调用方保存”的寄存器,如EDI或ESI。[但是,您确实需要在代码开始时推送该寄存器-但它确实将代码保存在循环中]谢谢您的建议。我会的。