1.37k likes | 1.55k Views
第三章 80x86 指令系统. 指令 —— 控制计算机完成指定操作的命令 机器指令 —— 指令的二进制代码形式。 例如: CD21H 汇编指令 —— 助记符形式的指令。 例如: INT 21H 指令系统 —— CPU 所有指令及其使用规则的集合. 章节分配. 第一节 80x86 的寻址方式. 第二节 80x86 指令系统. 第三节 80x86 指令系统的纵向比较. 立即寻址. 操作数包含在代码中. 存储器寻址. 寄存器寻址. 操作数存放在存储器中. 操作数存放在寄存器中. 寻址方式. I/O 端口寻址.
E N D
第三章 80x86指令系统 指令——控制计算机完成指定操作的命令 机器指令——指令的二进制代码形式。 例如:CD21H 汇编指令——助记符形式的指令。 例如:INT 21H 指令系统——CPU所有指令及其使用规则的集合
章节分配 第一节 80x86的寻址方式 第二节 80x86指令系统 第三节 80x86指令系统的纵向比较
立即寻址 • 操作数包含在代码中 存储器寻址 寄存器寻址 • 操作数存放在存储器中 • 操作数存放在寄存器中 • 寻址方式 I/O端口寻址 • 操作数存放在I/O端口中 第一节 80x86的寻址方式
存储器 存储器 操作码 操作码 B0H BBH 立即数 AL 20H 20H 立即数 18H MOV AL,20H MOV BX,1820H 图3-1 立即寻址方式指令执行情况 BH BL 一.立即寻址 立即寻址方式所提供的操作数直接包含在指令中,紧跟在操作码之后,作为指令的一部分,这种操作数称为立即数。立即数可以是8位的,也可以是16位的。立即数只能作为源操作数,主要用来给寄存器或存储单元赋值。 例1 MOV AL,20H MOV BX,1820H 指令执行情况如图3-1所示。执行结果为:AL = 20H,BX = 1820H。
二.寄存器寻址 寄存器寻址方式的操作数存放在指令规定的寄存器中,寄存器的名字在指令中指出。寄存器可以是16位的,如AX、BX 、SI、SP等,也可以是8位的,如AH、AL、CL等。 例2 MOV DL,AL MOV AX,CX 如果AL = 30H,CX = 1002H,执行结果为:DL = 30H,AX = 1002H。
三、存储器寻址 • 由于大部分操作数存放在存储单元中。指令中寻找内存单元(称为内存寻址)采用逻辑地址。逻辑地址中,段基址相对变化较少,常在程序的首部把段基址送入段寄存器,后面的指令只需给出段内的偏移地址就可以了。 • 偏移地址又称为有效地址EA,在指令中可以直接或间接给出存储单元的偏移地址,以达到存取存储器操作数的目的。8086指令系统提供了下述多种存储器寻址方式。 • 对16位机(如8086): EA = 基址 + 变址 + 位移量 • 基址——BX、BP • 变址——SI、DI • 位移量——8位或16位带符号数 若使用寄存器BP进行寻址,则默认操作数是存放在堆栈段中,否则默认操作数存放在数据段中
对32位机(如80386): EA = 基址 +(变址*比例因子)+ 位移量 • 基址——EAX、EBX、ECX、EDX、EBP、 ESP、ESI、EDI • 变址——EAX、EBX、ECX、EDX、EBP、 ESI、EDI • 比例因子——1、2、4或8 • 位移量——8位或32位带符号数 若使用寄存器BP进行寻址,则默认操作数是存放在堆栈段中,否则默认操作数存放在数据段中
数据段 段地址DS: 5 0 0 0 0 代码段 50000H …… 偏移量: 1 2 3 4 操作码 + 51234H 89H (操作数低8位) 34H (偏移量低8位) 物理地址: 5 1 2 3 4 51235H 67H (操作数高8位) 12H (偏移量高8位) …… 运行结果:(AX)= 6789H 1、直接寻址 程序直接通过操作数的地址来访问该操作数 例如:MOV AX,[1234H] ;设(DS)=5000H
点击视频播放 13
2、寄存器间接寻址 数据段 代码段 段地址DS: 5 0 0 0 0 50000H …… 传送指令 操作码 偏移量BX: 1 2 3 4 + 操作码 51234H 89H (操作数低8位) 物理地址: 5 1 2 3 4 51235H 67H (操作数高8位) …… 运行结果:(AX)=6789H 操作数存放在存储器中,但操作数的偏移量存放在基址寄存器或变址寄存器中 例如:设(DS)=5000H,(BX)=1234H ,则: MOV AX,[BX]
寄存器间接寻址 (BX) (BP) (SI) (DI) EA = • 只有SI、DI、BX和BP可作间址寄存器 • 例: MOV AX, [BX] • MOV CL, CS:[DI] • 错误例 : • × MOV AX,[DX] • ×MOV CL,[AX]
代码段 段地址DS: 5 0 0 0 0 数据段 50000H …… 操作码 偏移量BX: 1 2 3 4 操作码 位移量: 1 0 0 0 52234H 89H (操作数低8位) 00H (位移量低8位) + 52235H 67H (操作数高8位) 10H (位移量高8位) 物理地址: 5 2 2 3 4 …… 运行结果:(AX)= 6789H 3、寄存器相对寻址 EA = 基址或变址寄存器 + 位移量 例如:假设(DS)=5000H,(BX)=1234H,则: MOV AX,[BX+1000H]
段地址DS: 5 0 0 0 0 数据段 代码段 50000H …… 传送指令 基址BX: 1 2 3 4 操作码 操作码 变址SI: 1 0 0 0 52234H 89H (操作数低8位) + 52235H 67H (操作数高8位) 物理地址: 5 2 2 3 4 …… 运行结果:(AX) = 6789H 4、基址变址寻址 EA = 基址寄存器 + 变址寄存器 例如:设(DS)=5000H,(BX)=1234H,(SI)=1000H,则: MOV AX,[BX+SI]
代码段 段地址DS: 5 0 0 0 0 数据段 50000H …… 操作码 基址BX: 1 2 3 4 操作码 变址SI: 1 0 0 0 54234H 89H (操作数低8位) 00H (位移量低8位) 54235H 67H (操作数高8位) 20H (位移量高8位) 位移量: 2 0 0 0 + …… 物理地址: 5 4 2 3 4 运行结果:(AX) = 6789H 5、相对基址变址寻址 EA = 基址 + 变址 + 位移量 例如:(DS)=5000H,(BX)=1234H,(SI)=1000H ,则: MOV AX,[BX+SI+2000H]
1 8 3 2 5 2 4 0 9 A = 使用相对的基址-变址寻址方式可以很方便地访问二维数组。 数组首地址 (偏移地址) 位移量 基址寄存器 数组元素行址 (行位移地址) 数组元素列址 变址寄存器 (行内元素下标) 二维数组例:
数据段 变址(ESI): 2 12340H+0*4 比例因子: 4 元素0 位移量: 12340H 偏移量: 12340H+2*4=12348H 12340H+1*4 EAX 元素1 AH AL 12340H+2*4 元素2 …… 6、比例变址寻址(386以上) EA = 变址*比例因子 + 位移量 例如:设变址(ESI)=2,比例因子=4,则: MOV EAX,[ESI*4+12340H]
堆栈段 基址(EBP):12340H 12340H+0*2 元素0 变址(ESI):3 比例因子: 2 12340H+1*2 元素1 偏移量: 12340H+3*2=12346H 12340H+1*2 元素2 12340H+3*2 元素3 AH AL …… AX 7、基址比例变址寻址 (386以上) EA = 基址 + 变址*比例因子 例如:基址(EBP)=12340H,变址(ESI)=3,比例因子= 2,则: MOV AX,[EBP+ESI*2]
基址(EBX): 12340H 数据段 变址(EDI): 2 12340H+0*4+12H 比例因子: 4 元素0 位移量: 12H 偏移量: 12340H+2*4+12H=1235AH 12340H+1*4+12H EAX 元素1 AH AL 12340H+2*4+12H 元素2 …… 8、相对基址比例变址寻址 (386以上) EA = 基址 + 变址*比例因子 + 位移量 例如:设基址(EBX)=12340H,变址(EDI)=2,比例因子=4,则: MOV EAX,[EBX+EDI*4+12H]
四、I/O端口寻址 直接端口寻址 采用这种寻址方式时,端口地址只有8位(0~0FFH)。 例如: IN AL,10H ;从10H号端口读入8位数据 OUT 50H,AX ;把AX中的内容送到50H号端口 间接端口寻址:采用这种寻址方式时,端口地址为16位(0~0FFFFH)。 必须先将端口地址存放到寄存器DX中。 例如: MOV DX,1000H ;端口地址为1000H OUT DX,AL ;间接端口寻址
第二节 80x86指令系统 80x86的六大类指令: 一、数据传送类 二、算术运算类 • 三、逻辑操作类 • 四、字符串操作类 • 五、控制转移类 六、处理器控制类
一、数据传送类 通用数据传送指令: MOV、PUSH、POP、XCHG、XLAT 目标地址传送指令: LEA、LDS、LES 标志位传送指令: LAHF、SAHF、PUSHF、POPF 输入输出指令: IN、OUT
1、通用数据传送指令 (1)MOV(Move) • 指令格式:MOV 目的操作数,源操作数 • 指令作用:将一个字节、字或双字从源地址传送到目的地址中 • 指令用法: ① 通用寄存器之间的传送 如:MOV AL, BL MOV CX,DX ② 16位通用寄存器与段寄存器之间的传送 如:MOV BX,CS MOV ES,DX 注意:CS不能作为目的操作数!
③ 通用寄存器与存储器之间的传送 如: MOV [BP+DI],DL ④ 段寄存器与存储器之间的传送 如: MOV DS,[SI] MOV [BX+DI],CS 同样,CS不能作为目的操作数,只能是源操作数 ⑤ 立即数传送到通用寄存器 如: MOV BL,34H MOV AX,12H ⑥ 立即数传送到存储器 如: MOV BYTE PTR[BX],12H 注意:这里必须用“PTR”指定传送的是字节、字还是双字
几个不能传送的解决办法:用AX作桥梁 • 存储器←存储器: MOV AX,MEM1 MOV MEM2,AX • 段寄存器←段寄存器: MOV AX,DS MOV ES,AX • 段寄存器←立即数: MOV AX,DATA MOV DS,AX
SS 堆栈段 SP 栈顶(低地址) 已入栈 的数据 …… 栈底(高地址) (2) PUSH、POP • 入栈操作:数据存放在原栈顶的上方,指针SP相应减小,指向新的栈顶 • 出栈操作:栈顶的数据弹出到指定的位置,指针SP相应增大,指向新的栈顶 关于堆栈: 按先进后出原则组织的一段内存区域,栈顶低地址,栈底高地址 • SS:堆栈段的段基址 • SP:堆栈段的栈顶指针
指令格式:PUSH16位/32位源操作数 POP16位/32位目的操作数 源操作数:16位或32位通用寄存器、段寄存器或存储器操作数,386以上系统允许PUSH指令的源操作数为立即数 目的操作数:16位或32位通用寄存器、段寄存器或存储器操作数,只有386以上的处理器才能使用32位的操作数 • 指令作用: • PUSH指令能把一个字或一个双字操作数压入栈中 • POP指令能将栈顶的一个字或一个双字弹出送到目的操作数中
堆栈段 堆栈段 SS SS 原SP,1000H 34H(原栈顶) BL 新SP,0FFEH 34H(新栈顶) AL 1001H 12H BH 0FFFH 12H AH 新SP,1002H 新栈顶 原SP,1000H 原栈顶 …… …… PUSH AX 执行前:(AX)=1234H,(SP)=1000H 执行后:AX不变,(SP)=0FFEH 栈顶的字=1234H POP BX 执行前:栈顶的字=1234H, (SP)=1000H 执行后:(BX)=1234H,(SP)=1002H • 应用举例:
(3)XCHG (Exchange) • 指令格式: XCHG目的操作数,源操作数 源和目的操作数必须同为通用寄存器,或一个是通用寄存器,另外一个是存储器操作数 • 指令作用:交换源和目的操作数的值 • 应用举例: XCHG AX,BX 若执行前(AX)=1000H,(BX)=2000H 则执行后(AX)=2000H,(BX)=1000H
(4) XLAT (Translate) • 指令格式: XLAT TABLE TABLE为字节表的首地址,只起说明作用,可省去 • 指令作用: 完成一次查表的功能,将数据段中地址为(BX)+(AL)中的一个字节传送到AL中 • 指令用法: • 建立字节表 • (BX)←字节表的首地址 • (AL)←需要传送的字节在表中的序号 • 执行XLAT指令
应用举例: 建立一个0~9的整数平方表,然后利用XLAT指令,将42的值传送到AL中。 • 建立0~9的整数平方表 : SQUARE_TABLE DB 00H,01H,04H,09H,10H,19H,24H,31H,40H,51H • (BX)←字节表的首地址 MOV BX,OFFSET SQUARE_TABLE • (AL)←需要传送的字节在表中的序号4: MOV AL,4 • 执行XLAT指令: XLAT SQUARE_TABLE;“SQUARE_TABLE”可省去 • 结果: (AL)= 10H( 42=16)
2、目标地址传送指令 (1)LEA(Load Effective Address) • 指令格式: LEA 目的操作数,源操作数 目的操作数只能是通用寄存器,源操作数一定是存储器操作数 • 指令作用: 将存储器操作数的地址偏移量传送到目的寄存器中 • 应用举例: 设(BX)=1000H,(DI)=0100H LEA BX,[BX+DI+0010H] 执行指令后: EA=(BX)+(DI)+0010H = 1000H+0100H+0010H=1110H 故:(BX)= 1110H
…… BUFFER 数据段 12H 2000H 34H 2001H 56H 2002H …… 则: LEA AX,BUFFER ;(AX)←2000H MOV AX,BUFFER ;(AX)←3412H MOV AX,OFFSET BUFFER ; (AX)←2000H “OFFSET”是一个求段内偏移量的操作符 • LEA与MOV的区别与联系 • LEA指令得到的是存储器操作数的地址偏移量 • MOV指令得到的是存储器操作数中的值 例如:在数据段中有定义(设BUFFER的偏移量为2000H): BUFFER DB 12H,34H,56H
(2)LDS(Load pointer into DS) • 指令格式与作用: LDS目的操作数,存储器操作数 • 对8086系统: 目的操作数:16位通用寄存器 存储器操作数:32位远地址,其中高16位为段地址,低16位为偏移量 指令作用:(DS)←段地址,目的操作数←偏移量 • 对80386系统: 目的操作数:32位通用寄存器 存储器操作数:48位远地址,其中高16位为段地址,低32位为偏移量 指令作用:(DS)←段地址,目的操作数←偏移量
数据段 原DS …… 1000H:2000H 34H BX 偏移量 12001H 12H 12002H 00H 段地址 DS 12003H 20H …… 指令: LDS BX,[2000H] 执行后: (BX)=1234H,(DS)=2000H 相当于: MOV BX,[2000H] MOV AX,[2002H] MOV DS,AX • 应用举例: 在8086中,假设(DS)=1000H,数据段中偏移量为2000H~2003H的地址中分别存放34H,12H,00H,20H,则:
(3) LES • LES指令与LDS相似,区别是这些指令分别将段地址传送到段寄存器ES
FLAGS: - - - - O D I T S Z - A - P - C AH: 7 6 5 4 3 2 1 0 3、标志位传送指令 (1)LAHF(Load AH with Flags) • 指令格式: LAHF • 指令作用: 将标志寄存器中的SF、ZF、AF、PF、CF分别传送到AH的第7、6、4、2、0位,AH的其它位没有定义
(2)SAHF(Store AH with Flags) • 指令格式:SAHF • 指令作用:AH的值送标志寄存器低八位 (3)PUSHF(Push the Flags) • 指令格式:PUSHF • 指令作用:标志寄存器入栈,SP的值减2 (4)POPF(Pop the Flags) • 指令格式:POPF • 指令作用:标志寄存器出栈,SP的值增2
利用PUSHF/POPF修改TF: PUSHF ;标志寄存器入栈 POP AX ;标志寄存器→(AX) OR AH,01H ;AX第8位(对应标志寄存器的TF位)置1 PUSH AX ;AX入栈 POPF ;入栈的AX的值→标志寄存器
4、输入输出指令 (1)IN • 指令功能: 从指定的端口地址(0~0FFFFH)中读入一个字节、字或双字,并传送到AL、AX中 • 指令用法: • IN AL,8位端口地址n(直接端口寻址方式) 从端口号为n的端口中读入一个字节送至AL中,n≤255 例:IN AL, 20H ;(AL)←[20H] • IN AX,8位端口地址n(直接端口寻址方式) 从端口号为n+1、n的端口中读入两个字节送至AH、AL中,n≤255 例:IN AX, 20H ; (AH)←[21H] ,(AL)←[20H]
INAL,DX(间接端口寻址方式) 从端口号为(DX)的端口中读入一个字节,并送到AL中 例:设(DX)=1000H,则: IN AL, DX ;(AL)←[1000H] • INAX,DX(间接端口寻址方式) 从端口号为(DX)+1、 (DX)的端口中读入2个字节,并送到AH、AL中 例:设(DX)=1000H,则: IN AX, DX ; (AH)←[1001H], (AL)←[1000H]
(2)OUT • 指令功能: 将AL、AX中的数据输出到指定的端口中 • 指令用法: • OUT 8位端口地址n,AL 作用:[n]←(AL) • OUT 8位端口地址n,AX 作用:[n+1]←(AH), [n]←(AL) • OUT DX,AL 作用:[DX]←(AL) • OUT DX,AX 作用:[DX+1]←(AH), [DX]←(AL)
二、算术运算类 加法指令: ADD、ADC、INC、AAA、DAA 减法指令: SUB、SBB、CMP、DEC、NEG、AAS、DAS 乘法指令: MUL、IMUL、AAM 除法指令: DIV、IDIV、AAD 类型转换指令: CBW、CWD