以下行是什么意思:
...
401147: ff 24 c5 80 26 40 00 jmpq *0x402680(,%rax,8)
...
内存地址前面的星号是什么意思?另外,当内存访问方法缺少它的第一个寄存器值时,这意味着什么?
通常它类似于 ("%register", %rax, 8),但在这种情况下它没有第一个寄存器。
有小费吗?
以下行是什么意思:
...
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
for 跳转到存储在 中的绝对地址%rax * 8 + 0x402680
,并且是一个四字长。
AT&T 语法需要一种方法来区分 RIP = foo ( jmp foo
) 和 RIP = load from some symbol address ( jmp *foo
)。记住那movl $1, foo
是一个存储到的绝对地址foo
。
对于其他寻址模式,您正在执行的跳转/调用类型之间没有歧义,除了裸标签之外的任何内容都必须是间接的。(GAS 将推断并警告间接跳转,*
如果你这样做jmp %rax
,或者jmp 24(%rax)
除了裸符号名称之外的任何其他内容。)
(在 64 位模式下,您通常实际使用jmp *foo(%rip)
将全局变量加载到 RIP 中,而不是使用像jmp *foo
.做事。)
实际上这是计算表 jmp,其中 0x402680 是表的地址,而 rax 是 8 字节(qword)指针的索引。
将内容融入英特尔语法总是会让事情变得更清晰:
FF24C5 80264000 JMP QWORD PTR [RAX*8+402680]
jmpq
只是无条件跳转到给定地址。'q' 表示我们正在处理四字(64 位长)。
*0x402680(,%rax,8)
: 这是一种在 x-86 汇编中写入地址的方法。你说得对,通常在第一个逗号之前有一个寄存器,但如果没有指定寄存器,你仍然遵循相同的规则。
格式是这样工作的:
D(reg1, reg2, scalingFactor)
其中 D 代表位移。位移基本上只是一个整数。reg1
是第一个或基址寄存器。reg2
是第二个寄存器,scalingFactor
是 2、4、8 之一(甚至可能是 1,但我不确定)。现在,您可以通过简单地以这种方式添加值来获得您的地址:位移 + (value at reg1
) + scalingFactor
*(value at reg2
)。
我不完全确定地址前面的星号是做什么用的,但我的猜测是这意味着位移值存储在该地址中。
希望这可以帮助。
这是跳转到内存中包含的地址。该地址存储在内存中的 address 处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:
如果没有*
,它将跳转到节symbol
中的地址和.data
段错误。
我觉得这种语法有点不一致,因为对于大多数指令:
mov symbol, %eax
mov label, %eax
已经在地址移动数据symbol
,并$symbol
用于地址。英特尔语法在这一点上更加一致,因为它总是[]
用于取消引用。
这*
当然是 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)]