第 3 章 8086 的寻址方式和指令系统 (2) 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 1
3.3 8086 指令系统 可分成如下 6 类 : 数据传送指令 算术运算指令 逻辑运算和移位指令 串操作指令 程序控制指令 处理器控制指令 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 2
3.3.1 数据传送指令 可实现 存储器 立即数 段寄存器 CS DS ES SS 数据传送指令又可分为如下四种 : 通用传送 目标地址传送 标志传送 输入输出 通用寄存器 AX AH BX AL CX BH DX BL SI CH DI CL SP DH BP DL 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 3
3.3.1 数据传送指令 数据传送指令见表 3.3 数据传送指令, 除 SAHF 和 POPF 指令外, 对标志位均没有影响 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 4
1. 通用数据传送指令 1) MOV dest,src; dest src 指令功能 : 目的操作数 源操作数传送的是字节还是字取决于指令中涉及的寄存器是 8 位还是 16 位 具体来说可实现 : 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 5
1 MOV mem/reg1,mem/reg2 一般指令中两操作数中至少有一个为寄存器例 : MOVCL,DL MOV AX,BX MOV[SI],CX MOV CL,[BX+5] 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 6
2 MOV reg, data ; 立即数送寄存器 MOV BX,123H MOV AL, B ; B AL, (AL)=42H 3 MOV mem, data MOV [150H], 150H 4 MOV acc, mem MOV AX,[5200H] 5 MOV mem,acc MOV [9100H], AX ; 立即数送存储单元 ; 存储单元送累加器 ; 累加器送存储单元 6MOV segreg, mem/reg ; 存储单元 / 寄存器送段寄存器 MOV SS, AX 7 MOV mem/reg, segreg ; 段寄存器送存储单元 / 寄存器 MOV AX, CS 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 7
MOV 指令使用规则 : 1) IP 不能作源 目的寄存器,CS 不能作目的寄存器 2) 不允许 mem mem 3) 不允许 segreg segreg 4) 立即数不允许作为目的操作数 5) 不允许 segreg 立即数 6) 源操作数与目的操作数类型要一致 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 8
数据段 在汇编语言程序中, 数据通常存放在数据段中 例如, 某个程序的数据段 : DATA SEGMENT ; 数据段开始 AREA1 DB 12H,34H AREA2 DB 3 DUP(0) ARRAY DW 1234H,5678H STRING DB GOOD DATA ENDS ; 数据段结束 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 9
数据段 数据段以段说明符 SEGMENT 开始,ENDS 结束,DATA 是编程人员定义的数据段的段名 DB 伪操作符用来定义字节变量 DW 定义字变量, 低字节在前, 高字节在后 DUP 复制操作符, 前面的 3 说明在存储器中保留 3 个字节单元, 初值均为 0 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 10
数据段 数据占用存储空间的情况如图 AREA1 的偏移地址为 0000H AREA2 的偏移地址为 0002H ARRAY 的偏移地址为 0005H 字符串 GOOD 从 0009H 开始存放 AREA1 12 34 AREA2 00 00 00 ARRAY 34 12 78 56 STRING 'G' 'O' 'O' 'D'... 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 11
如, 偏移地址传送 MOV DX,OFFSET ARRAY 将 ARRAY 的偏移地址送到 DX, 其中,OFFSET 为属性操作符, 表示应把其后的符号地址的值 ( 而不是内容 ) 作为操作数 若 ARRAY 的值如上页图, 则指令执行后, 符号地址 ARRAY 的偏移量 0005H 被送到了 DX 中 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 12
再如, 段寄存器初始化 MOV AX,DATA MOV DS,AX 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 13
再如, 存储器 存储器 MOV AL,AREA1;AL AREA1 中的内容 12H MOV AREA2,AL;0002H 地址单元 12H 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 14
还有, 需要将两个逻辑段重叠, 即指向同一段物理空间 MOV AX,DS MOV ES,AX 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 15
应用举例将 1000H 开始的 100 个存储单元, 全部填充为 ASCII 码 2AH(*) 程序如下 : AGAIN: MOV DI, 1000H MOV CX, 64H MOV AL, 2AH MOV [DI], AL INC DI DEC CX JNZ AGAIN HLT 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 16
上述程序段存放在代码段中, 设 (CS)=2000H, 则各条指令存放地址如下 : CS : IP 指令 2000 : 0100 MOV DI,1000H 2000 : 0103 MOV CX,64H 2000 : 0106 MOV AL,2AH 2000 : 0108 MOV [DI],AL 2000 : 010A INC DI 2000 : 010B DEC CX 2000 : 010C JNZ 0108 2000 : 010E HLT 2000 : 0110 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 17
写入 2AH(*) 后, 数据段中相应存储单元的内容改变如下 : DS:1000 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A DS:1010 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A DS:1020 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A DS:1030 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A DS:1040 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A DS:1050 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A DS:1060 2A 2A 2A 2A 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 18
2) 堆栈操作指令 什么是堆栈? 按 先进后出 (FILO) 方式工作的存储区域 堆栈以字为单位进行压入 弹出操作 为什么要设置堆栈? 为什么要按 先进后出 方式工作? 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 19
主程序 主程序 执行子程序 1 IP IP( 下 ) 继主续程执序行 执行子程序 IP IP( 下 ) 继主续程执序行 IP IP ( 下 ) 继子续程执序行 1 执行子程序 2 (a) (b) 子程序调用示意图 (a) 主程序调子程序 ; (b) 子程序嵌套示意图 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 20
规定由 SS 指示堆栈段的段基址, 堆栈指针 SP 始终指向堆栈的顶部,SP 的初值规定了所用堆栈区的大小 堆栈的最高地址叫栈底 SS 入栈方向 SP 栈顶 堆栈段 出栈方向 栈底 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 21
1 入栈指令 PUSH src ; src 为 16 位操作数指令功能 : 将源操作数推入堆栈先修改栈顶 (SP SP-2), 再压数据 例 :PUSH AX ; 将 AX 内容入栈执行操作 : (SP) (SP)- 2 (SP)-2 低字节 AL (SP)-1 高字节 AH 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 22
设 (AX)=1020H, 执行示意图如图 低地址 存储区 (SS 段 ) 低地址 存储区 (SS 段 ) (SP)-2 (SP) 20 (AL) (SP)-1 (SP) 10 (AH) 进栈方向 高地址 执行前 (AX)=1020 高地址 PUSH AX 指令执行示意图 执行后 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 23
注意进栈方向是高地址向低地址增长 入栈指令的格式为 : PUSH reg PUSH mem PUSH segreg 例如 : PUSH AX PUSH [BX] PUSH DS 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 24
2 出栈指令 POP dest 指令功能 : 把当前 SP 所指向的一个字送到目的操作数中先弹出数据, 再修改栈顶 (SP SP+2) 例 :POP BX ; 将栈顶内容弹至 BX 执行操作 :(BL) (SP) (BH) (SP)+1 (SP) (SP)+2 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 25
POP BX 的执行示意图如下图所示 存储区 存储区 (SS 段 ) 低地址 (SS 段 ) 低地址 (SP) 20 (SP)+1 10 (SP)+2 执行前 10 20 BX 高地址 (SP) 执行后 (BX)=1020 出栈方向 高地址 POP BX 指令执行示意图 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 26
堆栈指令使用时应注意几点 : 1 堆栈操作总是按字进行 2 不能从栈顶弹出一个字给 CS 3 堆栈指针为 SS:SP,SP 永远指向栈顶 4SP 自动进行增减量 (-2,+2) 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 27
3) 交换指令 XCHG 格式 :XCHG reg, mem/reg 功能 : 交换两操作数的内容 要求 : 两操作数中必须有一个在寄存器中 ; 操作数不能为段寄存器和立即数 ; 源和目地操作数类型要一致 举例 : XCHG AX, BX XCHG [2000H], CL 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 28
(3) 交换指令 XCHG 方法二 : MOV DX, AX MOV AX, BX MOV BX, DX 方法三 : PUSH AX PUSH BX POP AX POP BX 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 29
4) 表转换指令 XLAT XLAT 转换表 ; 转换表 为表格首地址, 可省略不写指令功能 : 将 1 个字节从一种代码转换成另一种代码执行的操作 :AL [(BX)+(AL)] 又叫查表转换指令 典型的隐含寻址它可根据表项序号查出表中对应代码的内容 执行时先将表的首地址 ( 偏移地址 ) 送到 BX 中, 表项序号事先存于 AL 中 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 30
例如 : 内存数据段有一张 1 6 进制数的 ASCII 码表, 设首地址为 2000H, 如欲查出表中第 11 个代码 ( 代码序号从 0 开始 ) 即十六进制数 B 的 ASCII 码 ASCII 表在 DS 段中, 并假设 (DS)=4000H 见下页图 B 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 31
42000H+0 42000H+0BH 存储器 30 31 32... 39 41 42... 45 46... 0 1 2 9 A B E 十六进制数 ASCII 码表 F ( 必须先在内存中建表!) 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 32
则可用如下几条指令实现 : MOV BX, 2000H ;(BX) 表首地址 MOV AL, 0BH ;(AL) 序号 XLAT ; 查表转换 执行后得到 :(AL)= 42H = B 注意 : 转换表长度最大为 256 个表项 ( 字节 ) 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 33
2. 输入输出 (I/O) 指令 只限于用累加器 AL 或 AX 来传送信息 功能 : ( 累加器 ) I/O 端口 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 34
2. 输入输出 (I/O) 指令 (1) 输入指令 IN 格式 : IN AL, 端口地址 ;AL 从 8 位端口读入 1 字节或 IN AX, 端口地址 ; 从 16 位端口读入 1 个字 IN AL,DX ; 端口地址存放在 DX 中或 IN AX,DX 格式, 端口地址 (00~FFH) 直接包含在 IN 指令里, 共允许寻址 256 个端口 当端口地址大于 0FFH 时, 必须用格式 寻址, 即先将端口号送入 DX, 再执行输入操作, DX 允许范围 0000~ 0FFFFH 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 35
2. 输入输出 (I/O) 指令 (1) 输入指令 IN 例用 IN 指令从输入端口读取数据 IN AL,0F1H ;AL 从 F1H 端口读入 1 字节 ; IN AX,80H ;AL 80H 端口内容 ;AH 81H 端口内容 ; MOVDX,310H ; 端口地址 310H 先送入 DX IN AL,DX ;AL 310H 端口内容 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 36
(2) 输出指令 OUT 指令格式 : OUT 端口地址,AL 或 OUT 端口地址,AX ; OUT DX,AL 或 OUT DX,AX ;8 位端口 AL 内容 ;16 位端口 AX 内容 ;DX= 端口地址 例 : OUT 68H,AX ;(69H,68H) AX OUT DX,AL ;(DX) AL 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 37
在使用间接寻址 IN/OUT 指令时, 要事先用传送指令把 I/O 端口号设置到 DX 寄存器中, 如 : MOVDX, 220H IN AL, DX ; 将 220H 端口内容读入 AL 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 38
3. 地址目标传送指令 共有三条 : 格式 : 1)LEA reg, mem 2)LDS reg, mem32 3)LES reg, mem32 要求源操作数必须是一个内存操作数, 目的操作数必须是一个 16 位的通用寄存器 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 39
3. 地址目标传送指令 1) LEA 取有效地址指令 (Load Effective Address) 指令格式 : LEA 目的, 源指令功能 : 取源操作数地址的偏移量, 送到目的操作数 源操作数必须是存储单元, 目的操作数是一个除段寄存器之外的 16 位寄存器 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 40
例 :LEA BX, [SI+10H] 设 :(SI)=1000H 则执行该指令后,BX=1010H 注意以下两条指令差别 : LEA BX, BUFFER ; 有效地址传送 MOV BX, BUFFER; 直接寻址 BUFFER 所对 ; 应的单元, 将所存储的 ; 内容送 BX 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 41
如果要用 MOV 来取偏移地址的话, 下面两条指令等效 : LEA BX, BUFFER MOV BX, OFFSET BUFFER 注意,OFFSET 只能取静态地址 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 42
2)LDS(LES) reg, mem32; 指令格式 : LDS(ES) 目的, 源指令功能 : 从源操作数指定的存储单元中, 取出 1 个 4 字节地址指针, 送进目的寄存器 DS(ES) 和指令中指定的目的寄存器中 源操作数必须是 4 字节存储单元, 目的操作数必须是 16 位寄存器, 常用 SI 寄存器, 但不能用段寄存器 该指令运行后, 前两个字节送到指令中的目的寄存器 reg 中, 后两个字节送 DS(ES) 中 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 43
21000H 21080H 存储器... 00 10 34 12... 例 :LDS(LES) SI, [80H] 设 DS=2100H, (21080H)=1000H, (21082H)=1234H 执行指令后 : (SI)=1000H (DS/ES)=1234H 执行指令前后,DS 有无变化? 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 44
4. 标志传送指令 共有四条 : 1) 读标志指令 LAHF 指令格式 :LAHF 指令功能 :LAHF 把标志寄存器低 8 位中的 5 个标志位传送到 AH 中的指定位 D AH D7 6 D D 5 D D 3 D D 4 2 1 0 FLAG OF DF IF TF SF ZF AF PF CF LAHF 指令的功能 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 45
(2) 设置标志指令 SAHF 指令格式 :SAHF 指令功能 : SAHF 的功能与 LAHF 的功能正好相反 AH D7 D 6 D 5 D D 3 D D 4 2 1 D0 FLAG OF DF IF TF SF ZF AF PF CF SAHF 指令的功能 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 46
(3)PUSHF 标志入栈指令指令格式 : PUSHF 指令功能 : (SP-2) 标志寄存器 FR 低 8 位 (SP-1) 标志寄存器 FR 高 8 位 SP SP-2 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 47
(4)POPF 标志出栈指令指令格式 : POPF 指令功能 : 标志寄存器低 8 位 (SP) 标志寄存器高 8 位 (SP+1) SP SP+2 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 48
例如 : PUSH AX PUSH CX ; PUSHF ; 这段程序用到 AX,CX 以及标志位 ; 保护标志寄存器内容... POPF POP CX POP AX ; 程序体 ; 恢复标志寄存器内容 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 49
在数据传送指令中, 除 SAHF 和 POPF 这两条指令外, 其余指令均不影响标志位 可采用堆栈指令修改 TF 标志, 以进入跟踪状态 如 : PUSHF POP AX OR AX,0000 0001 0000 0000B PUSH AX POPF 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 50
课堂讨论 下列指令是否正确, 为什么? MOV BX,[CX] MOV DS,ES MOV [SI],35H PUSH AH PUSH CS POP CS POP DS 2015 年 3 月 26 日星期四 8 时 41 分 27 秒 51