470 likes | 721 Views
第七讲 8086/8088 指令系统(续) 2006 年 10 月 31 号(星期二). 课前复习指令系统: 1 .MOV DS,2010H ; 错 不能将立即数直接给段寄存器 2 .PUSH AL ; 错 不能对字节进行堆栈操作 3 .MOV DX, [SP] ; 错 无 [SP] 寻址方式,存储器地址 只能通过 BX,BP,SI,DI 寻址 4 .IN AL,0A00H ; 错 端口地址大于 FFH 应用 DX 寻址端口 5 .XCHG CL,CH ; 对.
E N D
第七讲8086/8088指令系统(续)2006年10月31号(星期二)第七讲8086/8088指令系统(续)2006年10月31号(星期二) 课前复习指令系统: 1 .MOV DS,2010H ;错 不能将立即数直接给段寄存器 2 .PUSH AL ;错 不能对字节进行堆栈操作 3 .MOV DX, [SP] ;错 无[SP]寻址方式,存储器地址 只能通过BX,BP,SI,DI寻址 4 .IN AL,0A00H ;错 端口地址大于FFH 应用DX寻址端口 5 .XCHG CL,CH ;对
6 .AAA CX ;错 AAA为无操作数指令,默认操作数AL 7 .ADD [BP+DI],[1000H] ;错 两个操作数不能均为存储器 8 .OUT DX,CL ;错 端口只能通过AL或AX传送数据 9.CBW BH ;错 符号扩展命令为无操作数指令, 默认操作数AL 10.ADD 03ECH,AX ;错 目的操作数不能为立即数 11.MOV BX,[SP+DI];错 无[SP+DI]寻址,必须是基址 (BX或BP)+变址(SI或DI) 12.MOV DI,[AX] ;错 无[AX]寻址
13.LDS CH,[DI] ;错 LDS指令目的操作数应为一个16为寄存器 14.LEA BX,1000H ;错 LEA源操作数应为一个存储器操作数, 不能是立即数 15.DIV 0010H ;错 单操作数不能是立即数 16.LEA DX,DI ;错 LEA源操作数应为一个存储器操作数, 不能是寄存器 17.MUL AX,200H ;错 MUL为单操作数指令, 且源操作数不能为立即数,AX隐含 18.MOV AX,[BX+BP];错 无[BP+BX]寻址,理由同第12题
19.CMP [BX],[SI] ;错 双操作数不能均为存储器 21.OUT DX,BX ;错 端口只能通过AL或AX传送数据 22.AND 0FH,AL ;错 目的操作数不能为立即数 23.JNZ AAA ;错 AAA十一条指令.不能作为符号地址
00 H 0000 0000 B - 80 H - 1000 0000 B 1 1 80H 1000 0000B • 例1 复习求补指令:MOV AH, 80H • NEG AH 执行后: (AL)=80H , CF=1,OF=1,ZF=0,SF=1,AF=0,PF=0
条件转移指令 判断条件 JB next CF = 1 低于 JBE next CF = 1 ZF = 1 低于或等于 或 JA next CF = 0 ZF = 0 高于 且 JAE next CF = 0 高于或等于 例2:复习比较指令: CMP oprd1, oprd2 ; (oprd1) - (oprd2) • 比较指令CMP,进行两操作数相减操作, 但只影响标志值,不影响操作数(减的结果不保存) • 利用CMP执行后的标志值,比较两操作数之间的关系 CMP A, B 有符号数小于用JL,大于用JG
CMP A,B • 例 将AX和BX中较大的带符号数,存于AX中 • CMP AX, BX ;比较 • JGE great ;大于或等于则跳转 • XCHG AX, BX ;小于则交换 • great: 、、、
CMP指令应用举例:带符号数找最大值 • 若自BLOCK开始的内存缓冲区中,有100个带符号数。 • 找出最大值。并存放到MAX单元中。 • 思路: • 第一个数取出( AX), • 取出第二个数(第二个字单元内容)与(AX)比较 : • (AX)>第二个数,不做交换, • 否则,(第二个字单元内容) (AX)。 • 再取第三个数, • … • 经过99次比较,在(AX)中得到最大数。 • …
编程: MOV BX,OFFSET BLOCK MOV AX,[BX] INC BX INC BX MOV CX,99 AGAIN:CMP AX,[BX] JG NEXT;(AX) 大,转NEXT MOV AX,[BX] NEXT: INC BX INC BX DEC CX JNZ AGAIN MOV MAX,AX ;MAX单元存放最大值
8086/8088指令系统(续) 8086/8088指令系统可以分成6个功能组: 1. 数据传送(Data transfer) 2. 算术运算(Arithmetic) 3. 逻辑运算和移位指令(Logic& Shift) 4. 串操作(String manipulation) 5. 控制转移(Control Transfer) 6. 处理器控制(Processor Control)
三. 逻辑运算指令 逻辑指令指令分类 AND OR XOR NOT TEST 逻辑运算 、 、 、 、 位 SHL 、 SAL 、 SAR SHR 移 、 ROL 、 ROR 、 RCL RCR 循环移位 、
1.逻辑运算指令 • AND AL , 0000 1111B • OR BX , 00FFH • NOT CL • XOR DL, AL • TEST AL, 0000 0001B 置CF、OF为0,AF不定 ( 无意义 ) SF、ZF、PF据结果置位 其他指令 • 除NOT指令单操作数外,其它均为双操作数 • 可进行字节或字操作 • NOT指令不影响标志 • TEST为“与”操作,但只影响标志位,不影响操作数。
以“与”指令为例,讨论注意事项: • “与”指令中操作数不能同时为存储器; • 影响条件码: CF=0F=0, AF未定义 , SF ZF PF • ↕ ↕ ↕ • “与”指令的用途: • (1) 清CF , 自己“与”自己. 操作数不变 ,CF=0 • 例:AND AL,AL ; 结果:操作数不变 ,CF=0。 • (2) 使操作数中若干位保持不变,若干位与“1”相与; • 而若干位置为“0 “的场合,若干位与“0” 相与。 • 例:若(AL)=43H • AND AL, 0FH ; (AL)=03H, (AL)0~3不变; • ;(AL)4~7=00H,屏蔽高4位。
1 CL SHL oprd, CF 0 1 CL SAL oprd, CF 0 1 CL SHR oprd, 0 CF 1 CL CF SAR oprd, 2. 移位指令 指令格式 执行操作 左移部分逻辑移位与算术移位
指令格式 执行操作 1 CL CF ROLoprd, 1 CL CF RORoprd, 1 CL CF RCLoprd, 1 CL CF RCRoprd, 3. 循环移位指令 循环移位分带进位与不带进位两种
共同点: • 所有移位指令都可以作B/W操作。 • 指令中的 dest : 寄存器、存储器寻址方式。 • cnt : 表示移位次数 • cnt=1,1可写在指令中,不能是1以外的常数。 cnt>1,用CL存放移位次数 ,不能是其他寄存器。 • 如: SAL AX,1 • MOV CL,4 • SAL AX,CL
注意事项: • SHL AL, 1 • SHR AL, CL • ROL BX, 1 • RCR AL, CL • 源操作数为移位的次数 • 为1可在指令中直接给出 • 大于1时,移位次数需由CL给出 • RCR AX,5 SHL BL, AL • 目的操作数类型决定操作类型 • SAL BL,CL 字节操作 • ROL BX,CL字操作 • oprd可以是reg/mem • 可进行字节或字操作 当移位次数
循环移位指令(Rotate)与移位指令(Shift)不同点:循环移位指令(Rotate)与移位指令(Shift)不同点: • 移位指令执行后,移出的位可能丢失; 循环移位指令移位后,操作数中原来各数位的信息不会丢失,这是移动了位置,必要时可以恢复。 • 循环移位指令可以对操作数进行测试。 • 例:测试(AL)5 =? 0 • MOV CL , 3 • ROL AL , CL • JNC ZERO • … • ZERO: … • …
利用带进位循环移位指令将两个寄存器或存储器单元利用带进位循环移位指令将两个寄存器或存储器单元 • 组合起来一起移位。 • 例: 将DX、AX组合起来构成32位寄存器向左移一位。 • 如下图所示: 32位寄存器向左移一位 程序: SHL AX , 1 RCL DX , 1
四、串操作指令(String manipulation ) “串”就是内存中一段地址相连的字节或字。 串操作—对串中各项进行操作,也叫数据块操作。 串操作指令是8088实现内存之间数据传送的一组指令 8088有5种基本操作: 1、 MOVS(Move string) 串传送指令 2、CMPS(Compare string) 串比较指令 3、SCAS(Scan string) 串扫描指令 4、LODS(Load from string) 串取数指令 5、STOS (Store in to string) 存入串数据指令
共同点: • 可以只有源操作数,可以只有目标操作数,可能二者都有。 • 源操作数用SI 寻址,隐含DS值为段地址,可以用段跨越前缀指定其它段。 • 目标操作数用DI寻址,隐含ES为段地址。 • 每次操作对SI、DI 调整: • DF=1,DI、SI自动-1 (字节)或-2(字); • DF=0,DI、SI自动+1(字节)或+2(字)。 • 与上述指令基本配合使用前缀有: • REP(Repeat)重复。 • REPE/REPZ(Repeat while equal/zero) 相等/为零则重复。 • REPNE/REPNZ(Repeat while not equal/not zero)不相等/不为零则重复。
下面分二种情况来讨论: • (一) 与REP相配合工作的MOVS、STOS指令 • REP 重复串操作直到(CX)=0为止 • LODS指令一般不直接与REP联合使用,但其操作与STOS相关,因而放在这里。 • (二) 与REPE/REPZ和REPNE/REPNZ联合工作的CMPS和SCAS指令 • REPE/REPZ 当相等/为零时重复串操作 • REPNE/REPNZ 当不相等/不为零时重复串操作
(一) 与REP相配合工作的MOVS、STOS指令 • REP 重复串操作直到(CX)=0为止 • 格式:REP String Primitive 串指令 • String Primitive 可为:MOVS、STOS。 • MOVS(Move String) 串传送 • LODS(Load from String) 读串指令 • STOS(Store into String) 写串指令
REP 重复串操作执行过程: • (1)当(CX)= 0 ,结束REP, • 执行REP后的下一条指令。 • (2) 当(CX)≠0, • (CX) (CX) -1, • (3) 执行REP后的串指令, • (4) 重复(1)~(3)。 REP 执行流程图
MOVS(Move string)串传送 • 串传送有3种格式: • (1) MOVS dest,src;((ES):(DI)←((DS):(SI)) • MOVSB (字节);(SI)←(SI)±1,(DI)←(DI) ±1 • MOVSW (字);(SI)←(SI)±2,(DI)←(DI)±2 • 当方向标志 CLD , DF=0时 用“+” • STD , DF=1时 用“-” • 该指令不影响条件码 。 • *如: MOVS ES:BYTE PTR [DI],DS:[SI] • * MOV单指令不能完成 存储单元之间的数据传送; • MOVS指令就是为解决 存储单元之间数据传送而设置的。
例:将内存的数据段中以AREA1为首地址的100个数据,传送到附加段中的AREA2为首地址的区域。例:将内存的数据段中以AREA1为首地址的100个数据,传送到附加段中的AREA2为首地址的区域。 用MOVS串操作指令编程: MOV AX,SEG AREA1 MOV DS,AX MOV AX,SEG AREA2 MOV ES,AX MOV SI,OFFSET AREA1 MOV DI,OFFSET AREA2 MOV CX,100 CLD ; DF=0,增址传送 REP MOVS ES:BYTE PTR[DI], DS:[SI]
应用MOV指令编程: MOV AX,SEG AREA1 MOV DS,AX MOV AX,SEG AREA2 MOV ES,AX MOV SI,OFFSET AREA1 ;将ARE1偏移地址→SI MOV DI,OFFSET AREA2 MOV CX,100 LOOP1:MOV AL,[SI] ; (AL)←((DS):(SI)) MOV ES:[DI],AL ;((ES):(DI))←(AL) INC SI INC DI DEC CX JNE LOOP1
归纳在执行MOVS指令时,应该先做好以下准备工作:归纳在执行MOVS指令时,应该先做好以下准备工作: (1) 数据段中源串首地址(如反向传送到末地址)存入SI寄存器中。 (2) 附加段中目的串首地址(或反向传送末地址)存入DI寄存器中。 (3) 数据串长度存入CX寄存器。 (4) 建立方向标志 建立方向标志介绍两条指令: · CLD(clear direction flag) 功能:DF=0,执行串处理指令时 可以使地址自动+1或+2。 · STD(set direction flag) 功能:DF=1,执行串处理指令时可以使地址自动-1或 -2。
LODS(Load from string)读串指令 • 读串指令有3种格式: • LODS src;(字节)(AL) ((DS):(SI)), (SI) (SI) ±1 • (字)(AX) ((DS):(SI)),(SI) (SI)±2 • LODS B (字节);(AL) ((DS):(SI)),(SI) (SI) ±1 • LODS W (字) ;(AX) ((DS):(SI)),(SI) (SI)±2 • 功能:该指令把由(SI)指定的数据段中某单元内容 (AL) • 或 (AX)中。 • DF=0,(SI)← (SI)+1或+2 • DF=1,(SI) ←(SI)-1或-2
LODS应用注意: • (1) 指令允许用段跨越前缀来指定非数据段的存储区。 • (2) 该指令不影响条件码。 • 一般说来, • 它不与REP联用,每重复一次,累加器的内容就改变一次。 • (AL)中只能保持最后一个元素。 • 有时缓冲区中的一串字符需要多次取出测试时可用本指令。 • 适用于在一个循环中,用基本串操作指令构成复杂串操作时很有用。
3 STOS(Store into string) 存入串指令 • 将(AL)或(AX) ((ES):(DI)),(DI) ±1或±2(DI) • 存入串指令有3种格式: • STOS dest;(字节) ((ES):(DI)) (AL) , (DI) (DI) ±1 • (字) ((ES):(DI)) (AX) , (DI) (DI) ±2 • (2) STOS B (字节); ((ES):(DI)) (AL) , (DI) (DI) ±1 • (3) STOS W (字) ; ((ES):(DI)) (AX) , (DI) (DI) ±2 • 用途: • 与REP联用时,(CX)←缓冲区长度。用来建立一串相同的值,初始清零。
例:在附加段STORE开始存5个空格 程序: MOV AL,20H ;‘_’ (AL) MOV CX,5 MOV DI,offset STORE CLD REP STOSB ;((ES):(DI)) (AL) (DI) (DI)+1
学习LODS,STOS指令应用 例:内存中有一个首地址为BLOCK补码表示的有符号数的数据块。 要求将正、负数分开,分别存于二个缓冲区: 存放正数的缓冲区首址为PUOS-DATA, 存放负数的缓冲区首址为MINUS-DATA。 设: 源数据块用SI寻址, 正数的目的区用DI寻址, 负数的目的区用BX寻址。 循环次数 ( CX )。
传送过程: • 用LODS指令把源数据取入(AL)中, • 检查其符号,确定正、负, • 若为正数用STOS指令送至正数缓冲区, • 若是负数,把(DI)与(BX)交换,仍使用STOS传送, • 传送 完后再 将(DI)与(BX)交换,恢复原值。
程序:START: MOV SI,OFFSET BLOCK ; 数缓串位置 MOV DI,OFFSET PUOS-DATA ; 正数缓冲区 MOV BX,OFFSET MINUS-DATA ;负数缓冲区 MOV CX,COUNT CLD GOON: LODS TEST AL,80H JNZ MINS ;若非0,为负数转MINS STOS B;正数 ,(DI)←(AL),(DI)←(DI)+1 JMP AGAIN MINS: XCHG BX,DI STOSB ;负数 ,(DI)←(AL),(DI)←(DI)+1 XCHG BX,DI AGAIN:DEC CX JNZ,GOON HLT
(二) 与REPE/REPZ和REPNE/REPNZ联合工作的CMPS和SCAS指令 • REPE/REPZ 当相等/为零时重复串操作 • 格式:REPE(或REPZ)string primitive • 当相等时的重复前缀REPZ • String primitive可用于 : CM PS , SCAS • 1、CM PS(Compare string ) 串比较指令 • 2、SCAS (Scan string ) 串扫描指令,搜索指令
执行过程: • 当(CX)= 0 , 结束REPZ, • 执行REPZ下一条指令; • (2) 当(CX)≠0,将CX 的内容减1, • 执行REPZ后的串指令; • (3) 当ZF = 1, 返回 (1) ; • (4) 当ZF≠1, 则结束REPZ • 执行REPZ下一条指令。 • 注意: • ◆ (CX)减1操作不影响标志 • ◆ ZF标志由串操作决定 • ◆ 当 (CX) = 0或ZF=0时退出循环 REPZ执行流程
REPNE/REPNZ 当不相等/不为零时重复串操作 • 格式:REPNE(或REPNZ)string primitive • 当不相等重复前缀REPNZ • string primitiveString primitive可为 : CM PS , SCAS • 1、CM PS(Compare string ) 串比较指令 • 2、SCAS (Scan string ) 串扫描指令,搜索指令
执行过程: • 当(CX )= 0 , 结束REPNZ, • 执行REPNZ下一条指令。 • (2) 当(CX)≠0,将CX 的内容减1, • 执行REPNZ后的串指令。 • (3) 当ZF = 0, 返回(1); • 当ZF≠0, 则结束REPNZ, • (4) 执行REPNZ下一条指令。 • 注意: • ◆ (CX)减1操作不影响标志 • ◆ ZF标志由串操作决定 • ◆ 当 (CX) = 0或ZF=1时退出循环 REPNZ执行流程
1、CMPS(Compare string ) 串比较指令 • (SI)—作为源串地址,(DI)—目的串地址 • 串比较指令有3种格式: • (1) CMPS dest,src;((ES) :(DI) -(DS):(SI)),结果不存,置标志 • CMPS B (字节);(SI) (SI)±1,(DI)←(DI) ±1 • CMPS W (字);(SI) (SI)±2,(DI) (DI)±2 • 执行操作: • ((ES) :(DI) -(DS):(SI)),结果不存,置标志。 • 字节操作:(SI) (SI)±1,(DI)←(DI) ±1 • 字操作:(SI) (SI)±2,(DI) (DI)±2 • 注意:两数相减,只影响标志,不影响操作数。 • 其它操作规定与MOVS同。
学习REPZ CMPSB指令 例:利用CMPS指令对STRING1和STRING2二个字符串进行 比较,比较结果相同在RESULT 单元送00H,不同送0FFH。 MOV SI,OFFSET STRING1 MOV DI,OFFSET STRING2 MOV CX,COUNT CLD REPZ CMPSB;相等时继续比较 JNZ UNMAT ;若串不同,在RESUL单元中置0FFH MOV AL,0 ;若串相等,在RESULT单元中置00H JMP OULPT UNMAT:MOV AL,0FFH OUTPT: MOV RESULT,AL HLT
2、SCAS (Scan string ) 串扫描指令,搜索指令 (DI)—字符串起始地址,(AL)或(AX) — 关键字 串扫描指令有3种格式: 格式:SCAS dest SCASB(字节);(AL)-((ES):(DI)),(DI)(DI)±1 SCASW(字);(AX)-((ES):(DI)),(DI) (DI)±2 注意: (AL)或(AX) - 目的串 两数相减,只影响标志,不影响操作数。 其它特性与MOVS同。
REP NE SCASB指令应用。 例:要搜索的关键字 放在(AL)或(AX)中,搜索某一数据块或字符串中有无关 键字,若有,且记录关键字地址;若判断结果为0转出,表示找到关键字;若计数器为0,表示没有要搜索的关键字。 MOV DI,0FFSET BLOCK;设置数据块地址指针 MOV CX,COUNT ;设置数据块长度 CLD MOV AL,CHAR ; 关键字送入AL或AX REP NE SCASB ;(CX)≠0,Z=0 继续SCASB JZ FOUND;Z=1,结果为0,表示比较相等,找到关键字 JMP DONE ;此处是没有找到必须完成的工作。 。。。。。。 HLT
应用举例: • 例:一个数据块由大小写英文字母、数字、其他符号组成, • 用CR(ASCII码0DH)结束。数据块首地址为BLOCK1。 • 将其传送到BLOCK2为首地址的内存区,并将英文中小 写英文字母(a~z)转换成大写英文字母(A~Z),其余不变。 • 分析: • 大小写英文字母中相应ASCII码的关系: • ‘a’~’z’相应ASCII码为: 61H~7AH • ‘A’~’Z’相应ASCII码为:41H~5AH • 英文中小写英文字母(a~z)转换成大写英文字母(A~Z): • 只要将小写的ASCII码减去20H即可。 • 程序和流程图如下:
程序: LEA SI , BLOCK1 LEA DI , BLOCK2 CLD NEXT: LODSB CMP AL , 0DH JZ DONE CMP AL , 61H JC OK CMP AL , 7BH JNC OK SUB AL , 20H OK: STOSB JMP NEXT DONE: HLT 流程图
小结:串操作指令重复前缀,操作数,地址指针小结:串操作指令重复前缀,操作数,地址指针
作业:1.继续上次作业 2.内存中有一个首地址为BLOCK单字节补码表示的有符号数的数据块。 要求将正、负数分开,分别存于二个缓冲区: 存放正数的缓冲区首址为PUOS-DATA, 存放负数的缓冲区首址为MINUS-DATA。 预习内容:复习控制转移指令和处理器控制指令