1.73k likes | 2.13k Views
第 3 章 80x86 汇编语言程序设计 ( 上 ) 16 位汇编版本. 3.1 80x86 的寻址方式. 有效地址 ( effective address EA ) —— 操作数在段内的偏移地址 寻址方式 —— 产生有效地址的方法. 80x86 指令的一般汇编语言格式: [ 标号 :] 指令助记符 [[ 目的操作数 ][, 源操作数 ]][; 注释 ] 其中 [ ] 表示可选项 ;. 3.1.1 操作数寻址. 80x86 的操作数寻址方式有: 1 、立即寻址 2 、寄存器寻址 3 、存储器寻址 4 、端口寻址.
E N D
3.1 80x86的寻址方式 有效地址(effective address EA) —— 操作数在段内的偏移地址 寻址方式 —— 产生有效地址的方法 80x86指令的一般汇编语言格式: [标号:]指令助记符[[目的操作数][,源操作数]][;注释] 其中[ ]表示可选项; 3.1.1 操作数寻址 80x86的操作数寻址方式有: 1、立即寻址 2、寄存器寻址 3、存储器寻址 4、端口寻址
我们首先讨论两种与存储器无关的寻址方式: 1、立即寻址 操作数以常量形式直接放在指令中,紧跟在操作码之后 机器码存放形式如下: 代码段 代码段 低地址 操作码 OP OP 操作码 D16低8位 D8 8位操作数 高地址 16位操作数 D16高8位 立即寻址示例 MOV AH, -40; -40AH MOV AX, 34D8H ;34HAH, D8HAL MOV AX, -40; 0FFD8H(-40)AX
2、寄存器寻址 操作数存放在某个寄存器中,指令指定寄存器号 指令 寄存器 操作数 寄存器号 寄存器寻址示例 MOV AH, BL;(BL)-->AH MOV DS, AX;(AX)-->DS MOV SI, AX;(AX)-->SI 说明:立即寻址和寄存器寻址方式不需访问存储器即可得到操作数,速度快
下面我们来讨论余下的几种与存储器有关的寻址方式,先介绍几个概念:下面我们来讨论余下的几种与存储器有关的寻址方式,先介绍几个概念: 有效地址(EA)的4种组成成分: 有效地址的计算: EA=基址 +(变址*比例因子)+ 位移量 • 位移量(displacement) 存放在指令中的8位、16位或32位的数,是一个地址 • 基址(base) 存放在基址寄存器中的内容,用于指向数组的首地址 • 变址(index) 存放在变址寄存器中的内容,用于访问数组的某个元素 • 比例因子(scale factor) 32位汇编才有 • 其值可为1,2,4或8,386及其后继机型新增加的
访问非默认段数据的方法——段超越 数据的存放比较灵活,除了放在默认的DS段,还可以存放在别的段,此时访问他们需要使用段超越前缀,可用的段超越前缀有CS:, DS:, ES:, SS:, FS:, GS:。 段超越举例: MOV AX, [10H] ;DS段10H处的一个字的数据赋给AX寄存器 MOV AX, ES:[10H]; ES段10H处的一个字的数据赋给AX寄存器 不允许使用段超越前缀的情况: (1)串操作指令的目的串必须用ES段 (2)PUSH指令的目的和POP指令的源必须用SS段 (3)程序的指令必须存放在CS段
3、直接寻址 操作数地址的偏移量(EA)在指令中 段基地址 存储器 指令 操作数 EA + 物理地址=指定段的段基地址×16+偏移量(EA) 系统默认,操作数在数据段 MOV AX, 2000H ; 立即寻址 MOV AX, [2000H] ; 直接寻址
直接寻址示例1 MOV AX, [1000H]物理地址 设(DS)=10A0H 代码段+ OP 00H 10H 数据段 11A00H 30H 50H 1000H 10A0H 10A00H 1000H 低地址 11A00H 11A00H 30H 50H AX 50H 30H (本章中图示存储器地址从上到下递增)
直接寻址示例2 MOV BL, ES:[0100H]物理地址 设(ES)=3000H 30000H (DS)=2000H + 0100H 30100H 4B 00 BL 0100H 3000H 30100H 30100H 4B 4B 在汇编语言指令中,可以用符号地址代替数值地址 如:MOV AX, BUFF 或 MOV AX, [BUFF] 其中BUFF为存放数据单元的符号地址。
4、寄存器间接寻址 操作数在存储器中,操作数地址的偏移量(EA)在寄存器中 段基地址 指令 寄存器 存储器 基址或变址寄存器号 EA 操作数 + 寄存器间接寻址示例 MOV AL, [BX] MOV AX, CS:[SI] MOV [BP], AH
MOV AH, [BP] MOV BX, [SI] MOV CX, SI 设(SS)=1000H, (DS)=2000H , (BP)=0B10H, (SI)=032AH 物理地址 物理地址 10000H 20000H + 0B10H + 032AH 40H 00H 3EH 46H 1000H 2000H 0B10H 032AH 10B10H 10B10H 2032AH 2032AH AH 40H 10B10H SI 032AH 032AH 40H 10B11H … CX 032AH 2032AH 3EH 463EH BX 46 2032BH
5、基址寻址 操作数的有效地址是基址寄存器的内容加上指令中指定的位移量 指 令 段基地址 基址寄存器号 位移量 存储器 EA 操作数 + + 基址寄存器 地址 可用于数组元素的访问
基址寻址示例 MOV AX, 3000H[BX] (或[BX+3000H]) MOV AX, COUNT[BX]; COUNT是符号地址 (或 MOV AX,[COUNT+BX]) 若(DS)=3000H, (BX)=2000H,COUNT=4000H 30000H 2000H + 4000H 4000H 3000H 2000H 36000H 36000H 34H 36000H 34H 12H 12 1234H AX
6、变址寻址 操作数的有效地址是变址寄存器的内容加上指令中指定的位移量 指 令 段基地址 变址寄存器号 位移量 存储器 操作数 + + 变址寄存器 EA 地址
变址寻址示例 MOV CX, 6020H[SI] (或[SI+6020H]) MOV DX, COUNT[SI];COUNT是符号地址 (或 MOV AX,[COUNT+SI]) 若(DS)=3000H, (SI)=2000H,COUNT=1000H 30000H 2000H + 1000H 3000H 2000H 1000H 33000H 33000H 33000H 34H 67H 34H 67 6734H DX
7、基址变址寻址 1)无位移量的基址变址寻址 操作数的有效地址是一个基址寄存器和一个变址寄存器的内容之和 变址寄存器 指 令 段基地址 变址值 基址寄存器变址寄存器 存储器 操作数 + + 基址寄存器 EA 基址值
无位移量基址变址寻址示例 MOV AX, [BX+DI] MOV AX, [BX][DI] 若 (DS)=2100H, (BX)=0158H, (DI)=10A5H, 2100H 0158H 物理地址 21000H 0158H + 10A5H 10A5H 221FDH 221FDH 34H 221FDH 34H 12H 12 1234H AX
2)基址变址相对寻址 操作数的有效地址是一个基址寄存器的内容、 一个变址寄存器的内容及位移量之和 指 令 基址寄存器变址寄存器位移量 段基地址 存储器 变址寄存器 EA 变址值 + + 操作数 基址值 基址寄存器
基址变址相对寻址示例 MOV AX, MASK[BX+SI];MASK是符号地址 若 (DS)=3000H, (BX)=2000H, (SI)=1000H, MASK=0250H 物理地址 30000H 2000H 1000H + 0250H 33250H 20H 43H 3000H 1000H 2000H 0250H 33250H 33250H 20H 43 4320H AX
8、端口寻址 1)直接寻址(I/O Port Direct Addressing) 直接寻址是使用一字节立即数寻址,因此I/O端口的寻址范围为00H~FFH,最多为256个。 IN AL, 20H;从20H端口读入1个字节 OUT 60H, AX;将AX中1个字送到60H端口 2)间接寻址(I/O Port Indirect Addressing) 间接寻址由DX寄存器间接给出I/O端口地址,为两个字节,所以最多可寻址216=64K个端口地址。 MOV DX, 3FCH IN AL, DX;从3FCH端口读入1个字节
3.1.2 转移操作寻址 • 段内直接寻址 • 转向的有效地址是当前IP/EIP寄存器的内容和指令中指定的位移量之和。位移量在条件转移以及短转移中只有8位,其它情况下为16位。
段内间接寻址 • 转向有效地址是一个寄存器或是一个存储单元的内容 。所得到的转向的有效地址用来取代IP/EIP寄存器的内容。 • 设:(DS)=2000H,(BX)=1000H,变量TABLE的有效地址为1000H,(21000H)=0040H,(22000H)=5678H,则下列三条指令分别执行后结果如下: • JMP BX ;执行后IP=1000H • JMP [BX] ;执行后IP=0040H • JMP TABLE[BX] ;执行后IP=5678H
段间直接寻址 • 指令中直接提供了转向段地址和偏移地址,用指令中提供的偏移地址取代IP/EIP寄存器,用指令中提供的段地址取代CS寄存器的内容就完成从一个段到另一个段的转移操作。 • JMP FAR PTR NEXT_PRO • 段间间接寻址 • 用存储器中的相继字的内容来取代IP/EIP和CS寄存器中的原始内容以达到段间转移的目的。 • 设:(DS)=2500H,(SI)=1300H,(26300H)=4500H,(26302H)=32F0H, 则执行以下指令后结果如下: • JMP DWORD PTR [SI];执行后CS=32F0H,IP=4500H
3.2 80x86的指令系统 • 数据传送指令 • 算术运算指令 • 逻辑运算与移位指令 • 串操作指令 • 控制转移指令 • 处理器控制指令
3.2.1数据传送指令 • 通用数据传送指令 • 地址传送指令 • 标志寄存器传送指令 • 输入输出指令 • 类型转换指令
1、通用数据传送指令 MOV(move) 传送 MOVSX(move with sigh-extend) 带符号扩展传送 MOVZX(move with zero-extend) 带零扩展传送 PUSH(push onto the stack) 进栈 POP(pop from the stack) 出栈 PUSHA/PUSHAD (push all registers) 所有寄存器进栈 POPA/POPAD (pop all registers) 所有寄存器出栈 XCHG(exchange) 交换 XLAT(translate) 换码
MOV 传送指令 格式:MOV DST, SRC 操作:DST<--(SRC) 即把源操作数的内容送入目的操作数 说明:1)可以进行8位、16位或32位数据的传送 2)SRC可为立即数、寄存器、存储器操作数 3)DST可为寄存器、存储器操作数 4)该指令不影响任何状态标志位 段寄存器 CS DS SS ES 通用寄存器 AX BX CX DX BP SP SI DI 立即数 存储器
MOV指令示例1 MOV AL, BL ;寄存器之间传送 MOV BP, SI MOV AX, [BX+DI] ;存储器操作数 MOV AX, ARRAY[SI] ;传送到寄存器 MOV AX, 0B00H ;立即数传送到寄存器 MOV CL, 10000000B MOV VALUE, 100H ;立即数传送到存储单元 MOV ES:[BX], 4BH MOV [BX], CX ;寄存器内容传送到存储器 MOV BUFF [BP][DI], AX
MOV指令示例2 MOV AX, ARRAY[SI] 设(DS)=3000H, (SI)=2000H, ARRAY=8000H 物理地址 30000H 2000H + 8000H 3A000H 3A000H 45H 0BH 0B45H AX
MOV指令注意事项: (1)两个操作数长度必须一致 MOV AL, BX ;不合法 例外:源是16进制立即数,位数小于目的操作数时,高位按0扩展,源是10进制立即数,位数小于目的操作数时,高位按符号位扩展 MOV AX, 0D8H 执行后,(AX)=00D8H MOV AX, -40 执行后,(AX)=FFD8H (2)不允许用立即数为段寄存器赋值 例:MOV ES, 10A0H ;不合法
(3)不允许两个操作数均是存储器操作数 MOV X, Y ;不合法 可以通过一个寄存器传送: MOV AX, Y MOV X, AX (4)不允许两个操作数均为段寄存器 MOV ES, DS ;不合法 (5)不允许CS、IP和立即数做目标操作数 MOV CS, AX ;不合法 MOV 100H, AX ;不合法 MOV IP, BX ;不合法
PUSH 压栈指令 格式:PUSH SRC 操作: 16位指令: SP<--(SP)-2 ((SP)+1,(SP))<--(SRC) 32位指令: ESP(ESP)-4 ((ESP)+3,(ESP)+2,(ESP)+1,(ESP))(SRC) 举例:PUSH AX PUSH DAT[BX][SI] PUSH 1234H PUSH 87654321H PUSH EAX 说明:1) 源操作数可以是寄存器或存储器操作数 2) 必须以字或双字为单位操作 3) 32位指令允许SRC是16位或32位立即数,也容许是32位寄存器和存储器操作数
压栈指令示例 PUSH AX 执行前 AX AX 25H 31H SP 52500H 执行后 31 25H 3125H 3125H 低地址 低地址 524FEH 524FFH 52500H SP 进栈方向
POP 出栈指令 格式:POP DST 操作: 16位指令: DST<--((SP)+1,(SP)) SP<--(SP)+2 32位指令: DST((ESP)+3,(ESP)+2,(ESP)+1,(ESP)) (ESP)(ESP)+4 举例:POP AX POP DAT[BX][SI] POP DS POP ECX
出栈指令示例 POP BX 执行前 执行后 BX BX 75C1H 低地址 低地址 SP 6Bh 51000H 6Bh 51000H 48h 1H 48h 1H 9Ah 2H 9Ah 2H 28h 3H 28h 3H 48h 6Bh 6Bh SP 48h 48h 出栈方向
PUSHA/PUSHAD 所有寄存器进栈 格式:PUSHA PUSHAD 操作: PUSHA: (286及其后继机型) 16位通用寄存器依次进栈,次序为: AX,CX , DX,BX,指令执行前的SP,BP,SI,DI 指令执行后 SP(SP)-16 仍指向栈顶 PUSHAD:(386及其后继机型, 32位汇编) 32位通用寄存器依次进栈,次序为:EAX,ECX, EDX,EBX,指令执行前的ESP,EBP,ESI,EDI 指令执行后 ESP(ESP)-32 仍指向栈顶
PUSHA指令示例 执行前 执行后 (DI) -16 (SI) -14 (BP) -12 (SP)原 -10 (BX) -8 (DX) -6 (CX) -4 (AX) -2 0 (SP) (SP)原
POPA/POPAD 所有寄存器出栈 格式:POPA POPAD 操作: POPA: (286及其后继机型) 16位通用寄存器依次出栈,次序为: DI,SI,BP,SP,BX,DX,CX , AX 指令执行后 SP(SP) +16 仍指向栈顶 POPAD: (386及其后继机型, 32位汇编 ) 32位通用寄存器依次出栈,次序为:EDI,ESI, EBP,ESP,EBX,EDX,ECX , EAX 指令执行后 ESP(ESP) +32 仍指向栈顶
XCHG 交换指令 格式:XCHG OPR1, OPR2 操作:(OPR1) (OPR2) 如: XCHG AX, BX;寄存器之间交换 XCHG BX, [BP+DI] ;寄存器与存储器之间交换 XCHG [SI], DX 说明: 1)操作数不允许为段寄存器 2)两个操作数长度必须相同 3)本指令不影响状态标志位 4)两个操作数不能同时为存储器操作数
交换指令示例 XCHG DX, DATA[BP] 设(SS)=5000H, (BP)=0400H, DATA=1800H 物理地址=5000H×16+0400H+1800H=51C00H 执行前 执行后 DX DX 37CDH 51C00H 42H 51C00H 1H 6DH 1H 6D42H CDH 37H
XLAT查表指令(换码指令) 格式:XLAT TABLE 或XLAT 操作:AL<--((BX)+(AL)) 或 AL((EBX)+(AL)) 将AL中的当前内容转换为表中某一种代码。执行前一定要将表(TABLE)的EA赋给BX(或EBX)寄存器,将代码在表中距首址的偏移放在AL寄存器中。 XLAT指令示例TABLE 30H LEA BX, TABLE +1 31H ;表首址给BX +2 32H MOV AL, 4 +3 33H ;待转换内容到AL +4 34H XLAT +5 35H +6 36H +7 37H 34H AL
2、地址传送指令 LEA (load effective address) 有效地址送寄存器 LDS (load DS with pointer) 指针送寄存器和DS LES (load ES with pointer) 指针送寄存器和ES LFS (load FS with pointer) 指针送寄存器和FS LGS (load GS with pointer) 指针送寄存器和GS LSS (load SS with pointer) 指针送寄存器和SS
LEA 装载有效地址指令 格式: LEA DST, SRC 操作:DST<--SRC的有效地址EA 说明:SRC必须是存储器操作数,而DST则必须是一个16位或32位的通用寄存器(AX..DI..) LEA指令示例 设(DS)=2000H, (BX)=1234H LEA DI, [BX] MOV SI, [BX] 执行后 执行后 21234H 78H 5H 56H SI 5678H SI 1234H 78H 56 1234H 1234H BX
LEA DI, BUFFER ; 将变量BUFFER的 ; 有效地址送到DI, ;而不是将BUFFER ;变量的值送DI MOV DI, BUFFER ; 将变量BUFFER的 ; 有效地址送到DI, ;而不是将BUFFER ;变量的值送DI 执行后 执行后 SI 1234H SI 5678H BUFFER 78H 78H 21234H 1234H 56 56 5H
LDS 装载数据段指针指令 格式:LDS DST, SRC 操作:DST(SRC) DS(SRC+2) 或DS(SRC+4) LES 、LFS、LGS、LSS 格式:同LDS,目标分别是ES,FS,GS,和SS寄存器 说明: 1) 源操作数必须是存储器操作数 2) 目的操作数必须是寄存器 3) 完成一个逻辑地址的传送,该逻辑地址须用伪指令预先定义在当前数据段中
LDS指令示例 LDS DI, [BX] 设(DS)=2000H, (BX)=1000H 执行前 执行后 DI DI 7659H D645H • H 45H • H D6H • H 00H • H 50H DS DS 2000H 5000H 再比如:LDS BX, BUFF[SI] LDS DI, BUFF
LEA与LDS的区别 LEA SI, BUFF LDS DI, BUFF BUFF(21000H) 45H +1 D6H +2 00H +3 50H 设(DS)=2000H EABUFF=1000H 执行后: SI=1000H DI=D645H DS=5000H 思考: LDS DI, BX是合法指令吗?
3、标志寄存器传送指令 LAHF(load AH with flags) 标志送AH SAHF(store AH into flags) AH送标志寄存器 PUSHF/PUSHFD(push the flags or eflags) 标志进栈 POPF/POPFD(pop the flags or eflags) 标志出栈