为什么 MS C++将此代码添加到程序集中?

发布于 2024-08-21 19:30:25 字数 792 浏览 6 评论 0原文

我有一些代码(内联汇编)。

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

我恋#小黄人 2024-08-28 19:30:25

它是标准函数进入和退出代码。它建立和拆除堆栈框架。如果你不想要它,你可以使用 __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.

凉风有信 2024-08-28 19:30:25

它正在维护调用堆栈。如果您将函数定义为,

int NativeLoop() { }

您将看到相同的程序集。

It's maintaining the call stack. If you defined the function as

int NativeLoop() { }

You would see the same assembly.

西瑶 2024-08-28 19:30:25

我记得你可以在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.

惯饮孤独 2024-08-28 19:30:25
  **push        ebp  ;save EBP register
  **mov         ebp,esp  ;Save the stackframe
  **push        ecx  ; So that the variable `m` has an address
;...
  **mov         esp,ebp ;restore the stack frame to it's original address
  **pop         ebp   ;restore EBP register
  **ret ;return from function call
  **push        ebp  ;save EBP register
  **mov         ebp,esp  ;Save the stackframe
  **push        ecx  ; So that the variable `m` has an address
;...
  **mov         esp,ebp ;restore the stack frame to it's original address
  **pop         ebp   ;restore EBP register
  **ret ;return from function call
情绪失控 2024-08-28 19:30:25

如果您可以搜索 C++ 调用约定,您将更好地了解编译器正在做什么。

If you can do a search on C++ calling conventions, you'll understand better what the compiler is doing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文