首页 > 解决方案 > 在这个简单的例子中调用汇编指令做什么?

问题描述

一个简单的c函数。

void sum ()
{
    return ;
}

命令

gcc -c -m32 -o simple simpleProg.c -O0 && objdump -d simple -M intel

simple:     file format elf32-i386


Disassembly of section .text:

00000000 <sum>:
   0:   f3 0f 1e fb             endbr32 
   4:   55                      push   ebp
   5:   89 e5                   mov    ebp,esp
   7:   e8 fc ff ff ff          call   8 <sum+0x8> --->This
   c:   05 01 00 00 00          add    eax,0x1
  11:   90                      nop
  12:   5d                      pop    ebp
  13:   c3                      ret    

这个call 8声明在这里做什么?还void需要像0x01eax一样返回吗?

标签: x86-64disassembly

解决方案


您实际上是在对其应用修复之前查看代码(通常在链接阶段完成)。如果您添加-r以查看重定位条目,您会看到这个(我没有得到,endbr32但这可能是因为我使用的是旧编译器):

00000000 <sum>:
   0:   55                      push   ebp
   1:   89 e5                   mov    ebp,esp
   3:   e8 fc ff ff ff          call   4 <sum+0x4>
                        4: R_386_PC32   __x86.get_pc_thunk.ax
   8:   05 01 00 00 00          add    eax,0x1
                        9: R_386_GOTPC  _GLOBAL_OFFSET_TABLE_
   d:   90                      nop
   e:   5d                      pop    ebp
   f:   c3                      ret

Disassembly of section .text.__x86.get_pc_thunk.ax:

00000000 <__x86.get_pc_thunk.ax>:
   0:   8b 04 24                mov    eax,DWORD PTR [esp]
   3:   c3                      ret

在修复时,第 3 行实际上将被修改为调用__x86.get_pc_thunk.ax(使用相对地址,因为e8是相对调用)。这个函数有效地加载eax了返回地址(从第 8 行开始的字节)。

第 8 行也是固定的,因此它不是添加一个,而是添加“相对于 PC”地址的全局偏移表 (GOT)。所以,毕竟,它eax包含全局偏移表的绝对地址,所以你可以从那里调用你想要的任何函数。


所以,最重要的是,它实际上并没有调用它看起来正在调用的地址。那将开始在指令中运行代码,除非您知道自己在做什么,否则这通常是一件坏事:-)

它也没有专门加载eax返回码。它正在做的是准备能够从函数中访问 GOT,尽管它实际上并不会使用它。

相反,它会丢弃所有信息并退出,保留eax一些任意值,因为void函数并不关心。如果您实际调用诸如 之类的函数puts("Hello"),您会看到它使用此值来定位puts函数的正确地址。

几乎可以肯定的是,如果您提高优化级别,很多(不必要的)代码将会消失。

有关 GOT(和过程链接表,或 PLT)的更深入概述,请参阅这个答案,由许多个月前一些非常聪明和漂亮的人发布:-)


推荐阅读