为什么 MS C++将此代码添加到程序集中?
我有一些代码(内联汇编)。
void NativeLoop()
{
int m;
__asm
{
PUSH ECX
PUSH EDX
MOV ECX, 100000000
NEXTLOOP:
MOV EDX, ECX
AND EDX, 0X7FFFFFFF
MOV DWORD PTR m, EDX
DEC ECX
JNZ NEXTLOOP
POP EDX
POP ECX
}
}
MS C++ Automagicaly 将这些代码(标有 **)添加到我的程序中。
为什么?
如何避免呢?
**push ebp
**mov ebp,esp
**push ecx
push ecx
push edx
mov ecx,5F5E100h
NEXTLOOP:
mov edx,ecx
and edx,7FFFFFFFh
mov dword ptr m,edx
dec ecx
jnz NEXTLOOP
pop edx
pop ecx
**mov esp,ebp
**pop ebp
**ret
i have some code(inline assembly).
void NativeLoop()
{
int m;
__asm
{
PUSH ECX
PUSH EDX
MOV ECX, 100000000
NEXTLOOP:
MOV EDX, ECX
AND EDX, 0X7FFFFFFF
MOV DWORD PTR m, EDX
DEC ECX
JNZ NEXTLOOP
POP EDX
POP ECX
}
}
MS C++ Automagicaly adds these codes(marked with **) to my procedure.
Why?
how to avoid it?
**push ebp
**mov ebp,esp
**push ecx
push ecx
push edx
mov ecx,5F5E100h
NEXTLOOP:
mov edx,ecx
and edx,7FFFFFFFh
mov dword ptr m,edx
dec ecx
jnz NEXTLOOP
pop edx
pop ecx
**mov esp,ebp
**pop ebp
**ret
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
它是标准函数进入和退出代码。它建立和拆除堆栈框架。如果你不想要它,你可以使用 __declspec(naked)。如果这样做,请不要忘记包含 RET。
但是,您的代码片段依赖于有效的堆栈框架,您的“m”变量需要它。它的地址是[ebp-10]。如果没有前导码,ebp 寄存器将无法正确设置,并且您将破坏调用者的堆栈帧。
It is the standard function entry and exit code. It establishes and tears down the stack frame. If you don't want it you can use __declspec(naked). Don't forget to include the RET if you do.
However, your snippet relies on a valid stack frame, your "m" variable requires it. It is addressed at [ebp-10]. Without the preamble, the ebp register won't be set correctly and you'll corrupt the stack frame of the caller.
它正在维护调用堆栈。如果您将函数定义为,
您将看到相同的程序集。
It's maintaining the call stack. If you defined the function as
You would see the same assembly.
我记得你可以在MSVC++中
__declspec(naked)
,这意味着你必须自己处理堆栈,这意味着你必须保存你破坏的每个寄存器,并恢复它。没有唯一的规则可以正确地做到这一点,因为它取决于调用约定。请参阅 http://en.wikipedia.org/wiki/X86_calling_conventions 。
旁注:在 gcc 中,您明确向编译器说明您将驱动无效的内容,以便 gcc 将输出更优化的保存/恢复/堆栈帧代码(如果有)。在 MSVC 中,asm 对于编译器来说主要是一个黑匣子,对于编译器来说它通常/总是最糟糕的。
请参阅 http://www.ibiblio.org /gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3 ,gcc内联asm语法更难看,但实际上更有效。
I remember that you can
__declspec(naked)
in MSVC++, meaning that you have to take care of the stack yourself, that means you must save every register you clobber, and restore it.There is no the-one-rule to do that properly, as it depends on calling convention. See http://en.wikipedia.org/wiki/X86_calling_conventions .
Sidenote: In gcc, you explitly state to the compiler what you will drive invalid, so that gcc will output more optimal save/restore/stackframe-code, if any. In MSVC, asm is mostly a blackbox to the compiler, for which it will often/always the worst.
See http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html#ss5.3 , gcc inline asm syntax is more ugly, but effectively more effective.
如果您可以搜索 C++ 调用约定,您将更好地了解编译器正在做什么。
If you can do a search on C++ calling conventions, you'll understand better what the compiler is doing.