assembly 为什么括号在AT&T语法中根据上下文做不同的事情?

bvn4nwqk  于 2023-11-19  发布在  其他
关注(0)|答案(2)|浏览(113)

我正在上一门关于汇编的课,我和几个朋友正在讨论%rdi(%rdi)在以下情况下的区别:
假设RDI以ASCII格式保存字符值'w'。据我所知,如果执行%rdi,我们将处理值'w'本身,而如果执行(%rdi),我们将处理'w'指向的值(或者更具体地,在编号为'w'的ASCII码的地址处的值,即绝对地址0x0000000000000077)。
类似地,如果RDI保存值0x1007bf,我相信%rdi给出的是数值0x1007bf本身,而(%rdi)给出的是地址0x1007bf处的值......
正确的解释是如何呢?
注意:所有这些都在mov和cmp函数的上下文中。

cgvd09ve

cgvd09ve1#

AT&T语法区分四种寻址模式:
1.*register operations * 其中操作数是一个寄存器。语法是给予寄存器名称。这样的操作数的一个例子是%rax
1.immediate operators * 其中操作数是立即值。语法是$后跟表达式。例如$42,但也有$foo$'w'$(42)$$foo(值是符号$foo的值)和$$foo+$$bar(值是符号$foo加上$$bar的值)。
1.
内存操作数 *,其中操作数引用内存中的位置。语法为

  • 内存操作数 * = [ * 寄存器 * :] [ * 表达式 * ] ( * 索引 * )

  | [ register: ] expression

  • index* = register

  | register,register
  | [ register ] [ , [ register ]] ,expression
即,存储器操作数可选地以诸如%ds:的段选择器开始,然后是可选的 * 位移 *,以及可选的 * 索引 。位移和索引不能同时省略。索引是寄存器,一对寄存器,或者scale-index-base类型索引,其中base和index(可能包括第二个逗号)可以省略。如果既不给出基址也不给出下标,则寻址方式为绝对寻址(跳转除外,见下文)。要获得RIP相对寻址,请使用(%rip)作为索引。
内存操作数的例子有foo(%rax)(foo)(其中foo是表达式的位移)、($foo)(取符号$foo的值作为位移)、%fs:(%rax, %rsi, 1)231234(%rsp)
1.
间接操作数 * 其中操作数间接引用内存中的位置。语法为*后跟内存操作数。这用于区分直接跳转(其采用具有绝对寻址的存储器操作数,但就像使用相对寻址一样使用)从间接跳转by analogy to PDP-11 assembly。例子是*foo跳转到存储在变量foo中的地址,而不是跳转到foo
请注意,由于历史原因,远直接跳转被编码为采用立即操作数。
我希望这能澄清问题。特别注意括号是如何用于表达式内的分组和表示索引的。没有语法上的歧义,因为索引必须包含寄存器或包含逗号,这两者都不能出现在表达式中。

jtjikinw

jtjikinw2#

你基本上是正确的,%rdi是寄存器直接addressing mode,而(%rdi)是寄存器间接,但让我们注意两件事:
1.源与目标:%rdi(%rdi)这两种形式都可以出现在源或目标位置(或源/目标),因此这意味着读与写(与先读后写)。(所以你所说的对于阅读是准确的。)

  1. %rdi单独指定64位操作数/操作,因为它是64位寄存器。而(%rdi)指定有效地址,但不指定操作数大小(它指定使用64位寄存器进行解引用,例如,与(%edi)相反,它说使用32位寄存器进行解引用)但是位于该存储器地址处的项的大小仅由此未指定,并且我们需要知道更大的上下文(操作码或其他操作数)以理解存储器访问的大小,无论是字节、字、双字还是双字。

相关问题