<__x86.get_pc_thunk.ax>有什么作用?

本文详细解析了C语言反汇编过程中遇到的__x86.get_pc_thunk.ax指令。这个指令实际上是获取下一条指令地址的机制,通过调用子程序并利用调用者保存下一条指令地址的特点,将esp栈顶的值赋给eax寄存器。这一操作在动态链接和代码优化中具有重要意义,为程序的运行提供必要的信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、<__x86.get_pc_thunk.ax>

在把C语言反汇编时,经常会看到这样的代码<__x86.get_pc_thunk.ax>

比如下面一段C语言代码:

// main.c
int main(void)
{
	return 0;
}

然后,生成32位的可执行文件(32位的可执行文件比较简单,容易分析):

gcc main.c -o main -m32

然后反汇编,我这里使用gdb反汇编(也可以使用objdump等其他工具):

image-20210609150525084

可以看到main函数的反汇编结果。其他指令都可以理解,这里有一个call 0x11c5 <__x86.get_pc_thunk.ax>是什么意思?

二、<__x86.get_pc_thunk.ax>的内容

乍一看<__x86.get_pc_thunk.ax>后面是ax,可能跟ax寄存器有关,确实,这种类型的还有比如<__x86.get_pc_thunk.bx><__x86.get_pc_thunk.cx>等格式都差不多的符号。确实跟结尾的寄存器有关。

查了网上资料,这样的一条指令,就类似下面的操作:

__get_pc_thunk.ax:
movel (%esp),%eax
return

就是把esp的内容赋值给eax。

内容上,很容易理解,可是为什么要这样干呢?

三、<__x86.get_pc_thunk.ax>的意义

这里要注意的是,get_pc_thunk.xx是一个子程序,是被调用的,程序调用时,会把调用者的下一条指令的地址压栈保存(用于返回),所以进入get_pc_thunk.xx时,栈顶esp就是调用者的下一条指令地址。

比如,还是下面的例子:

image-20210609150525084

这里是Intel汇编

  • call 0x11c5 <__x86.get_pc_thunk.ax>执行时,会把该指令的下一条指令的地址压栈保存
  • 也就是把指令add eax, 0x2e23的地址0x000011b9压入栈中

所以当进入子程序0x11c5 <__x86.get_pc_thunk.ax>时,主要是执行:

movel (%esp),%eax

这里是AT&T风格汇编,注意区分

  • 就把指令add eax, 0x2e23的地址0x000011b9赋值给了eax。

当调用者call 0x11c5 <__x86.get_pc_thunk.ax>执行完毕返回时,将要执行的是:

add eax,0x2e23

这里eax原始值就是该条指令本身的地址(在<__x86.get_pc_thunk.ax>中给eax赋值的)!然后加上0x2e23,就是在本条指令偏移0x2e23地址。

所以call 0x11c5 <__x86.get_pc_thunk.ax>的意义就是为了获取下一条指令的地址。

利用了调用子程序会将下一条指令地址压栈的特性,提前获取下一条指令的地址。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值