x86-64 - 在这个简单的例子中调用汇编指令做什么?
问题描述
一个简单的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
需要像0x01
eax一样返回吗?
解决方案
您实际上是在对其应用修复之前查看代码(通常在链接阶段完成)。如果您添加-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)的更深入概述,请参阅这个答案,由许多个月前一些非常聪明和漂亮的人发布:-)
推荐阅读
- geotiff - 无法使用光栅获得单波段 tiff 图像的彩色图
- ssas - 具有行安全过滤器和对象级安全过滤器的两个角色的用户
- java - ArrayList null 不为空
- go - Go - 基于字符串返回包错误的最佳方法?
- azure-pipelines - Microsoft.TeamFoundation.Build.WebApi 在将工件与构建进行排队之前将其与构建相关联
- javascript - JS:如何在不不断发出请求的情况下更新来自端点的数量?
- python - 缺少 2 个口味和勺子所需的位置参数?
- .net - 拥有大量大型对象且您永远不想水合的实体 - 推荐的模式是什么?
- regex - 正则表达式搜索字符串的实例然后删除某些字符
- function - 函数有没有办法根据输入返回整数或字符串?