分类:
2009-01-14 09:59:29
寻址方式(Addressing)通俗地讲就是寻找地址的方法。
这个地址可以是CPU内部的寄存器――寄存器寻址方式。(程序员以名称区别各个寄存器,但CPU则利用地址编码区别)
这个地址也可以是主存储器地址――存储器寻址方式。
这个地址还可以是I/O地址――I/O寻址方式。
本节学习8086的操作数寻址方式,其他寻址方式在第2章陆续展开。
操作数寻址方式――寻找操作数的方法。
CPU可以直接将数据本身与指令一起编码作为指令代码的一部分,也可以存放在寄存器或主存储器中,这就对应立即数寻址、寄存器寻址和存储器寻址方式。又由于存储器地址有多种表示方法,于是又存在多种存储器寻址方式;8086支持的存储器寻址方式有:直接寻址、寄存器间接寻址、寄存器相对寻址、基址变址寻址、相对基址变址寻址方式。
8086CPU的机器代码(Machine Code,也称指令代码Instruction Code)一般格式:操作码占1个或2个字节,后面的各个字节指明操作数。其中,“mod reg r/m”字节表明寻找操作数的方式(即采用的寻址方式),“位移量”字节给出某些寻址方式需要的相对基地址的偏移量,“立即数”字节给出立即寻址方式需要的数值本身。操作数的各个字段有多种组合。 8086指令最多可以有两个操作数。在“mod reg r/m”字节中,reg字段表示一个采用寄存器寻址的操作数;reg占用3位,不同编码指示8个8位(w=0)或16位(w=1)通用寄存器之一。mod和r/m字段表示另一个操作数的寻址方式,分别占用2位和3位。
除了上述一般机器代码格式外,8086CPU还有其它机器代码格式。 读者不能理解机器代码,没有关系,不会影响程序设计。现在,只要能够理解最常用的传送指令MOV功能: MOV dest,src ;dest←src MOV指令的功能是将源操作数src传送至目的操作数dest。 |
在立即数寻址方式下,指令中的操作数就直接存放在机器代码中,紧跟在操作码之后。这条指令汇编成机器代码后,操作数作为指令的一部分存放在操作码之后的主存单元中。称这种操作数为立即数imm,它可以是8位数值i8(00H ~ FFH),也可以是16位数值i16(0000H ~ FFFFH)。 立即数寻址方式常用来给寄存器赋值。 |
例:将16位立即数0102H送至AX寄存器
MOV AX,0102H ;AX←0102H
该指令机器代码为“B8 02 01”,其中B8为操作码,紧接着16位立即数0102H。注意高字节01H存放于高地址中,低字节存放于低地址单元中。
寄存器寻址方式的操作数存放在CPU的内部寄存器reg中, 它可以是8位寄存器r8:AH / AL / BH / BL / CH / CL / DH / DL; 也可以是16位寄存器r16:AX / BX / CX / DX / SI / DI / BP / SP。 另外,操作数还可以存放在4个段寄存器中seg:CS / DS / SS / ES。 寄存器寻址方式的操作数存放于CPU的某个内部寄存器中,不需要访问存储器,因而执行速度较快,是经常使用的方法。 |
例:将寄存器AX的内容传送给BX寄存器保存
MOV BX,AX ;两个操作数均为寄存器寻址:BX←AX
如何寻址主存中存储的操作数就称为存储器寻址方式,也称为主存寻址方式:
为了方便各种数据结构的存取,根据有效地址的提供方法不同,8086设计了多种主存寻址方式:
指令中直接包含了有效地址。16位有效地址紧接着操作码,存放在代码段中。默认的段地址在DS段寄存器中,但可使用段超越前缀改变。 汇编语言的语法中,一般规定用中括号表达存储单元的内容。所以为了区别于16位立即数,书写汇编指令时要将16位有效地址加上中括号。 |
例1:将数据段中偏移地址2000H的一个16位数据传送给AX
MOV AX,[2000H] ;AX←DS:[2000H],指令代码:A10020
该指令中给定了有效地址2000H,它还不是存储器的物理地址。默认情况下,有效地址要与数据段寄存器DS一起构成操作数所在存储单元的物理地址。
寄存器间接寻址方式中,有效地址存放在基址寄存器BX或变址寄存器SI、DI中。默认的段地址在DS段寄存器中,但可使用段超越前缀改变。
例:将数据段中由SI指定偏移地址的一个16位数据传送给AX
MOV AX,[SI] ;AX←DS:[SI]
该指令中有效地址存放于SI寄存器中,而操作数则存放在数据段主存单元中。假设SI内容设置为2000H,则该指令等同于MOV AX, [2000H]。
寄存器相对寻址方式下,有效地址是寄存器内容与有符号8位或16 位位移量之和,寄存器可以是BX、BP或SI、DI。其中采用BX、SI、DI寄存器则默认是数据段DS,采用BP 寄存器默认是堆栈段SS;当使用非默认段时,可用段超越前缀。
操作数的有效地址应该是:有效地址=BX / BP / SI / DI + 8 / 16位位移量
例:将数据段中由DI内容加上6作为偏移地址指向的一个16位数据传送给AX
MOV AX,[DI+06H] ;AX←DS:[DI+06H]
这条指令中使用的是DI寄存器,位移量为06H,那么操作数的有效地址EA=DI+06H,与DI寄存器约定的段是数据段是DS。
例:将堆栈段中由BP内容加上6作为偏移地址指向的一个16位数据传送给AX
MOV AX,[BP+06H] ;AX←SS:[BP+06H]
该指令使用的是BP寄存器,与之约定的段为堆栈段SS。
基址变址寻址方式是把一个基址寄存器(BX或BP)的内容加上变址寄存器(SI或DI)的内容构成有效地址EA。若基址寄存器使用BX,其默认段为数据段DS;若基址寄存器使用BP,其默认段为堆栈段SS。
操作数的有效地址EA为:有效地址=BX / BP + SI / DI
例:
MOV AX,[BX+SI] ;AX←DS:[BX+SI]
MOV AX,[BP+DI] ;AX←SS:[BP+DI]
MOV AX,DS:[BP+DI] ;AX←DS:[BP+DI]
相对基址变址寻址方式,也使用基址寄存器(BX / BP)和变址寄存器(SI / DI), 另外还在指令中指定一个8位或16位的位移量,这三者之和构成操作数的有效地址EA,与BX寄存器约定的段为数据段DS,与BP寄存器约定的段为堆栈段SS。
相对基址变址寻址方式的有效地址=BX / BP + SI / DI + 8 / 16位位移量
例:
MOV AX,[BX+SI+06H] ;AX←DS:[BX+SI+06H]
操作数寻址方式是汇编语言的重点和难点。请按如下思路学习:
1. 操作数可以存在什么地方?
⑴ 操作数存在于指令代码中,处理器译码时就立即获得了这个操作数,这就是立即(数)寻址方式。汇编指令中,这个立即数(操作数)以常量形式出现。
⑵ 操作数存在于处理器内部寄存器中,处理器从寄存器中获得这个操作数, 这就是寄存器寻址方式。汇编指令中,这个寄存器操作数以寄存器名形式出现。
⑶ 操作数存在于主存中,处理器从主存单元获得这个操作数,这就是存储器寻址方式。汇编指令中,这个存储器操作数以主存地址形式出现。
2. 8086/8088处理器的主存地址在程序设计时采用逻辑地址。
逻辑地址分成段地址和偏移地址两部分。3. 存储器寻址方式表达存储器地址时,段地址在默认的或段超越前缀指令指定的段寄存器中,偏移地址被称为有效地址EA(Effective Address)。有效地址用中括号括起来。
4. 有多种获得偏移地址的方法,所以存储器寻址方式又分成多种寻址方式。
⑴ 有效地址直接给出,存在于指令代码中,就是直接寻址方式。
⑵ 有效地址存在寄存器中,就是通过寄存器的间接寻址方式。
⑶ 有效地址是两部分的和,一部分在寄存器中,另一部分直接给出(称为位移量),这就是寄存器相对寻址方式。
⑷ 有效地址是两部分的和,一部分在基址寄存器中(8086是BX和BP),另一部分在变址寄存器中(8086是SI和DI),这就是基址变址寻址方式。
⑸ 有效地址是三部分的和,第一部分在基址寄存器中(8086是BX和BP),第二部分在变址寄存器中(8086是SI和DI),第三部分直接给出(称为位移量),这就是相对基址变址寻址方式。
5. 区别各种寻址方式时,注意各自的特点。
只有一个常量,是立即(数)寻址方式;只有一个寄存器名,是寄存器寻址方式;其他则是存储器寻址方式。用中括号括起一个常量是直接寻址方式;用中括号括起一个寄存器名,是寄存器间接寻址方式;用中括号括起一个寄存器名和一个常量是寄存器相对寻址方式;用中括号括起两个寄存器名是基址变址寻址方式;用中括号括起两个寄存器名和一个常量是相对基址变址寻址方式。
6. 汇编语句中,还有其他形式出现,需要理解相应操作符才能做出正确判断。
例如,直接写出变量名实际上是直接寻址方式;变量名加减一个常量还是直接寻址方式;变量名和一个寄存器则是寄存器相对寻址方式;利用offset后跟一个变量名则是立即数寻址方式。
chinaunix网友2009-06-20 10:44:16
bistu-mawenxiao,find 2k_debug_kernel,sometimes d->rf->zr(or nz),only show IP=???? NV,even [2b0,59d5] hold still(ie silence),but 99.999999%,can show ip=???? NV UP ..NC