Intel和AT&T语法中内存寻址的一般形式如下:
[base + index*scale + disp] # Intel, including GAS .intel_syntax noprefix
disp(base, index, scale) # AT&T我的问题如下:
base和index可以注册吗?scale可以接受哪些值,是1、2、4和8(1是默认值)?index和disp是否可以互换(唯一的区别是index是寄存器,而disp是即时值)?发布于 2015-01-14 06:51:27
英特尔的手册中描述了这一点:
3.7.5指定偏移量 内存地址的偏移部分可以直接指定为静态值(称为位移),也可以通过由以下一个或多个组件组成的地址计算来指定:
由于添加这些组件而产生的偏移量称为有效地址。
缩放因子被编码为2位移位计数(0, 1,2,3),对于1,2,4或8的比例尺因子。
在AT&T语法中,它的disp(base, index, scale)常量在父类之外。一些英特尔语法汇编程序也允许像1234[ebx]这样的语法,而另一些则不允许。但是AT&T语法是僵化的,寻址模式的每一个组件都只能在适当的位置。例如:
movzwl foo-0x10(,%edx,2), %eax从地址foo-0x10 + edx*2将零扩展16位("word")加载到EAX中。EDX是索引寄存器,具有缩放因子2,没有基寄存器.foo和-0x10都是位移的一部分,都是链接时间常数.foo是一个符号地址,链接器将填写该地址并从中减去0x10 (因为-0x10组装时间偏移)。
如果您有选择,只使用一个基,而不是一个标度为1的索引。索引需要一个SIB字节来编码,从而使指令更长。这就是为什么编译器选择像8(%ebp)这样的寻址模式来访问堆栈内存,而不是8(,%ebp)。
有关何时可以使用基、和/或索引和/或置换的更多信息,请参见Referencing the contents of a memory location. (x86 addressing modes)。
16位位移量只有在16位寻址模式下才能编码,这种模式使用的different format不能包含缩放因子,并且具有非常limited selection of which registers可以作为基或索引。
因此,像1234(%edx)这样的模式必须在32位机器代码中将1234编码为32位disp32。
字节偏移从-128 ..。+127可以使用短格式8位编码.您的汇编程序将为您处理这一点,使用最短的有效编码的位移。
对于64位寻址模式,所有这些在64位模式下都是相同的,disp32也被符号扩展到64位,就像disp8一样。
64位模式确实添加了一种新的不同的寻址模式,即symbol(%rip),它不适用于任何通用寄存器,只与RIP相距32位。请参阅https://stackoverflow.com/questions/54745872/how-do-rip-relative-variable-references-like-rip-a-in-x86-64-gas-intel-sy,它也涉及AT&T语法。
https://stackoverflow.com/questions/27936196
复制相似问题