0 前言
众所周知,对于8086汇编语言,有几大寻址方式,不过我觉得这个好墨迹,会用就可以了,为什么命名这么多,这次只说本质,不说命名,至于命名,还是得知道,毕竟是大部分人公认的,不能反抗这点哦,但是你知道,不代表你真的要这么去想。
1 何为寻址?何为寻址方式?
看了很多资料,让人眼花缭乱,各种专业词汇让人眼花缭乱,扑朔迷离,我直接用最简练的语言说明。
- 寻址,就是找数据
- 寻址方式,就是找数据的方法
接下来,根据数据的位置,我再细说一下各种寻址方式。
2 立即数寻址
一句话,在指令中找数据。
访问方式: 找指令的时候,顺便将数据带过来了,怎么找指令就怎么找它。
举例:
mov ax,1000h
1000h
就是立即数,也就用到了立即数寻址。
3 寄存器寻址
一句话,在寄存器中找数据。
访问方式: 直接写上寄存器的名字,就能访问了。
举例:
mov ax,1000h
ax
就是寄存器的名称,也就用到了寄存器寻址。
4 存储器寻址
一句话,在存储器中找数据。(这里的存储器,通常情况下指的是主内存)
访问方式: 表示出存储单元的地址,就能访问了。
唯独存储器寻址比较麻烦,因为它表示地址的方式有很多种。
但是在我这里,也就一句话,地址的形成方式是:BX,BP,SI,DI和立即数
的各种组合。
其实也就这些而已,只不过还有一些其他的规则限定,我也来细说一下(顺便说一句,这些东西,先看懂理解,然后自己动手试一下,多试试就学会了,不要背)。
BX —— based register——基地址寄存器
BP —— base point——基础指针
SI —— source index——源变址寄存器
DI —— destination index——目的变址寄存器
先给出你英文全称,你就很快能够知道,为什么是这几个寄存器了。
4.1 语法格式
mov ax,dataSegmentName
mov ds,ax
mov 目标,[address]
使用存储器寻址的时候,需要
- 设置好DS的值
- 再设置
[address]
的值,address的内容,就是上面说的
4.2 各种存储单元地址的生成方式
这里,我结合大家公认的命名,以及我自己的观点,阐述这些内容。
不管是什么寻址方式,本质就是为了生成address的值,生成数值的本质,就是我说的5个东西(bx,bp,si,di,立即数
)进行基本的数学运算。
- 寄存器直接寻址
由立即数提供偏移地址。
mov ax,ds:[1000h]
在汇编语言中,立即数作为偏移地址,前面需要显式地加上提供段地址的寄存器,另外,这种显式的方式,一样可以应用于后面的方式,但是不是强制的。
- 寄存器间接寻址
由bx,si,di
提供偏移地址,注意没有BP,至于原因,与硬件设计和语法设定有关,不必追究。
mov ax,[bx] ; 也可以写上 mov ax,ds:[bx]
mov ax,[si]
mov ax,[di]
另外,也可以使用其他段寄存器(ss,cs,es)提供段地址,显示加上就可以,mov ax,ss:[bx]
,这样就由ss提供段地址,bx提供偏移地址。
- 基址寻址
由bx + 位移量
或bp + 位移量
提供偏移地址。
特殊:只有bp提供偏移地址的时候,默认ss寄存器提供段地址,其他的默认ds。
mov ax,[bx + 10H] ; 本质 mov ax,ds:[bx + 10H]
mov ax,[bp + 10H ]; 本质 mov ax,ss:[bp + 10H]
另外,在寻址范围之内,位移量可正可负可为0,下面的4,5也是这样。
- 变址寻址
由si + 位移量
或di + 位移量
提供偏移地址。
mov ax,[si - 10h]
mov ax,[di - 10h]
- 基址变址寻址
由1个基址寄存器 + 1个变址寄存器 + 位移量
提供偏移地址,只有含有BP,就是SS提供段地址。
mov ax,[bx + si + 10h]
4.3 位移量为什么还可以是负数?
首先,你需要了解的是,这里的负数是十进制的负数,编码方式是二进制补码。
位移量是正数,就代表在基础之上,加了东西
位移量是负数,就代表在基础之上,减了东西
说白了就是,可加可减,反正都是找数据,怎么找都可以,画个图你就明白了。
你可能问,如果是bx - 11h
,但是bx < 11h
,不是成了负数?注意,在二进制世界,减过头了,叫溢出,是正溢出,溢出的结果,就是循环回去。 我再画个图:
对于有符号数
正溢出:两数运算,大于最大的正数,进入负数区域
负溢出:两数运算,小于最小的负数,进入正数区域
4.4 小结
注意,位移量其实就是个常数,也可以说成立即数,大多数情况不用区分。
1个:[常数]
,[bx]
,[si]
,[di]
2个:[bx + 位移量]
,[bp + 位移量]
,[si + 位移量]
,[di + 位移量]
3个:[(bx或bp)+ (si或di)+ 位移量]
,注意,不可以是[bx + bp + 位移量]
或[si + di + 位移量]
。
4.5 思想方法
需要注意的是,以上是数学运算,都是加减法,但是这只是在8086中,未来,还会有乘法的出现,但是依然没有脱离本质,address = { {BX,BP,SI,DI和立即数} 的基本数学混合运算}。
希望你明白,之所以不要你去专注于各种被限定的寻址方式,是因为那些不是本质,掌握本质,把握知识源头,才能够更好地应对未来。
在x86-32汇编语言中,地址的生成方式,又有所改变。
例如:mov dword ptr [ebp+eax*4-6Ch],edx
,如果你记忆的是8086汇编于寻址方式,那么这个新的方式,你依然要去记忆,但是如果你掌握的是本质,你就知道,这不过是在生成地址的过程中,增加了一个乘号而已,之后你再去探索一下,为什么增加这个乘号,你就可以快速透彻理解和掌握它了。
5 注意事项
需要注意的是,这些理解,是为了让你抓住本质,但是并不代表,你只知道这些就可以了,内些杂乱的命名,依然有存在的价值,你同样需要掌握。
最后,还有一个重要的感悟,那就是任何操作数,都需要应用到这些寻址方式,因为计算机的本质就是处理数据,数据又需要通过寻址来找到。
推荐阅读:计算机处理信息的本质,是二进制数的运算(本文第2节)