【发布时间】:2012-10-18 22:29:23
【问题描述】:
在这个 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
为什么不直接推送它们呢?即
push dword ptr [ebp-8]
另外,如果您要单独推送,为什么不手动进行。换句话说,不要在上面做“push eax”,而是做
mov [esp], eax
等等。这样做的好处是,在执行 3 次 mov 之后,您可以执行一次减法来设置新的堆栈指针,而不是通过推送隐式减去 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 组合。
【问题讨论】:
-
这实际上是在发布模式下编译的吗?它看起来隐约调试
-
它是为调试而编译的。为什么在这种情况下会有所不同?
-
因为在调试模式下编译器不会关心这些事情。
-
在你的最后一个例子中,通过延迟 sub 暂时使堆栈不平衡是否安全?我知道这在实模式下是个坏消息(在不合时宜的时候中断“借用”堆栈的一部分),但我不确定在保护模式下。
-
通过解耦指令,可以减少寄存器停顿的数量。
标签: visual-c++ assembly compiler-construction x86