链接之前,用汇编语言调用功能

发布于 2025-02-04 07:49:20 字数 861 浏览 3 评论 0 原文

我正在浏览编译器生成的装配代码。我正在使用C编程语言和 GCC 编译器。

我在C中编写了一个函数,该函数通过调用另一个函数来增加两个数字,并将结果存储在指向指向该函数的参数指向的变量中。

void add_two_num(int x, int y, int * dest)
{
  int val;

  val = dummy(x, y);
  *dest = val;
}

我将源代码编译为对象代码(未完成链接),然后使用 objdump -d 在行中使用 objdump -d

在行+0x9 是什么含义。 >调用d< add_two_num+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  

I was going through the assembly code generated by the compiler. I am using the C programming language and GCC compiler.

I wrote a function in C which adds two numbers by calling another function and stores the result in the variable pointed to by the pointer passed as an argument to the function.

void add_two_num(int x, int y, int * dest)
{
  int val;

  val = dummy(x, y);
  *dest = val;
}

I compiled the source code to object code (linking not done) and then disassembled the code using objdump -d

What is the meaning of the number +0x9 in the line call d <add_two_num+0x9>?
Is that useful at the stage of linking when that line will be replaced by the actual function call?

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  

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我最亲爱的 2025-02-11 07:49:20

您正在查看对象文件。该文件尚未链接,外部功能的地址尚未填写。您可以在指令编码中看到这一点: 00 00 00 00 是稍后对实际调用目标进行修补的假人。

不幸的是,Objdump还不够聪明,无法在X86上知道这一点,因此它将偏移量实际上是 00 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    

You are looking at an object file. This file has not been linked yet and the addresses of external functions have not been filled in yet. You can see this in the instruction encoding: the 00 00 00 00 is a dummy for the actual call target to be patched in later.

Unfortunately objdump is not smart enough to know about this on x86, so it disassembles as if the offset was actually 00 00 00 00, i.e. the call goes to the next instruction. This instruction is 0x9 bytes after the last label, so you see it interprets this address as add_two_num+0x9.

You can pass the -r option to objdump to have it show you relocation information. This way you know what function is actually being called. It'll look something like this:

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    
如若梦似彩虹 2025-02-11 07:49:20

注意呼叫线上的代码字节;直接操作数是所有零。这显然是接头的占位符。

add_two_num+9 来自以下事实: call>呼叫是呼叫目的地的偏移,相对于呼叫指令的结束。因此,零操作数意味着呼叫目标是呼叫后的下一个指令,恰好是从add_two_num offset 9处的 mov 。拆卸器试图尽最大努力解释呼叫目标的含义,并认为呼叫目标在ADD_TWO_NUM中是(技术上)。

Note the code bytes on the call line; the immediate operand is all zeros. This is clearly a placeholder for the linker.

The add_two_num+9 comes from the fact that the immediate operand on call is an offset of the call destination, relative to the end of the call instruction. So a zero operand means the call target is the next instruction after call, which happens to be the mov at offset 9 from add_two_num. The disassembler tries to do its best to interpret the meaning of the call target, and it sees that the call target is (technically) within add_two_num.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文