我正在上一门关于汇编的课,我和几个朋友正在讨论%rdi
和(%rdi)
在以下情况下的区别:
假设RDI以ASCII格式保存字符值'w'
。据我所知,如果执行%rdi,我们将处理值'w'
本身,而如果执行(%rdi)
,我们将处理'w'
指向的值(或者更具体地,在编号为'w'
的ASCII码的地址处的值,即绝对地址0x0000000000000077
)。
类似地,如果RDI保存值0x1007bf
,我相信%rdi
给出的是数值0x1007bf
本身,而(%rdi)
给出的是地址0x1007bf
处的值......
正确的解释是如何呢?
注意:所有这些都在mov和cmp函数的上下文中。
2条答案
按热度按时间cgvd09ve1#
AT&T语法区分四种寻址模式:
1.*register operations * 其中操作数是一个寄存器。语法是给予寄存器名称。这样的操作数的一个例子是
%rax
。1.immediate operators * 其中操作数是立即值。语法是
$
后跟表达式。例如$42
,但也有$foo
,$'w'
,$(42)
,$$foo
(值是符号$foo
的值)和$$foo+$$bar
(值是符号$foo
加上$$bar
的值)。1. 内存操作数 *,其中操作数引用内存中的位置。语法为
:
] [ * 表达式 * ](
* 索引 *)
| [ register
:
] expression| register
,
register| [ register ] [
,
[ register ]],
expression即,存储器操作数可选地以诸如
%ds:
的段选择器开始,然后是可选的 * 位移 *,以及可选的 * 索引 。位移和索引不能同时省略。索引是寄存器,一对寄存器,或者scale-index-base类型索引,其中base和index(可能包括第二个逗号)可以省略。如果既不给出基址也不给出下标,则寻址方式为绝对寻址(跳转除外,见下文)。要获得RIP相对寻址,请使用(%rip)
作为索引。内存操作数的例子有
foo
、(%rax)
、(foo)
(其中foo
是表达式的位移)、($foo)
(取符号$foo
的值作为位移)、%fs:(%rax, %rsi, 1)
、23
和1234(%rsp)
。1. 间接操作数 * 其中操作数间接引用内存中的位置。语法为
*
后跟内存操作数。这用于区分直接跳转(其采用具有绝对寻址的存储器操作数,但就像使用相对寻址一样使用)从间接跳转by analogy to PDP-11 assembly。例子是*foo
跳转到存储在变量foo
中的地址,而不是跳转到foo
。请注意,由于历史原因,远直接跳转被编码为采用立即操作数。
我希望这能澄清问题。特别注意括号是如何用于表达式内的分组和表示索引的。没有语法上的歧义,因为索引必须包含寄存器或包含逗号,这两者都不能出现在表达式中。
jtjikinw2#
你基本上是正确的,
%rdi
是寄存器直接addressing mode,而(%rdi)
是寄存器间接,但让我们注意两件事:1.源与目标:
%rdi
和(%rdi)
这两种形式都可以出现在源或目标位置(或源/目标),因此这意味着读与写(与先读后写)。(所以你所说的对于阅读是准确的。)%rdi
单独指定64位操作数/操作,因为它是64位寄存器。而(%rdi)
指定有效地址,但不指定操作数大小(它指定使用64位寄存器进行解引用,例如,与(%edi)
相反,它说使用32位寄存器进行解引用)但是位于该存储器地址处的项的大小仅由此未指定,并且我们需要知道更大的上下文(操作码或其他操作数)以理解存储器访问的大小,无论是字节、字、双字还是双字。