我使用 Visual Studio C++ 2008 SP1 编译了以下内容,x64
C++
编译器:
我很好奇,为什么编译器要添加那些 nop
之后的说明call
s?
PS1。我会理解第二个和第三个 nop
s 将在 4 字节边距上对齐代码,但第一个 nop
打破了这个假设。
PS2。编译的 C++ 代码中没有循环或特殊优化内容:
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestDlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
//This makes no sense. I used it to set a debugger breakpoint
::GdiFlush();
srand(::GetTickCount());
}
PS3。 附加信息: 首先,感谢大家的意见。
以下是补充意见:
我的第一个猜测是 incremental linking可能与它有关。但是,
Release
Visual Studio
中的build设置项目有incremental linking
关闭。这似乎会影响
x64
仅构建。与x86
构建的代码相同(或Win32
)没有那些nop
s,即使使用的指令非常相似:
- 我尝试使用更新的链接器构建它,即使
x64
VS 2013
生成的代码看起来有些不同,它仍然添加了那些nop
在一些call
之后年代:
- 还有
dynamic
与static
链接到 MFC 对这些nop
的存在没有影响s。这个是通过动态链接到 MFC dll 的VS 2013
构建的。 :
- 还要注意那些
nop
s 可以出现在near
之后和far
call
s 也是如此,它们与对齐无关。这是我从IDA
获得的部分代码如果我再进一步:
如您所见,nop
在 far
之后插入call
这恰好“对齐”下一个 lea
B
上的说明地址!如果这些只是为了对齐而添加的,那是没有意义的。
- 我原本倾向于相信,自从
near
relative
call
s(即以E8
开头的那些)是 somewhat faster比far
call
s(或以FF
开头的,在这种情况下为15
)
链接器可能会尝试使用 near
call
s 首先,因为它们比 far
短一个字节call
s,如果成功,它可以用 nop
填充剩余空间s 在最后。但是上面的例子(5)有点覆盖了这个假设。
所以我仍然没有明确的答案。
最佳答案
这纯粹是一种猜测,但它可能是某种 SEH 优化。我说 优化 因为 SEH 似乎在没有 NOP 的情况下也能正常工作。 NOP 可能有助于加快展开。
在以下示例 (live demo with VC2017) 中,在 test1
中调用 basic_string::assign
之后插入了一个 NOP
,但是不在 test2
中(相同但声明为非抛出1)。
#include <stdio.h>
#include <string>
int test1() {
std::string s = "a"; // NOP insterted here
s += getchar();
return (int)s.length();
}
int test2() throw() {
std::string s = "a";
s += getchar();
return (int)s.length();
}
int main()
{
return test1() + test2();
}
组装:
test1:
. . .
call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::assign
npad 1 ; nop
call getchar
. . .
test2:
. . .
call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::assign
call getchar
请注意,MSVS 默认使用 /EHsc
标志(同步异常处理)进行编译。没有那个标志,NOP
就会消失,而使用 /EHa
(同步 和 异步异常处理),throw()
不再有任何影响,因为 SEH 始终处于开启状态。
1 出于某种原因,只有 throw()
似乎减少了代码大小,使用 noexcept
使生成的代码更大,甚至召唤更多NOP
。 MSVC...
关于c++ - 为什么 64 位 VC++ 编译器在函数调用后添加 nop 指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44854497/