目录
4.1 立即寻址方式n
4.1.1 使用格式及功能
4.1.2 例子
4.2 寄存器寻址方式R
4.2.1 使用格式及功能
4.2.2 例子
4.3 直接寻址方式[n]
4.3.1 使用格式及功能
4.3.2 读操作
4.3.3 写操作
4.3.4 符号地址
4.3.5 段前缀
4.3.6 例子
4.4 寄存器间接寻址方式[R]
4.4.1 使用格式及功能
4.4.2 例子
4.5 寄存器相对寻址方式[R+n]
4.5.1 使用格式及功能
4.5.2 例子
4.6 基址变址寻址方式V[R×F]
4.6.1 使用格式及功能
4.6.2 例子
4.7 相对基址变址寻址方式[BR+IR×F+V]
4.7.1 使用格式及功能
4.7.2 例
4.8 小结
寻址方式就是指令中寻找操作数的方式。对于每一条指令,我们需要关注指令执行什么操作?操作数存放在的位置?。那机器指令处理的数据在什么地方?
操作数的存放地址:
CPU的寄存器
内存
I/O设备接口
操作数在主存时:关注段址/段选择符、段内偏移——物理地址
操作数的类型:字节/字/双字
数据处理大致可分为3类:读取、写入、运算。在机器指令这一层来讲,并不关心数据的值是多少,而关心指令执行前一刻,它将要处理的数据所在的位置。指令在执行前,所要处理的数据可以在3个地方:CPU内部、内存、端口
指令:操作码和操作数组成。操作数字段可以有一个、两个或三个,通常称为一地址、二地址或三地址指令。
二地址指令中两个操作数:源操作数和目的操作数。
格式: [标号:] 指令助记符 [操作数] [;注释]
双操作数指令的两点提示:
(1) 双操作数指令的两个操作数,长度须匹配。
(2) 双操作数指令的两个操作数中,不能两个操作数同为内存单元。
操作数直接放在指令中,在指令的操作码后;
操作数是指令的一部分,位于代码段中;
指令中的操作数是8位、16位或32位二进制数。
格式:n
格式:R
功能:操作数存放在寄存器。指令中给出寄存器名。
说明:除个别指令外,R可为任意寄存器
源操作数和目的操作数类型需要一致。
操作数在内存中
操作数的有效地址EA就在指令中,紧跟操作码后面。机器默认段地址在DS中。
操作数所在的段:由段寄存器名指示,或者是变量所在的段
操作数的类型:若有变量,则是定义变量的类型
如果要实现CPU写内存操作,只要把MOV指令的目的操作数变为存储单元,源操作数为CPU的寄存器即可。
例4-5 MOV DS: [4000H], AX
直接寻址方式除了用数值作为有效地址之外,还可以用符号地址的形式。为存储单元定义一个名字,该名字就是符号地址。如果把存储单元看成变量,该名字也是变量名。
在与内存有关的寻址方式中,操作数的段地址默认为数据段,80X86规定除了数据段之外,数据还可以存放在其他三种段中。如果操作数在其他段中存放,称为段超越,需要在指令中用段超越前缀指出,即用操作数前加上段寄存器名和冒号表示。
mov ax, ds:[bx]
mov ax, cs:[bx]
mov ax, ss:[bx]
mov ax, es:[bx]
mov ax, ss:[0]
mov ax, cs:[0]
例1. VALUE EQU 1000H
例2:计算2^12
assume cs:code
code segment
mov ax, 2
mov cx, 11 ;循环次数
s: add ax, ax
loop s ;在汇编语言中,标号代表一个地址,标号s实际上标识了一个地址,
;这个地址处有一条指令:add ax,ax。
;执行loop s时,首先要将(cx)减1,然后若(cx)不为0,则向前
;转至s处执行add ax,ax。所以,可以利用cx来控制add ax,ax的执行次数。
mov ax,4c00h
int 21h
code ends
end
例3:将内存ffff:0 ~ ffff:b
单元中的数据复制到0:200 ~ 0:20b
单元中。
assume cs:code
code segment
mmov ax,0ffffh
mov ds,ax ;(ds)=0ffffh
mov ax,0020h
mov es,ax ;(es)=0020h 0:200→0020:0
mov bx,0 ;(bx)=0,此时ds:bx指向ffff:0,es:bx指向0020:0
mov cx,12 ;循环12次
s: mov dl,[bx] ;(d1)=((ds)* 16+(bx)),将ffff:bx中的字节数据送入dl
mov es:[bx],dl ;((es)*16+(bx))=(d1),将dl中的数据送入0020:bx
inc bx ;(bx)=(bx)+1
loop s
mov ax,4c00h
int 21h
code ends
end
格式:[R]
功能:操作数在内存中,操作数的偏移地址在寄存器R中,即(R)位操作数的偏移地址。
操作数的有效地址在寄存器中,只允许使用BX、BP、SI和DI寄存器。
eg:MOV AX,[CX] 不符合规定❌
寄存器间接寻址方式的寻址过程:
例1: MOV AX,[BX]
例2: MOV SS:[DI],AX
MOV AX,[BX] ;默认DS寄存器作段地址
MOV DX,[BP] ;默认SS寄存器作段地址
MOV ES:[DI],AX ;指定ES寄存器作段地址
例3:比较
MOV AX,BX
MOV AX,[BX]
例4:设BUF DB 10,20,30,40,50即以BUF为首址的字节区中存有5个数据,求他们的和。
算法分析:
和
循环次数
数据位置 BX (0005)([BX])
单元中的内容无规律,但单元的地址有规律
SEG1 SEGMENT USE16 STACK
DB 200 DUP(0)
SEG1 ENDS
SEG2 SEGMENT USE16
BUF DB 10,20,30,40,50
RES DB ?
SEG2 ENDS
SEG3 SEGMENT USE16
ASSUME CS:SEG3,
DS:SEG2,SS:SEG1
START: MOV AX,SEG2
MOV DS,AX
MOV CX,0 ; 计数
MOV AH,0 ; 和
MOV BX,OFFSET BUF ;取buf的偏移地址
LP: CMP CX,5
JGE EXIT
ADD AH,[BX]
INC BX
INC CX
JMP LP
EXIT:MOV RES,AH
MOV AX,4C00H
INT 21H
SEG3 ENDS
END START
Question:ADD AH, [BX]可否换成 ADD AH, BX?不可以
C语言:
SEG1 SEGMENT USE16 STACK
DB 200 DUP(0)
SEG1 ENDS
SEG2 SEGMENT USE16
BUF DB 10,20,30,40,50
RES DB ?
SEG2 ENDS
SEG3 SEGMENT USE16
ASSUME CS:SEG3,
DS:SEG2,SS:SEG1
START: MOV AX,SEG2
MOV DS,AX
MOV CX,0 ; 计数
MOV AH,0 ; 和
MOV BX,OFFSET BUF ;取buf的偏移地址
LP: CMP CX,5
JGE EXIT
ADD AH,[BX]
INC BX
INC CX
JMP LP
EXIT:MOV RES,AH
MOV AX,4C00H
INT 21H
SEG3 ENDS
END START
p与BX对应:ADD EAX,[BX] ADD BX,4
操作数的有效地址是一个寄存器和位移量之和。
格式:[R+n]
例: MOV AX, TOP[SI],指令TOP为符号地址,即位移量。
例: MOV AX,[BX+2623H]或写成MOV AX,[BX].2623H
格式:[R×F+V] 或 [R×F]+V 或 V[R×F]
功能:R中的内容×F+V,为操作数的偏移地址
操作数的有效地址是一个基址寄存器和一个变址寄存器的内容之和。
基址寄存器BX和BP,变址寄存器SI和DI。
F可以为1,2,4,8(比例因子),当R为16位寄存器时,F只能为1
默认段寄存器搭配和寄存器间接寻址方式一样。
段地址(SA)和偏移地址(EA) ;指令要处理的数据在内存中,在汇编指令中可用[X]的格式给出EA,SA在某个段寄存器中。
mov ax, [0]
mov ax, [di]
mov ax, [bx+8]
mov ax, [bx+si]
mov ax, [bx+si+8] ;以上段地址默认在ds中
mov ax, [bp]
mov ax, [bp+8]
mov ax, [bp+si]
mov ax, [bp+si+8] ;以上段地址默认在ss中
mov ax, ds:[bp]
mov ax, es:[bx]
mov ax, ss:[bx+si]
mov ax, cs:[bx+si+8] ;显式给出存放段地址的寄存器
例: MOV AX, [BX+DI]
例:MOV AL, [EBX*2]+5
例:用变址寻址方式写一段程序,求BUF中数据的和
STACK SEGMENT USE16 STACK
DB 200 DUP(0)
STACK ENDS
SEG1 SEGMENT USE16D
BUF DD 10,20,30,40,50
RES DD ?
SEG1 ENDS
CODE SEGMENT USE16
ASSUME CS:CODE
DS:SEG1,SS:STACK
START: MOV AX,SEG1
MOV DS,AX
MOV EBX,0 ; 计数
MOV EAX,0 ; 和
LP: CMP EBX,5
ADD EAX,BUF[EBX*4]
INC EBX
JMP LP
EXIT:MOV RES,EAX
MOV AX,4C00H
INT 21H
CODE ENDS
END START
int buf[5]={10,20,30,40,50};
int i;
int res = 0;
p = buf;
for{i=0;i<5;i++}{
res+ = buf[i];
}
思考:(EBX) 中的值就是变量i的值,为何C语言中的访问方是 buf[i],而汇编语言中是 buf[EBX*4] ?
C语言放在变量里面,汇编放在寄存器里面。
比较变址寻址和寄存器间接寻址有何异同
1.遍历EBX第几个元素 2.EBX里面的值就是偏移地址,不知道BUF放在什么位置,类似于指针用法。
例:
设 BUF1 DB 10,20,25,37,50 即以BUF1 为首地址的字节区存放有5个数据,将他们拷贝到以BUF2为首址的字节去。与数组类比:A[0],A[1],A[2],......B[0],B[1],B2[2]
for (i=0;i<5;i++)
BUF2[i] = BUF1[i];
MOV BX,0 ;BX:第几个元素
MAINP: CMP BX,5
JGE EXIT
MOV AL,BUF1[BX]
MOV BUF2[BX], AL ;两个立即数不能直接传送
INC BX
JMP MAINP
EXIT:
用寄存器间接寻址程序段
MOV SI,OFFSET BUF1 ;取地址
MOV DI,OFFSET BUF2
MOV CX,5
MAINP: MOV AL,[SI]
MOV [DI],AL
INC SI
INC DI
DEC CX
JNZ MAINP
EXIT:
设 BUF1 DB 10,20,25,37,50 即以BUF1 为首地址的双字去存放有5个数据,将他们拷贝到以BUF2为首址的字节区。
for(i=0;i<5;i++)
BUF2[i] = BUF1[i];
MOV BX,0
MAINP: CMP BX,5
JGE EXIT
MOV AL,BUF1[BX*4]
MOV BUF2[BX*4], AL
INC BX
JMP MAINP
EXIT:
MOV SI,OFFSET BUF1
MOV DI,OFFSET BUF2
MOV CX,5
MAINP:MOV AL,[SI]
MOV [DI],AL
INC SI
INC DI
DEC CX
JNZ MAINP
格式:[BR+IR×F+V] 或 V[BR] [IR×F] 或V[IR×F] [BR] 或V[BR+IR×F]
功能:操作数的偏移 = 变址寄存器IR中的内容×比例因子F+位移量V+基址寄存器BR中的内容
$$
EA = (IR)*F+V+(BR)
$$