intel风格寻址方式格式速查
文章目录
0. 段寄存器的使用规定***
访问存储器的方式 | 默认的段寄存器 | 可超越的段寄存器 | 偏移地址 |
---|---|---|---|
取指令, 跳转? | cs | 不可超越 | ip |
堆栈操作 | ss | 不可超越 | sp |
一般数据访问 | ds | cs , ss , es | ea |
串操作的源操作数 | ds | cs , ss ,es | si |
串操作的目的操作数 | es | 不可超越 | di |
bp 作为基址的寻址方式 | ss | cs , ds , es | ea |
总结:
- 取指令只能
cs
push
,pop
只能ss
- 串操作目的串只能
es
- 只要有
bp
出现默认段寄存器为ss
- 只要有
bx
,si
,di
出现默认段寄存器为ds
段超越就是指不使用默认的段寄存器, 如
ss:[si]
就是超越到ss
段, 使用默认的段寄存器可以不用写出比如[si]
1. 直接寻址方式
[imm16]
mov ax, [2000h] ; ax << ds:[2000h]
2. 寄存器间接寻址方式
注:
这里的reg16
只能取bx
,bp
,si
,di
, 其中若取bp
则隐含段寄存器为ss
, 其余隐含为ds
[reg16]
mov ax, [si] ; ax << ds:[si]
3. 寄存器相对寻址方式
[reg16 + imm16] 或 imm16[reg16]
注:
这里的reg16
只能取bx
,bp
,si
,di
, 其中若取bp
则隐含段寄存器为ss
, 其余隐含为ds
mov ax, [di + 06h] ; ax << ds:[di + 06h]
4. 基址变址寻址方式
[base + reg16] 或 [bx][reg16]
注:
这里的base
只能从bx
,bp
中取(取bx
则隐含段寄存器为ds
, 取bp
则隐含段寄存器为ss
)
这里的reg16
只能从si
,di
中取
mov ax, [bx + si] ; ax << ds:[bx + si]
5. 相对基址变址寻址方式
[base + reg16 + imm16] 或 imm16[base][reg16]
注:
这里的base
只能从bx
,bp
中取(取bx
则隐含段寄存器为ds
, 取bp
则隐含段寄存器为ss
)
这里的reg16
只能从si
,di
中取
mov ax, [bx + si + 06h] ; ax << ds:[bx + si + 06h]
附录: AT&T风格,Intel风格汇编差异对比
Win家一般使用Intel风格, 开源界和类Unix系统一般使用AT&T风格
1. 寄存器命名 %
在
AT&T
风格中,寄存器会加上%
作为前缀.而Intel
汇编中寄存器名是不需要加前缀的.可以直接使用.
AT&T风格 | Intel风格 | 说明 |
---|---|---|
push %eax | push eax | 这是一条入栈指令,把寄存器eax中的值压入栈中 |
2. 立即数格式 $
- 在
AT&T
汇编中 , 用$
前缀表示一个立即数. - 在
Intel
汇编中 , 立即数没有任何前缀. 直接用一个数字表示. (当然有不同的进制. 比如 0x01 , 10 等)
AT&T风格 | Intel风格 | 说明 |
---|---|---|
push $1 | push 1 | 把一个立即数压入栈中 |
3. 操作数顺序
AT&T和Intel格式中的源操作数和目标操作数的位置正好相反
下面是给寄存器EAX
赋一个初值1.
AT&T
风格:操作符 源操作数 , 目的操作数
mov $1 , %eaxIntel
风格:操作符 目的操作数 , 源操作数
mov eax , 1
AT&T风格 | Intel风格 | 说明 |
---|---|---|
push $1 | push 1 | 把一个立即数压入栈中 |
4. 内存操作数的寻址方式
AT&T
寻址格式:section:disp(base, index, scale)
Intel 寻址格式
:section:[base + index*scale + disp]
无论形式如何,都是实现如下的地址计算:(其中base和index必须是寄存器,disp和scale可以是常数)
disp + base + index * scale
中文释义: 地址或偏移 (%基址或偏移量寄存器, %索引寄存器, 比例因子)
计算方法: 最终地址 = 地址或偏移 + %基址或偏移量寄存器 + %索引寄存器 * 比例因子
寻址参考: AT&T汇编语言及其寻址方式
AT&T格式 | Intel格式 |
---|---|
movl -4(%ebp), %eax | mov eax, [ebp - 4] |
movl array(, %eax, 4), %eax | mov eax, [eax*4 + array] |
movw array(%ebx, %eax, 4), %cx | mov cx, [ebx + 4*eax + array] |
movb $4, %fs:(%eax) | mov fs:eax, 4 |
注: 关于寻址中的段寻址知识参考:
目前在Linux环境上,不管是32位还是64位操作系统段寻址都被废弃. 直接使用的线性地址. 不过fs
和gs
在特殊情况下还有使用.
5. 数据宽度表示
- 在AT&T汇编格式中,操作数的字长由操作符的最后一个字母决定,
后缀b
、w
、l
分别表示操作数为字节(byte,8比特)、字(word,16比特)和长字(long,32比特); - 而在Intel汇编格式中,操作数的字长是用
byte ptr
和word ptr
等前缀来表示的
AT&T格式 | Intel格式 |
---|---|
movb val, %al | mov al, byte ptr val |