visual-c++ - 为什么VC++编译器MOV + PUSH args不仅仅是PUSH它们? x86

标签 visual-c++ assembly compiler-construction x86

在这种从VC++进行的反汇编中,正在执行一个函数调用。编译器在将本地指针压入寄存器之前先将其移动到寄存器:

    memcpy( nodeNewLocation, pNode, sizeCurrentNode );
0041A5DA 8B 45 F8             mov         eax,dword ptr [ebp-8]  
0041A5DD 50                   push        eax  
0041A5DE 8B 4D 0C             mov         ecx,dword ptr [ebp+0Ch]  
0041A5E1 51                   push        ecx  
0041A5E2 8B 55 D4             mov         edx,dword ptr [ebp-2Ch]  
0041A5E5 52                   push        edx  
0041A5E6 E8 67 92 FF FF       call        00413852  
0041A5EB 83 C4 0C             add         esp,0Ch 

为什么不直接插入它们呢? IE
push  dword ptr [ebp-8]

另外,如果您要进行单独的推送,为什么不手动进行。换句话说,不要在上面做“推eax”,而是
mov [esp], eax

这样做的好处是,在执行了3次移动之后,您可以执行一次减法来设置新的堆栈指​​针,而不是通过插入隐式地减去3次。

更新-发布版本

这是为发布而编译的相同代码:
; 741  :    memcpy( nodeNewLocation, pNode, sizeCurrentNode );

  00087 8b 45 f8     mov     eax, DWORD PTR _sizeCurrentNode$[ebp]
  0008a 8b 7b 04     mov     edi, DWORD PTR [ebx+4]
  0008d 50       push    eax
  0008e 56       push    esi
  0008f 57       push    edi
  00090 e8 00 00 00 00   call    _memcpy
  00095 83 c4 0c     add     esp, 12            ; 0000000cH

绝对比调试版本有效,但它仍在执行MOV/PUSH组合。

最佳答案

这是一个优化。在英特尔处理器手册第4卷第12.3.3.6节中明确提到:

In Intel Atom microarchitecture, using PUSH/POP instructions to manage stack space and address adjustment between function calls/returns will be more optimal than using ENTER/LEAVE alternatives. This is because PUSH/POP will not need MSROM flows and stack pointer address update is done at AGU. When a callee function need to return to the caller, the callee could issue POP instruction to restore data and restore the stack pointer from the EBP.

Assembly/Compiler Coding Rule 19. (MH impact, M generality) For Intel Atom processors, favor register form of PUSH/POP and avoid using LEAVE; Use LEA to adjust ESP instead of ADD/SUB.



手册的其余部分不清楚原因,但确实提到了隐式ESP调整可能造成的3个周期的AGU停顿。

关于visual-c++ - 为什么VC++编译器MOV + PUSH args不仅仅是PUSH它们? x86,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13124501/

相关文章:

c++ - 如何使用vc++获取菜单项文本?

c# - 当 c# 访问 c++ dll 时尝试读取或写入 protected 内存错误

c++ - 如何将类方法的地址转换为 (void *)

c - C 中的枚举类型警告

c - 链接 c 项目时体系结构 x86_64 的 undefined symbol

c++ - 预编译头如何减少编译时间

c - C 语言 hello world 程序的汇编代码

assembly - 除以负数会导致 NASM 溢出

使用 shellcode 调用 x86 本地函数

将c语言转换为IA32汇编语言