为什么在调用函数时会有额外的间接层?

时间:2018-01-20 18:25:04

标签: c++ visual-studio assembly linker visual-studio-2017

背景

所以我一直在观看有关编译器和链接器(在VS 2017 VC ++编译器/链接器中)如何通过查看汇编文件来拼凑所有内容的教程视频。当我编译并链接这两个cpp文件时:

main.cpp (注意:我已经删除了与c库的隐式链接,并定义了我自己的' mainCRTStartup' funcion,以便更轻松地查看结果.exe文件。)

int Func1(int x);

int mainCRTStartup(void)
{
    Func1(3);

    return 0;
}

func1.cpp

int Func1(int x)
{
    x +=2;

    return x;
}

我得到了我的结果main.exe,在程序集中看起来像这样:

File Type: EXECUTABLE IMAGE

  0000000140001000: CC                 int         3
  0000000140001001: CC                 int         3
  0000000140001002: CC                 int         3
  0000000140001003: CC                 int         3
  0000000140001004: CC                 int         3
@ILT+0(?Func1@@YAHH@Z):
  0000000140001005: E9 36 00 00 00     jmp         ?Func1@@YAHH@Z
@ILT+5(?mainCRTStartup@@YAHXZ):
  000000014000100A: E9 11 00 00 00     jmp         ?mainCRTStartup@@YAHXZ
  000000014000100F: CC                 int         3
  0000000140001010: CC                 int         3
  0000000140001011: CC                 int         3
  0000000140001012: CC                 int         3
  0000000140001013: CC                 int         3
  0000000140001014: CC                 int         3
  0000000140001015: CC                 int         3
  0000000140001016: CC                 int         3
  0000000140001017: CC                 int         3
  0000000140001018: CC                 int         3
  0000000140001019: CC                 int         3
  000000014000101A: CC                 int         3
  000000014000101B: CC                 int         3
  000000014000101C: CC                 int         3
  000000014000101D: CC                 int         3
  000000014000101E: CC                 int         3
  000000014000101F: CC                 int         3
?mainCRTStartup@@YAHXZ:
  0000000140001020: 48 83 EC 28        sub         rsp,28h
  0000000140001024: B9 03 00 00 00     mov         ecx,3
  0000000140001029: E8 D7 FF FF FF     call        @ILT+0(?Func1@@YAHH@Z)
  000000014000102E: 33 C0              xor         eax,eax
  0000000140001030: 48 83 C4 28        add         rsp,28h
  0000000140001034: C3                 ret
  0000000140001035: CC                 int         3
  0000000140001036: CC                 int         3
  0000000140001037: CC                 int         3
  0000000140001038: CC                 int         3
  0000000140001039: CC                 int         3
  000000014000103A: CC                 int         3
  000000014000103B: CC                 int         3
  000000014000103C: CC                 int         3
  000000014000103D: CC                 int         3
  000000014000103E: CC                 int         3
  000000014000103F: CC                 int         3
?Func1@@YAHH@Z:
  0000000140001040: 89 4C 24 08        mov         dword ptr [rsp+8],ecx
  0000000140001044: 8B 44 24 08        mov         eax,dword ptr [rsp+8]
  0000000140001048: 83 C0 02           add         eax,2
  000000014000104B: 89 44 24 08        mov         dword ptr [rsp+8],eax
  000000014000104F: 8B 44 24 08        mov         eax,dword ptr [rsp+8]
  0000000140001053: C3                 ret
  0000000140001054: CC                 int         3
  0000000140001055: CC                 int         3
  0000000140001056: CC                 int         3
  0000000140001057: CC                 int         3

问题:

我有两个问题,我在这里苦苦挣扎:

1。)在视频中,当教师在链接完所有内容后检查他的.exe文件时,他有一个电话'指令后跟硬编码地址,如000040001000但在我的asm文件中,我仍然有我想要调用的函数的符号名@ILT+0(?Func1@@YAHH@Z)。我认为链接器的工作是解决这个符号并输入.exe的绝对地址?我知道这个地址,当exe被加载到内存中时我不是最终地址,但仍然认为像000040001000这样的绝对地址会放在那里。

2。)在教程视频中,拨打' Func1的指令在VS调试器内运行,调试器直接跳转到存储函数代码开头的地址。但是,对于我的exe(你可以在上面看到),调用指令首先首先跳转到其他地址(在我的asm文件中用@ILT+0(?Func1@@YAHH@Z)表示)然后调用一个jmp指令,然后跳转到函数Func1的代码。为什么我在我的代码中通过'调用'来获得这种双重间接?那么' jmp'?

1 个答案:

答案 0 :(得分:2)

在执行" debug"时,Visual Studio会为大多数或所有函数创建一个跳转表。构建,创建"额外的间接层"。如果"发布"构建完成后,不会创建跳转表,并且对函数的调用会使链接器填充其地址/偏移量。

尝试执行发布版本,也许是打开调试内容的发布版本,以便您可以查看函数名称。请注意,为发布版本启用调试内容需要更改项目属性中的项目属性和源文件。