You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86-64 AT&T语法汇编中*符号与RIP的用法相关疑问

AT&T语法x86-64汇编*符号与RIP使用问题解答

关于*符号的核心定义

首先明确:并非永远指代对应地址中存储的数据,它是AT&T汇编中专用于控制转移类指令的标识符,仅用来区分直接寻址和间接寻址,普通内存读写指令(如mov、add等)不需要加,本身就会读取地址对应的数据。

问题1:jmp*、call*指令的含义与常见用法

不带的jmp/call属于直接控制转移,汇编器会直接将操作数编码为相对当前指令的偏移量,执行时直接跳转到目标位置;带的jmp*/call*属于间接控制转移,操作数本身存储的是跳转目标的地址,执行时需要先读取操作数对应位置的内容作为目标地址再跳转。
常见用法示例:

  • 寄存器间接寻址:call *%rax
    直接将rax寄存器中存储的值作为调用目标地址,对应C语言中普通函数指针调用的常见编译结果,比如void (*func)() = test; func();就会生成类似指令。
  • 内存间接寻址:jmp *(%rbx)
    先读取rbx寄存器指向的内存地址中的8字节值(x86-64下地址长度为8字节),再将该值作为跳转目标地址,常用于函数指针数组的访问,比如call *func_arr(, %rdi, 8)就是取func_arr数组第rdi个元素存储的函数地址进行调用。
  • 绝对内存间接寻址:jmp *0x402000
    直接读取固定内存地址0x402000处存储的8字节值作为跳转目标,仅在内核、裸机开发等地址固定的场景使用。

问题2:RIP相关寻址规则与操作方法

关于call label(%rip)的寻址逻辑

你感知到的「调用label对应的地址」是最终效果,但底层计算逻辑确实是RIP + 偏移量。
AT&T汇编中offset(%基址寄存器)的通用规则是计算「基址寄存器值 + offset」作为有效地址,label(%rip)里的label并不是符号的绝对地址,而是汇编器/链接器自动计算的「label地址与当前指令下一条指令地址的差值」(执行当前call指令时,RIP本身就指向当前指令的下一条指令地址),二者相加的结果刚好是label的绝对地址,所以最终效果是跳转到label处。

RIP的使用规则

x86-64架构中RIP的使用只有两类固定场景,没有例外:

  1. RIP相对内存寻址:就是上述offset(%rip)的形式,所有用RIP作为基址的内存访问都遵循「RIP值 + offset」的计算规则
  2. 显式读取RIP值:x86-64没有直接读写RIP的指令,通用读取方式是lea 0(%rip), %rax,lea指令仅计算有效地址不访问内存,所以执行后rax中存储的就是当前RIP的值。

实现rip+5操作的方法

分两种需求场景:

  • 仅需要获取rip+5的值存到寄存器:直接写lea 5(%rip), %rax即可,执行后rax中存储的就是当前RIP+5的结果
  • 需要跳转到rip+5的位置:两种写法都可以实现
    # 写法1:直接相对跳转,汇编器自动计算偏移
    jmp .+5
    # 写法2:先计算地址再间接跳转
    lea 5(%rip), %rax
    jmp *%rax
    

内容的提问来源于stack exchange,提问作者Dan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 07:45:01