[英]What does an asterisk * before an address mean in x86-64 AT&T assembly?
下面这行是什么意思:
...
401147: ff 24 c5 80 26 40 00 jmpq *0x402680(,%rax,8)
...
内存地址前面的星号是什么意思? 另外,当内存访问方法缺少它的第一个寄存器值时,这意味着什么?
通常它类似于 ("%register", %rax, 8),但在这种情况下它没有第一个寄存器。
有小费吗?
这是 AT&T 汇编语法:
q
表示四边形等)%
为前缀,立即数以$
为前缀DISP(BASE, INDEX, SCALE)
(DISP + BASE + INDEX * SCALE)*
表示的间接跳转/调用操作数(与直接相反)。 因此,您有一个jmpq
用于跳转到存储在%rax * 8 + 0x402680
的绝对地址,并且是一个四字长。
AT&T 语法需要一种方法来区分 RIP = foo ( jmp foo
) 和 RIP = 从某个符号地址 ( jmp *foo
) 加载。 请记住, movl $1, foo
是绝对地址foo
的存储。
对于其他寻址模式,您正在执行的跳转/调用类型之间没有歧义,除了裸标签之外的任何内容都必须是间接的。 (如果您执行jmp %rax
或jmp 24(%rax)
或任何非裸符号名称,GAS 将推断出并警告没有*
的间接跳转。)
(在 64 位模式下,您通常实际上会使用jmp *foo(%rip)
将全局变量加载到 RIP 中,而不是使用像jmp *foo
这样的 32 位绝对地址。但这种可能性存在,并且在 x86-64 之前在设计 AT&T 语法时,这是正常的做事方式。)
实际上这是计算表 jmp ,其中 0x402680 是表的地址, rax 是 8 字节(qword)指针的索引。
将事物纳入 Intel 语法总是会使内容更清晰:
FF24C5 80264000 JMP QWORD PTR [RAX*8+402680]
jmpq
只是无条件跳转到给定地址。 “q”表示我们正在处理四字(64 位长)。
*0x402680(,%rax,8)
:这是一种在 x-86 汇编中写入地址的方法。 您说的第一个逗号之前通常有一个寄存器是正确的,但是如果没有指定寄存器,您仍然遵循相同的规则。
格式是这样工作的: D(reg1, reg2, scalingFactor)
其中 D 代表位移。 位移基本上只是一个整数。 reg1
是第一个或基址寄存器。 reg2
是第二个寄存器,而scalingFactor
是scalingFactor
之一(甚至可能是 1,但我不确定)。 位移+(在值:现在,你可以通过简单地以这种方式加入值获取你的地址reg1
)+ scalingFactor
*(在价值reg2
)。
我不完全确定地址前面的星号是做什么用的,但我的猜测是这意味着位移值存储在该地址处。
希望这可以帮助。
它是跳转到包含在内存中的地址。 该地址存储在内存中的地址rax*8+0x402680
,其中rax
是当前的rax
值(当该指令执行时)。
最小的例子
为了使事情更清楚:
.data
# Store he address of the label in the data section.
symbol: .int label
.text
# Jumps to label.
jmp *symbol
label:
如果没有*
,它将跳转到.data
部分和段错误中的symbol
地址。
我觉得这个语法有点不一致,因为对于大多数指令:
mov symbol, %eax
mov label, %eax
已经在地址symbol
处移动数据,并且$symbol
用于地址。 Intel 语法在这一点上更加一致,因为它总是使用[]
来取消引用。
*
当然是 C 取消引用运算符*ptr
的助记符。
正如 Necrolis 所写,Intel 语法使它更明显一些,但RTN确实更清晰。 线
jmpq *0x402680(,%rax,8)
将在 RTN 中描述为:
RIP <- M[0x402680 + (8 * RAX)]
其中M
是系统内存。
因此,我们可以编写通用形式jmpq *c(r1, r2, k)
,其中c
是立即数, r1
和r2
是通用寄存器, k
是 1(默认)、2、4 或 8:
RIP <- M[c + r1 + (k * r2)]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.