函数调用的间接奇怪程度

时间:2011-08-28 15:28:59

标签: visual-studio-2008 visual-c++ x86

我正在写一些低级代码,我注意到函数调用的一些不必要的间接性,我根本就没有得到这个间接的原因。这是显示该行为的虚拟代码:

__declspec(noinline) int get_alignment(void * ptr)
{
    return 1;
}

__declspec(noinline) int test123()
{
    char buf[123];
    return get_alignment(buf);
}

然后,当我在asm模式(Ctrl + F11)的调试器中逐步执行函数test()内的代码时,我看到了:

__declspec(noinline) int test123()
{
0041FA70  sub         esp,7Ch 
    char buf[123];
    return get_alignment(buf);
0041FA73  lea         eax,[esp] 
0041FA76  push        eax  
0041FA77  call        get_alignment (40A38Fh) 
}
...
get_alignment:
0040A38F  jmp         get_alignment (41FA60h) 
...
__declspec(noinline) int get_alignment(void * ptr)
{
    return 1;
0041FA60  mov         eax,1 
}

所以,问题是关于额外的间接水平: get_alignment: 0040A38F jmp get_alignment(41FA60h)

WTF是关于什么的?!我只是没有得到它,它不是来自dll的导入函数,它是可执行文件中定义的本地函数。此可执行文件使用各种优化(链接时间代码生成除外)编译。 如果我将static添加到get_alignment的声明中,那么额外的间接消失了。但我不是在寻找一个“修复”,我只想了解为什么那里会有额外的跳跃!

在我的真实应用程序中,我实际上使用了.asm文件中编写的函数,我只是不明白为什么会产生额外的跳转。似乎如果我在C模式(而不是C ++)中编译我的代码,那么我再也看不到间接级别......

任何人都可以对这种奇怪的行为有所了解吗?

谢谢!

3 个答案:

答案 0 :(得分:2)

您可能已启用增量链接。增量链接模块“可以包含跳转thunk以处理将函数重定位到新地址”。 http://msdn.microsoft.com/en-US/library/4khtbfyf(v=VS.80).aspx

答案 1 :(得分:2)

这是链接器的/ INCREMENTAL选项的副作用。这将启用增量链接和编辑+继续。在程序运行时编辑代码时使用跳转。替换函数被编译到另一个地址,并且jmp目标被修补以指向新函数。增量链接也使用它,以避免必须从头开始重新创建二进制图像。

答案 2 :(得分:1)

简而言之,在我的情况下,启用了增量链接,因为我没有为我的构建明确禁用它。 通常,链接器选项可以禁用增量链接以避免额外跳转(/ INCREMENTAL:NO选项)