大多数指令有一个或者多个操作数,指示出执行一个操作中要使用的源数据值,以及放置结果的目的位置。x86-64支持多种操作数格式。
源数据值可以以常数形式给出,或者是从寄存器或内存中读出。
结果可以存放在寄存器或内存中。
立即数寻址
在AT&T汇编中,立即数用来表示常数值。立即数的书写方式是$后面跟随一个用标准C表示法表示的整数。
不同的指令允许的立即数值范围不同,汇编器会自动选择最紧凑的方式进行数值编码。
寄存器寻址
寄存器寻址主要是根据寄存器的名称读取寄存器的内容。
16个寄存器的低位1字节、2字节、4字节、8字节中的一个作为操作数,这些字节数分别对应于8位、16位、32位、24位。
我们用符号
r
a
r_a
ra来表示任意寄存器a,用
R
[
r
a
]
R[r_a]
R[ra]来表示它的值,这是将寄存器集合看成一个数组R,用寄存器标识符作为索引。
内存寻址
内存寻址会根据计算出来的有效地址,访问某个内存位置。
因为将内存看成一个很大的字节数组,我们用
M
b
[
A
d
d
r
]
M_b[Addr]
Mb[Addr]表示对存储在内存中从地址
A
d
d
r
Addr
Addr开始的b个字节值的引用。为了简便,我们通常省去下标b。
针对不同的寻址模式,总结如下表:
类型 | 格式 | 操作数值 | 名称 |
---|---|---|---|
立即数 | $ I m m Imm Imm | I m m Imm Imm | 立即数寻址 |
寄存器 | r a r_a ra | R [ r a ] R[r_a] R[ra] | 寄存器寻址 |
存储器 | I m m Imm Imm | M [ I m m ] M[Imm] M[Imm] | 绝对寻址 |
存储器 | ( r a ) (r_a) (ra) | M [ R [ r a ] ] M[R[r_a]] M[R[ra]] | 间接寻址 |
存储器 | I m m ( r b ) Imm(r_b) Imm(rb) | M [ I m m + R [ r b ] ] M[Imm+R[r_b]] M[Imm+R[rb]] | (基址+偏移量)寻址 |
存储器 | ( r b , r i ) (r_b, r_i) (rb,ri) | M [ R [ r b ] + R [ r i ] ] M[R[r_b] + R[r_i]] M[R[rb]+R[ri]] | 变址寻址 |
存储器 | I m m ( r b , r i ) Imm(r_b, r_i) Imm(rb,ri) | M [ I m m + R [ r b ] + R [ r i ] ] M[Imm + R[r_b] + R[r_i]] M[Imm+R[rb]+R[ri]] | 变址寻址 |
存储器 | ( , r i , s ) (, r_i, s) (,ri,s) | M [ R [ r i ] ∗ s ] M[R[r_i] * s] M[R[ri]∗s] | 比例变址寻址 |
存储器 | I m m ( , r i , s ) Imm(, r_i, s) Imm(,ri,s) | M [ I m m + R [ r i ] ∗ s ] M[Imm + R[r_i] * s] M[Imm+R[ri]∗s] | 比例变址寻址 |
存储器 | ( r b , r s , i ) (r_b, r_s, i) (rb,rs,i) | M [ R [ r b ] + R [ r i ] ∗ s ] M[R[r_b] + R[r_i] * s] M[R[rb]+R[ri]∗s] | 比例变址寻址 |
存储器 | I m m ( r b , r i , s ) Imm(r_b, r_i, s) Imm(rb,ri,s) | M [ I m m + R [ r b ] + R [ r i ] ∗ s ] M[Imm + R[r_b] + R[r_i] * s] M[Imm+R[rb]+R[ri]∗s] | 比例变址寻址 |
对于寻址语法
I
m
m
(
r
b
,
r
i
,
s
)
Imm(r_b, r_i, s)
Imm(rb,ri,s),表示的是最常用的形式。
这样的引用由4部分组成,一个立即数偏移
I
m
m
Imm
Imm,一个基址寄存器
r
b
r_b
rb,
一个变址寄存器
r
i
r_i
ri和一个比例因子
s
s
s,这里s必须是1、2、4或者8.
基址和变址寄存器都必须是64位寄存器。
有效地址被计算为
I
m
m
+
R
[
r
b
]
+
R
[
r
i
]
∗
i
Imm + R[r_b] + R[r_i] * i
Imm+R[rb]+R[ri]∗i。
引用数组元素时,会用到这种通用形式。
其他形式都是这种通用形式的特殊情况,只是省略了某些部分。