8086汇编内存寻址方式
前面的博客都多少提到了8086汇编的内存寻址,例如mov ax [2345H]。而8086汇编还提供了更多、更灵活的寻址方式,以满足多种需求。
需要强调的是,无论何种寻址方式,内存寻址的地址总是由基础地址+偏移地址(段基址+偏移量)组合而成,不同之处在于基础地址与偏移地址应该从何处获得。
8086汇编提供寻址段基址的方式
在示例mov ax [2345H]中,并没有显示的指明段地址的值,这是因为8086汇编在处理没有明确指明段基址的指令时,一般默认将数据段寄存器DS的值作为段基址。也就是说,mov ax [2345H]其实是mov ax ds:[2345H]的缩写。
特别的,当偏移地址的指定[],存在了bp段寄存器时,则默认的段寄存器为SS栈段寄存器,指令mov ax [bp]实际为mov ax ss:[bp]的缩写形式。
8086汇编中通过“段寄存器:偏移地址”的方式指定寻址时的段基址。而ds并不是唯一的段寄存器,在内存寻址时的段地址可以不存放于段寄存器DS中,而是存放其它的段寄存器中。可以在指令中显式的指明(mov ax cs:[2345H] 此时的段地址在代码段寄存器cs中)。
8086汇编提供寻址偏移量的方式
8086汇编提供偏移地址的方式很多样,大致可以分为五类:直接寻址、寄存器间接寻址、寄存器相对寻址、基址变址寻址、相对基址变址寻址,按照先后顺序,灵活性和复杂度逐渐增加。
偏移地址可能由某一寄存器指定,也可能存放在某一处内存中,或是在指令缓冲器中,亦或是由它们的组合构成。
直接寻址
直接寻址其实就是前面提到过的寻址方式(mov ax [2345H]),其所指明的寻址偏移地址直接保存在指令中,在实际运行时,CPU会从指令缓冲器中获取到对应的偏移值进行内存寻址。
这里提出一个idata(immediate data)直接数、立即数的概念,用以指代1000H或是2345H这样指令中的常量值。包含idata常量的指令,其值都存放在指令缓冲器中,供CPU在执行时获取。
指令mov ax, 1000H,代表将立即数1000H送入ax中,可以抽象表示为mov ax, idata的形式。
指令mov ax, [1000H],代表对DS:1000H内存进行寻址,可以抽象表示为mov ax, [idata]的形式。
寄存器间接寻址
寄存器间接寻址,从寻址方式的名字中可得,地址不是常量而是类似一个变量,其值存在于一类特殊的寄存器,寻值寄存器中。
需要注意的是,8086并不允许所有的寄存器作为寄存器间接寻址之用,而只有寄存器bx、bp、si、di这四个寄存器被称为寻值寄存器,可用于寄存器间接寻址。寄存器间接寻址时使用其它的寄存器都会被编译器认为是语法错误。
寄存器间接寻址的的方式为[bx]/[bp]/[si]/[di]四种,例如mov ax,[bx],指令的含义为将内存地址为ds:bx处的数据送入寄存器ax中。
寄存器相对寻址
通过常量idata或是特定类型寄存器可以指定偏移地址进行寻址,直接寻址和寄存器间接寻址只选用了寄存器或立即数idata中的一种元素,较为简单。而更复杂的寻址方式是将常量idata和寄存器寻址组合起来实现的。
寄存器相对寻址是通过将寻址寄存器与idata结合起来进行的。 在寄存器相对寻址这种一个寻址寄存器+一个常量的寻址模式中,bx/bp/si/di是等价的。
寄存器相对寻址较为灵活,大致有以下几种(第1种是标准格式,2、3、4是语法糖):
1.[bx+idata]/[bp+idata]/[si+idata]/[di+idata] 标准格式
2.[bx].idata/[bp].idata/[si].idata/[di].idata 一般用于结构体
3.idata[bx]/idata[bp]/idata[si]/idata[di] 一般用于一维数组
4.[bx][idata]/[bp][idata]/[si][idata]/[di][idata] 一般用于二维数组
为什么8086汇编会为寄存器相对寻址提供如此之多语法不同但本质一样的语法糖呢?仔细观察可以发现,2、3、4的写法很像高级语言中的结构体/对象、数组的访问方式。8086提供的多样的语法格式能够让写出的程序更加易于理解。后续的博客会对8086汇编模拟高级语言中数组、结构体的内存结构设计进行详细说明。
基址变址寻址
基址变址寻址比寄存器相对寻址的方式更加灵活,是通过两个不同的寻址寄存器组合而成。但这里bx/bp/si/di并不能随意的两两搭配,其中bx/bp一组,si/di一组。不同组之间的寻址寄存器才能两两组合,共有四种:[bx+si]、[bx+di]、[bp+si]、[bp+di]。
基址变址寻址一般用于对二维数组中数据的寻址。
相对基址变址寻址
相对基址变址寻址在基址变址寻址的基础上,再添加了一个idata常量元素,寻址模式是两个变量+一个常量,是最复杂也最灵活的一种寻址方式。
和基址变址寻址寻址类似,相对基址变址寻址也有四种方式:[bx+si+idata]、[bx+si+idata]、[bx+si+idata]、[bx+si+idata]。
8086CPU提供的相对基址变址寻址方式,为处理嵌套的结构化数据提供了方便,如访问结构体中的数组时可以比较自然的表达其偏移地址。