链接前在汇编语言中的函数调用
Function call in the assembly language before linking
我正在查看编译器生成的汇编代码。我正在使用 C 编程语言和 GCC
编译器。
我用 C 编写了一个函数,它通过调用另一个函数将两个数字相加,并将结果存储在作为参数传递给该函数的指针所指向的变量中。
void add_two_num(int x, int y, int * dest)
{
int val;
val = dummy(x, y);
*dest = val;
}
我将源代码编译为目标代码(链接未完成),然后使用 objdump -d
反汇编代码
第 call d <add_two_num+0x9>
行中的数字 +0x9
是什么意思?
当该行将被实际函数调用替换时,这在链接阶段有用吗?
file format elf64-x86-64
0000000000000004 <add_two_num>:
4: 53 push %rbx
5: 48 89 d3 mov %rdx,%rbx
8: e8 00 00 00 00 call d <add_two_num+0x9>
d: 89 03 mov %eax,(%rbx)
f: 5b pop %rbx
10: c3 ret
注意调用行上的代码字节;立即操作数全为零。这显然是链接器的占位符。
add_two_num+9
是因为 call
上的直接操作数是调用目标相对于调用指令末尾的偏移量。因此零操作数意味着调用目标是调用后的下一条指令,恰好是 add_two_num 偏移量 9 处的 mov
。反汇编器尽力解释调用目标的含义,并且它看到调用目标(技术上)在 add_two_num.
内
您正在查看目标文件。这个文件还没有链接,外部函数的地址也没有填写。您可以在指令编码中看到这一点:00 00 00 00
是稍后要修补的实际调用目标的虚拟对象。
不幸的是,objdump 不够聪明,无法在 x86 上了解这一点,因此它会反汇编,就好像偏移量实际上是 00 00 00 00
,即调用转到下一条指令。该指令在最后一个标签之后 0x9
字节,因此您看到它将此地址解释为 add_two_num+0x9
.
您可以将 -r
选项传递给 objdump
以让它显示您的搬迁信息。这样你就知道实际调用的是什么函数。它看起来像这样:
0000000000000000 <add_two_num>:
0: 53 push %rbx
1: 48 89 d3 mov %rdx,%rbx
4: e8 00 00 00 00 call 9 <add_two_num+0x9>
5: R_X86_64_PLT32 dummy-0x4
9: 89 03 mov %eax,(%rbx)
b: 5b pop %rbx
c: c3 ret
我正在查看编译器生成的汇编代码。我正在使用 C 编程语言和 GCC
编译器。
我用 C 编写了一个函数,它通过调用另一个函数将两个数字相加,并将结果存储在作为参数传递给该函数的指针所指向的变量中。
void add_two_num(int x, int y, int * dest)
{
int val;
val = dummy(x, y);
*dest = val;
}
我将源代码编译为目标代码(链接未完成),然后使用 objdump -d
第 call d <add_two_num+0x9>
行中的数字 +0x9
是什么意思?
当该行将被实际函数调用替换时,这在链接阶段有用吗?
file format elf64-x86-64
0000000000000004 <add_two_num>:
4: 53 push %rbx
5: 48 89 d3 mov %rdx,%rbx
8: e8 00 00 00 00 call d <add_two_num+0x9>
d: 89 03 mov %eax,(%rbx)
f: 5b pop %rbx
10: c3 ret
注意调用行上的代码字节;立即操作数全为零。这显然是链接器的占位符。
add_two_num+9
是因为 call
上的直接操作数是调用目标相对于调用指令末尾的偏移量。因此零操作数意味着调用目标是调用后的下一条指令,恰好是 add_two_num 偏移量 9 处的 mov
。反汇编器尽力解释调用目标的含义,并且它看到调用目标(技术上)在 add_two_num.
您正在查看目标文件。这个文件还没有链接,外部函数的地址也没有填写。您可以在指令编码中看到这一点:00 00 00 00
是稍后要修补的实际调用目标的虚拟对象。
不幸的是,objdump 不够聪明,无法在 x86 上了解这一点,因此它会反汇编,就好像偏移量实际上是 00 00 00 00
,即调用转到下一条指令。该指令在最后一个标签之后 0x9
字节,因此您看到它将此地址解释为 add_two_num+0x9
.
您可以将 -r
选项传递给 objdump
以让它显示您的搬迁信息。这样你就知道实际调用的是什么函数。它看起来像这样:
0000000000000000 <add_two_num>:
0: 53 push %rbx
1: 48 89 d3 mov %rdx,%rbx
4: e8 00 00 00 00 call 9 <add_two_num+0x9>
5: R_X86_64_PLT32 dummy-0x4
9: 89 03 mov %eax,(%rbx)
b: 5b pop %rbx
c: c3 ret