汇编学习笔记(2)-80x86寻址方式
寻址方式
所谓寻址方式就是表示指令中数据所在地址的方式。一共有七种寻址方案
立即数寻址
寄存器寻址
直接寻址
寄存器直接寻址
寄存器相对选址
基址变质寻址
相对基址变质寻址
在此之前,先介绍一个数据复制指令 MOV 指令, 格式是 MOV AX, BX 。 AX, BX是寄存器上一章介绍过的MOV就是指令。 指令的含义就是将BX的值复制给AX。C语言的表述就是AX=BX;
举个例子 如果一开始 AX=5; BX=0;
MOV AX,BX 之后 AX = BX 都是0;
立即数寻址 / 寄存器寻址
MOV AX, 1 ; AX = 1
立即数寻址,我觉得称不上寻址,因为他给出的不是地址,而就是实际的数字,上面的命令中 1 就是立即数,而AX就是寄存器寻址所以寄存器寻址就是直接使用寄存器,数据直接存入指定的寄存器
寄存器寻址可以使用的寄存器是AX(AL AH) BX(BL BH) CX(CL CH) DX(DL DH) SI DI SP BP等, 这些寄存器可以任意组合,举例如下
MOV AX, BX ; AX = BX
MOV BX, AX ; BX =AX
MOV SI, DI ; SI = DI
MOV DI, SI ; DI = SI
这两种寻址方式是不涉及内存的操作的,所以速度是最快的,所以为了性能考虑应该尽量多的使用这两种寻址方式的操作。
注意: MOV 1, AX 是非法的,应为1就是常数,你不能给常数赋值
直接寻址
MOV AX, [1234H]
MOV AX, ES:[1234H]
直接寻址就是直接给出内存地址的寻址方式,格式是 段寄存器:[偏移地址] 偏移地址是立即数,用[]括起来。当然也可以直接省去前面的段寄存器写作 [偏移地址],这样汇编会自动选择一个默认的段地址,一般来说是DS段寄存器。前面讲过内存地址是 段地址X16+偏移地址,所以使用段寄存器:[偏移地址] 给出的地址就是 段寄存器的值X16 + 偏移地址,
举例
MOV AX, DS:[1234H]
这句话的就是将DSx16+1234H处的数据复制给AX寄存器,假设DS=5000H 那么就是将内存51234处的数据复制给AX,具体是多少就要看当时内存中是什么数据了。
MOV AX, ES:[1234H]
就是显示指定了使用的ES段寄存器,所以就是将ESx16+1234H处的数据复制给AX
注意 ":"前面只能跟着段寄存器 DS ES SS CS寄存器
这一条寻址方式其实是最基础的寻址方式,接下来的其他几种寻址方式都是只是[]中偏移地址的表示方式发生了一些变化而已。
寄存器直接寻址 / 基址寻址
MOV AX, [BX]
MOV AX,CS:[BX]
本质上和直接寻址是没太大区别的,唯一的区别就是在直接寻之中[]中的数据是直接给出的,但是在寄存器间接寻址中这个数字是存储在寄存器中而已。
这里有个限制就是[] 中能使用的寄存器只有 BX BP SI DI ,如果使用的是BX SI DI则默认的段寄存器是DS,如果是BP寄存器则默认使用SS寄存器。
当然如果特意指定寄存器那么就用指定的寄存器。
举例 AX =1 BX = 1111H DS = 5000H
MOV AX, [BX] ; 等于MOV AX,DS:[1111H] 就是将51111H内存出的数据复制到AX中
寄存器相对寻址 / 相对基址寻址
MOV AX, [BX + 1111H]
在寄存器直接寻址的基础上加上立即数,其他规则还是和寄存器直接寻址一样的
举例 AX =1 BX = 2222H DS=5000H
MOV AX, [BX + 1111H] ; 等于 MOV AX, DS:[2222H + 1111H] => MOV AX, DS:[3333H]
基址变址寻址
MOV AX,[BX+SI]
基址变址寻址就是用了两个寄存器 {BX/BP}+{SI/DI}, 如果是出现BP寄存器则默认使用SS寄存器,否则默认使用DS寄存器.规则和寄存器间接寻址也是一样的。
要注意的是这里分为两组了寄存器 BX/BP 和SI/DI,一组中只能出现一个,即不能出现[ BX+BP ] 和 [SI+DI],从名字中就可以看出的 基址+变址,
BX 基地址寄存器
BP 基址指针寄存器(Base Point)
SI 源地址寄存器(Source Index)
DI 目的地址寄存器(Destination Index)
举例 AX =1 BX=1111H SI=2222H DS= 5000H
MOV AX,[BX+SI]; 等于 MOV AX, DS:[BX+SI] => MOV AX, DS:[1111H+2222H] => MOV AX, DS:[3333H]
相对基址变址寻址
MOV AX,[BX+SI+4444H]
可以看出就是在基址变址寻址的基础上加上了立即数其他规则不变
举例 AX =1 BX=1111H SI=2222H DS= 5000H
MOV AX,[BX+SI+4444H]; 等于 MOV AX, DS:[BX+SI+4444H] => MOV AX, DS:[1111H+2222H+4444H] => MOV AX, DS:[7777H]
总结:
在我看来其实就三种寻址方式
1. 立即数寻址 MOV AX, 1 直接给出数据
2. 寄存器寻址 MOV AX, BX 地址是寄存器
3. 内存寻址 MOV AX, 段寄存器 : [地址]
地址使用 [] 括起来,[] 中的结果就是数据在内存中的偏移地址,[] 可以使用两组寄存器 (BX/BP 和 SI/DI) 和 立即数的任意组合,同组寄存器不能同时出现,段寄存器如果不指定则如果出现了BP寄存器就默认使用SS段寄存器否则默认使用DS寄存器
寄存器间接寻址 = [ 只用一个寄存器]
寄存器相对选址 = [用一个寄存器+立即数]
基址变质寻址 = [用两个寄存器]
相对基址变质寻址 = [用两个寄存器+立即数]
写个公式就是
[地址] = [ {BX | BP | 空} + {SI | DI | 空} + {立即数 | 空} ] = [ 基址 + 变址 + 相对(包含其他寄存器)/ 直接(不包含其他寄存器) ]
BX | BP = 基址
SI | DI = 变址
立即数 = 相对(包含其他寄存器)/ 直接(不包含其他寄存器)
这里面是 全用、任选其一、任选其二,名字就根据选用情况来搭配
比如
[基址(BX|BP)+立即数] = 相对基址寻址
[基址(BX|BP)+变址] = 基址变址寻址
[基址(BX|BP)+变址+立即数] = 相对基址变址寻址
其实这些寻址方式在使用汇编写代码的时候都是有对应的使用场景的,这个在以后会介绍的。