Assembly 在x86-64 AT&;中,地址前的星号*表示什么;T组装?

Assembly 在x86-64 AT&;中,地址前的星号*表示什么;T组装?,assembly,x86-64,att,addressing-mode,Assembly,X86 64,Att,Addressing Mode,下面这行是什么意思 ... 401147: ff 24 c5 80 26 40 00 jmpq *0x402680(,%rax,8) ... 内存地址前面的星号是什么意思? 另外,当内存访问方法缺少它的第一个寄存器值时,这意味着什么 通常它类似于(“%register”,%rax,8),但在本例中它没有第一个寄存器 有什么提示吗?这是跳转到内存中包含的地址。地址存储在内存中的地址rax*8+0x402680,其中rax是当前的rax值(当此指令执行时)。将内容转换为英特尔语法总是让内

下面这行是什么意思

...
401147: ff 24 c5 80 26 40 00    jmpq   *0x402680(,%rax,8)
...
内存地址前面的星号是什么意思? 另外,当内存访问方法缺少它的第一个寄存器值时,这意味着什么

通常它类似于(“%register”,%rax,8),但在本例中它没有第一个寄存器


有什么提示吗?

这是跳转到内存中包含的地址。地址存储在内存中的地址
rax*8+0x402680
,其中
rax
是当前的
rax
值(当此指令执行时)。

将内容转换为英特尔语法总是让内容更清晰:

FF24C5 80264000  JMP QWORD PTR [RAX*8+402680]

这是AT&T汇编语法:

  • 源在目的之前
  • 助记符后缀表示操作数的大小(
    q
    表示四元组,等等)
  • 寄存器前缀为
    %
    ,立即值前缀为
    $
  • 有效地址的格式为
    DISP(基、索引、刻度)
    (DISP+BASE+INDEX*SCALE)
  • *
    指示的间接跳转/调用操作数(与直接操作相对)
因此,您有一个用于跳转到绝对地址的
jmpq
,它存储在
%rax*8+0x402680
中,是一个四字长


AT&T语法需要一种方法来区分RIP=foo(
jmp-foo
)和来自某个符号地址的RIP=load(
jmp*foo
)。请记住
movl$1,foo
是绝对地址
foo
的存储

对于其他寻址模式,您正在进行的跳转/呼叫类型之间没有歧义,除了裸标签之外的任何内容都必须是间接的。(如果您执行
jmp%rax
jmp 24(%rax)
或除裸符号名称以外的任何操作,GAS将推断并警告没有
*
的间接跳转。)


(在64位模式下,您通常会使用
jmp*foo(%rip)
将全局变量加载到rip中,而不是使用像
jmp*foo
这样的32位绝对地址。但这种可能性是存在的,在设计AT&T语法时,x86-64之前,这是正常的操作方式。)

实际上这是计算表jmp,其中0x402680是tabele的地址,rax是8字节(qword)指针的索引。

正如Necrolis所写,Intel语法使其更为明显,但实际上更为清晰。线路

jmpq   *0x402680(,%rax,8)
将在RTN中描述为:

RIP <- M[0x402680 + (8 * RAX)]

jmpq
只是到给定地址的无条件跳转。“q”表示我们正在处理四字(64位长)

*0x402680(,%rax,8)
:这是在x-86程序集中写入地址的一种方法。您的说法是正确的,通常在第一个逗号之前有一个寄存器,但是如果没有指定寄存器,您仍然遵循相同的规则

格式的工作方式如下:
D(reg1,reg2,scalingFactor)
其中D代表位移。位移基本上只是一个整数
reg1
是第一个或基址寄存器
reg2
是第二个寄存器,
scalingFactor
是2、4、8中的一个(甚至可能是1,但我不确定)。现在,您可以通过以下方式简单地添加值来获得您的地址:位移+(位于
reg1
的值)+
scalingFactor
*(位于
reg2
的值)

我不完全确定地址前面的星号是什么意思,但我猜这意味着位移值存储在该地址


希望这有帮助。

最简单的例子

为了让事情更清楚:

.data
    # Store he address of the label in the data section.
    symbol: .int label   
.text   
    # Jumps to label.
    jmp *symbol
    label:

如果没有
*
,它将跳转到
.data
部分中的
符号的地址,然后执行segfault

我觉得这种语法有点不一致,因为对于大多数指令:

mov symbol, %eax
mov label, %eax
已将数据移动到地址
symbol
,并且
$symbol
用于该地址。英特尔语法在这一点上更为一致,因为它总是使用
[]
进行解引用


*
当然是C取消引用操作符的助记符
*ptr

,但是它前面的星号会有区别吗?我明白你说的话在其他方面是有道理的。我认为首先星号将从内存位置0x402680中取出数据。所以基本上,它将变成%rax*8+mem[0x402680],星号只指定这是一个绝对跳转
jmp
会将数据从指定的内存位置中取出,不管怎样。
*
实际上意味着间接,就像C去引用操作符一样。考虑<代码> JMP Fo< <代码>(RIP= FO)vs.代码> JMP*Fo< <代码>(RIP= FO内存内容)。当然,通常使用RIP相对寻址来访问代码指针变量foo,比如
jmp*foo(%RIP)
,但是
foo
*foo
的对比很好地说明了为什么AT&T语法需要使用
*
来消除歧义。谁投了反对票,请解释一下原因?仅仅是反英特尔语法不是理由…@MichaelFoukarakis:除了用英语逐字重复数学之外,在使用英特尔语法时没有什么真正需要补充的。这并不能回答这个问题。@MichaelO这实际上是你能给出的最简洁、最直接的答案。如果你看一下这里评级最高的回复,它实际上是一个从左到右读取的英特尔助记符的要点列表……当C代码完成If-else或switch语句时,在汇编代码中经常使用跳转表。它允许以恒定的时间传递控件,而不必检查许多单独的相等性检查。re:“不一致性”:在标签处跳转“访问”代码
jmp foo
使CPU将
foo
处的字节作为代码加载(通过设置RIP)。与mov foo相比,%eax
将foo处的字节加载到寄存器中。我不确定使用
jmp$foo
进行直接相关跳转的语法设计是否是好的,因为
mov symbol, %eax
mov label, %eax