以下例子中的寻址方式说的都是源操作数,因为目的操作数都用的是寄存器寻址,不再讨论
1.立即寻址
立即寻址是指令直接给出立即数本身作为操作数,立即数作为指令的一部分跟指令一起存在于代码段中,会被指令预取队列直接取到CPU中进行执行。
如图:
B0H为MOV AL的机器码,不需要咱们掌握,而03H就跟在指令码的下一条,位于存储器的代码段。
2.寄存器寻址
寄存器寻址的操作数在CPU内部的寄存器中,需要指定寄存器名。
如图:
MOV AX,BX的作用是将BX寄存器中的数放到AX寄存器中去。
例:AX ;十六位寄存器
BL ;八位寄存器
3.存储器寻址
注意:存储器寻址中括号中地址,地址长度跟数据长度没关系!地址长度跟数据长度没关系!地址长度跟数据长度没关系![BX]不一定是16位的,[BX]只是一个起始地址,数据长度可以从另一个操作数得到,也可以用ptr指定!
1.直接寻址
操作数在存储器中,操作数的有效地址直接给出。
如图:
1200H只是数据的起始地址,数据的长度跟1200H这个地址没有关系。MOV AX,[1200H]这个指令,因为[1200H]的长度不确定,所以只能看AX来确定长度,AX中的值为5634H。
例:[1200H] ;[数字表达式]
[BUF] ;[地址表达式]
BUF ;地址表达式
2.寄存器间接寻址
操作数在存储器中,操作数的地址由一个寄存器给出。
最令宝子们感到疑惑的寻址方式,宝子们的问题:MOV AL,[BX],因为BX是十六位的,AL是八位的,所以指令不合法~
注意:BX里面装的是有效地址,这个地址是16位的,跟以BX中内容为地址开始的数据长度没有关系。
如图:
BX中的1200H是一个起始地址,这个从这个地址开始,可以存任意长度的数据,[BX]的长度是不确定的,操作数长度由另一个操作数指定,如果另一个操作数长度也不确定,指令就非法了。比如MOV [BX],1234H,[BX]的长度不确定,1234H的长度也不确定,因为立即数可以在前面无限加0,所以指令非法。
寄存器间接寻址的寄存器只能是BX,BP,SI,DI四个。
例:[BX] ;位于数据段的寄存器间接寻址
[BP] ;位于堆栈段的寄存器间接寻址
3.寄存器相对寻址
寄存器相对寻址中,地址由一个间址寄存器和一个偏移量构成,地址为两者之和(或差)
如图:
例:20H[SI] ;偏移地址为SI+20H,在数据段中
[BP]5 ;偏移地址为BX+5,在堆栈段中
STR[BX] ;偏移地址为BX+STR,在数据段中
4.基址加变址寻址
操作数在存储器中,偏移地址由一个基址寄存器(BX或BP)加一个变址寄存器给出(SI或DI)。
如图:
例:[BX+SI] ;偏移地址为BX+SI,在数据段中
[BP][DI] ;偏移地址为BP+DI,在堆栈段中
5.相对基址加变址寻址
操作数在存储器中,存储单元的地址由一个基址寄存器(BX或BP)加一个变址寄存器(SI或DI)加一个偏移量组成。
如图:
例:[BX+SI+5]
buf[bx][di]
4.I/O端口寻址
端口寻址也是给出的端口地址,数据长度要看是多少位的端口,端口地址的位数不代表端口的位数
1.直接端口寻址
操作数在端口中,如果是八位的端口地址,则可以直接由立即数的形式给出
如图:
例:IN AL,34H ;如图,AL中的值为12H
IN AX,34H ;如果34H是个十六位端口的地址,则数据放入AX中
2.间接端口寻址
操作数在端口中,如果是十六位的端口地址,则必须由DX寄存器间接给出
如图:
例:IN AL,DX ;如图,DX中的地址为3456H,则AL中是12H
IN AX,DX ;如果DX中的地址是个十六位端口的地址,则用AX