1 / 58

第五章 循环与分支程序设计

第五章 循环与分支程序设计. §5.1 循环与转移指令 §5.2 循环程序设计 §5.3 分支程序设计. §5.1 循环与转移指令. 一、循环控制指令 二、转移指令. 控制转移类指令通过改变 IP( 和 CS) 值,实现程序执行顺序的改变. 一、循环控制指令. 8086指令系统的循环控制指令均为二字节指令 一字节为转移的相对位移量(8位带符号的二进制数) IP ← IP+ 相对位移量 EIP ← EIP+ 相对位移量 隐含使用 CX 作为循环计数器. 短转移. 程序中的某段需反复执行若干次时,用循环来实现. 一、循环控制指令.

ama
Télécharger la présentation

第五章 循环与分支程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第五章 循环与分支程序设计 • §5.1 循环与转移指令 • §5.2 循环程序设计 • §5.3 分支程序设计

  2. §5.1 循环与转移指令 一、循环控制指令 二、转移指令 • 控制转移类指令通过改变IP(和CS)值,实现程序执行顺序的改变

  3. 一、循环控制指令 • 8086指令系统的循环控制指令均为二字节指令 • 一字节为转移的相对位移量(8位带符号的二进制数) IP ← IP+相对位移量 EIP ← EIP+相对位移量 • 隐含使用CX作为循环计数器 短转移 • 程序中的某段需反复执行若干次时,用循环来实现

  4. 一、循环控制指令 LOOP label ;CX←CX-1,CX≠0,循环到标号label LOOPE/LOOPZ label ;CX←CX-1,CX≠0 且ZF=1,循环到标号label 等于时循环 不等于时循环 LOOPNE/NZ label ;CX←CX-1,CX≠0且ZF=0,循环到标号label

  5. 一、循环控制指令(例) MOV CX,COUNT ;设置循环次数 MOV SI,OFFSET DATA_BYTE XOR AX,AX ;BX清0,用于存放累加和 AGAIN: ADD AL,[SI] ADC AH,0 INC SI LOOP AGAIN ;计数器减1,不为0继续循环

  6. 一、循环控制指令(例) MOV CX,COUNT ;设置循环次数 MOV SI,OFFSET STRING XOR BX,BX ;BX清0,用于记录空格数 MOV AL,20H AGAIN: CMP AL,[SI] JNZ NEXT ;ZF=0,非空格,转移 INC BX ;ZF=1,是空格,个数加1 NEXT: INC SI LOOP AGAIN ;计数器减1,不为0继续循环

  7. 二、转移指令 • 无条件转移指令 • 条件转移指令

  8. 目的地址与JMP属同一逻辑段,只修改IP值 从一个代码段转移到另一个代码段,CS和IP都会被修改 无条件转移指令 JMP label ;程序转向label标号指定的地址 NEAR FAR • 只要执行无条件转移指令JMP,就使程序转到指定的目标地址处,从目标地址处开始执行那里的指令 • JMP指令分成4种类型: ⑴ 段内转移、直接寻址 ⑵ 段内转移、间接寻址 ⑶ 段间转移、直接寻址 ⑷ 段间转移、间接寻址

  9. 1.无条件转移指令—目标地址的寻址方式 • 直接寻址方式 • 转移地址象立即数一样,直接在指令的机器代码中,就是直接寻址方式 • 间接寻址方式 • 转移地址在寄存器或主存单元中,就是通过寄存器或存储器的间接寻址方式 用标号表达 用寄存器或存储器操作数表达

  10. 代码段 代码段 1.无条件转移指令—目标地址的范围:段内 • 段内转移——近转移(near) • 在当前代码段64KB范围内转移( ±32KB范围) • 不需要更改CS段基值,只要改变IP偏移地址 • 段内转移——短转移(short) • 转移范围可以用一个字节表达,在段内-128~+127范围的转移

  11. 代码段 代码段 1.无条件转移指令 —目标地址的范围:段间 • 段间转移——远转移(far) • 从当前代码段跳转到另一个代码段,可以在1MB范围 • 需要更改CS段基值和IP偏移地址 • 目标地址必须用一个32位数表达,叫做32位远指针,它就是逻辑地址 • 实际编程时,汇编程序会根据目标地址的距离,自动处理成短转移、近转移或远转移 • 程序员可用操作符short、near ptr 或far ptr 强制

  12. 段内直接寻址转移 实际为相对寻址 JMP label ;IP←IP+位移量 • 位移量是紧接着JMP指令后的那条指令的偏移地址,到目标指令的偏移地址的地址位移 • 当向地址增大方向转移时,位移量为正;向地址减小方向转移时,位移量为负 JMP AGAIN ;转移到AGAIN处继续执行 …… AGAIN: DEC CX ;标号AGAIN的指令 …… JMP OUTPUT ;转向OUTPUT …… OUTPUT: MOV RESULT,AL ;标号OUTPUT的指令

  13. 段内间接寻址转移 JMP r16/m16 ;IP←r16/m16 • 将一个16位寄存器或主存字单元内容送入IP寄存器,作为新的指令指针,但不修改CS寄存器的内容 JMP AX ;IP←AX JMP WORD PTR [BX] ;IP←[BX]

  14. 段间直接寻址转移 JMP far ptr label ;IP←label的偏移地址 ;CS←label的段基值 • 将标号所在段的段基值作为新的CS值,标号在该段内的偏移地址作为新的IP值;程序跳转到新的代码段执行 JMP FAR PTR OTHERSEG ;远转移到代码段2的otherseg

  15. 段间间接寻址转移 JMP far ptr mem ;IP←[mem],CS←[mem+2] • 用一个双字存储单元表示要跳转的目标地址。这个目标地址存放在主存中连续的两个字单元中的,低位字送IP寄存器,高位字送CS寄存器 MOV WORD PTR [BX],0 MOV WORD PTR [BX+2],1500H JMP FAR PTR [BX] ;转移到1500H:0

  16. 2.条件转移指令 Jcc label ;条件满足,发生转移:IP←IP+8位位移量 ;条件不满足,顺序执行 • 指定的条件cc如果成立,程序转移到由标号label指定的目标地址去执行指令;条件不成立,则程序将顺序执行下一条指令 • 操作数label是采用短转移,称为相对寻址方式

  17. 2.条件转移指令 • Jcc指令的操作数label是一个标号 • 一个8位位移量是相对于当前IP的,且距当前IP地址-128~+127个单元的范围之内,属于段内短距离转移 • Jcc指令为2个字节,条件不满足时的顺序执行就是当前指令偏移指针IP加2

  18. 2.条件转移指令—指令的分类 • Jcc指令不影响标志,但要利用标志。 • 根据利用的标志位不同,19条指令分成4种情况: ⑴ 判断单个标志位状态 ⑵ 比较无符号数高低 ⑶ 比较有符号数大小 ⑷ 判断计数器CX为0

  19. 实际虽然指令只有19条,但却有31个助记符 • 采用多个助记符,只是为了方便记忆和使用

  20. 判断单个标志位状态 这组指令单独判断5个状态标志之一 ⑴JZ/JE和JNZ/JNE:利用零标志ZF,判断结果是否为零(或相等) ⑵JS和JNS:利用符号标志SF,判断结果是正是负 ⑶JO和JNO:利用溢出标志OF,判断结果是否产生溢出 ⑷JP/JPE和JNP/JPO:利用奇偶标志PF,判断结果中“1”的个数是偶是奇 ⑸JC和JNC:利用进位标志CF,判断结果是否进位或借位 例 题 例 题 例 题 例 题 例 题

  21. 2.条件转移指令— JZ/JNZ指令 REPZ CMPSB ;重复比较两个字符 JNZ UNMAT;ZF=0(不等),转移 MOV AL,0 ;顺序执行(相等) JMP OUTPUT UNMAT: MOV AL,0FFH OUTPUT: MOV RESULT,AL REPZ CMPSB ;重复比较两个字符 JZ MAT ;ZF=1(相等),转移 MOV AL,0FFH ;顺序执行(不等) JMP OUTPUT MAT: MOV AL,0 OUTPUT: MOV RESULT,AL

  22. 2.条件转移指令— JS/JNS指令 • 计算|X-Y|(绝对值)。X和Y为存放于X单元和Y单元的16位操作数,结果存入RESULT。 MOV AX,X SUB AX,Y JNS NONNEG NEG AX NONNEG: MOV RESULT,AX

  23. 2.条件转移指令— JO/JNO指令 • 计算X-Y。X和Y为存放于X单元和Y单元的16位操作数,若溢出,则转移到OVERFLOW处理 MOV AX,X SUB AX,Y JO OVERFLOW ... ;无溢出,结果正确 OVERFLOW: ... ;有溢出处理

  24. 2.条件转移指令— JP/JNP指令 • 设字符的ASCII码在AL寄存器中。将字符加上奇校验位:在字符ASCII码中为“1”的个数为奇数时令其最高位为“0”,否则令最高位为“1” AND AL,7FH;最高位置“0”,同时判断“1”的个数 JNP NEXT ;个数已为奇数,则转向NEXT OR AL,80H;否则,最高位置“1” NEXT: ...

  25. 2.条件转移指令— JC/JNC指令 • 记录BX中1的个数 XOR AL,AL ;AL=0,CF=0 AGAIN: TEST BX,0FFFFH ;等价于 CMP BX,0 JZ NEXT SHL BX,1 JNC AGAIN INC AL JMP AGAIN NEXT: ... ;AL保存1的个数

  26. 2.条件转移指令 —无符号数的比较 • 无符号数的大小用高(Above)低(Below)表示 • 利用CF确定高低、利用ZF标志确定相等(Equal) • 两数的高低分成4种关系: ⑴高于(不低于等于): JA( JNBE ) ⑵高于等于(不低于): JAE( JNB ) ⑶低于(不高于等于): JB(JNAE) ⑷低于等于(不高于): JBE(JNA)

  27. 2.条件转移指令—无符号数的比较(例) CMP AX,BX ;比较AX和BX JAE NEXT ;若AX≥BX,转移 XCHG AX,BX ;若AX<BX,交换 NEXT: ... 结果:AX保存较大的无符号数

  28. 2.条件转移指令 —有符号数的比较 • 有符号数的大(Greater)小(Less)需要组合OF、SF标志,并利用ZF标志确定相等(Equal) • 两数的大小分成4种关系: • ⑴ 小于(不大于等于):JL(JNGE) • ⑵小于等于(不大于):JLE(JNG) • ⑶大于(不小于等于): JG( JNLE ) • ⑷大于等于(不小于): JGE( JNL )

  29. 2.条件转移指令 —有符号数的比较(例) CMP AX,BX ;比较AX和BX JGE NEXT ;若AX≥BX,转移 XCHG AX,BX ;若AX<BX,交换 NEXT: ... 结果:AX保存较大的有符号数

  30. 2.条件转移指令—计数器CX为0转移 JCXZ label ;CX=0,发生转移:IP←IP+8位位移量 ;CX≠0,顺序执行 • CX寄存器通常在程序中用做计数器 • JCXZ指令用来判断计数是否为0

  31. §5.2 循环程序设计 一、循环程序的结构形式 二、循环程序设计 三、多重循环程序设计

  32. 初始化 循环的初始状态 循环体 循环的工作部分 及修改部分 修改部分 计数控制循环 条件控制循环 Y 控制条件 N 结束 一、循环程序的结构形式 先循环,后判断

  33. 初始化 循环的初始状态 N 计数控制循环 条件控制循环 控制条件 Y 结束 循环体 循环的工作部分 及修改部分 修改部分 一、循环程序的结构形式 先判断,后循环

  34. 二、循环程序设计(例) xor ax,ax ;被加数ax清0 mov cx,100 again: add ax,cx ;从100,99,...,2,1倒序累加 loop again .model small .stack 256 .data sum dw ? .code .startup mov sum,ax ;将累加和送入指定单元 .exit 0 end

  35. 开始 1的个数计数器←0 循环次数计数器CX←16 Y左移一次 N CF=1 Y 1的个数计数器+1 N CX ←CX-1=0 Y COUNT ←1的个数计数器 结束 例5.2 在ADDR单元存放着数Y的地址,试编制一程序把Y中1的个数存入COUNT单元中 循环次数固定,完全由循环计数器控制

  36. 例5.2 REPEAT: SHL AX,1 JNC NEXT INC DL NEXT: LOOP REPEAT EXIT0: MOV COUNT,DL MOV AH,4CH INT 21H CODE ENDS END START DATA SEGMENT Y DW 1234H ADDR DW Y COUNT DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV DL,0 MOV BX,ADDR MOV AX,[BX] MOV CX,16

  37. 开始 1的个数计数器←0 循环次数计数器CX←16 Y Y=0 N Y左移一次 Y N CF=1 1的个数计数器+1 N CX ←CX-1=0 Y COUNT ←1的个数计数器 结束 例5.2

  38. 例5.2 REPEAT: SHL AX,1 JNC NEXT INC DL NEXT: LOOP REPEAT EXIT0: MOV COUNT,DL ADD DL,30H MOV AH,2 INT 21H MOV AH,4CH INT 21H CODE ENDS END START CMP AX,0 JZ EXIT0 DATA SEGMENT Y DW 1234H ADDR DW Y COUNT DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV DL,0 MOV BX,ADDR MOV AX,[BX] MOV CX,16 JMP REPEAT

  39. HEAD END -1, 23, 37, 49, 52 32, 23, 37, 49, 52 32 • 循环结束的控制: 执行插入操作后结束循环 • 例5.4 将正数N插入一个已升序排列的字数组的正确位置。该数组的首地址和末地址分别为ARRAY_ HEAD 和ARRAY_ END,其中所有的数均为正数。 -1, 解法一: • 从数组的尾部开始比较 N较大,则在比较对象后插入,结束循环 N较小,则把比较对象及其后元素后移一个字 • 若N比所有元素都小,扫描整个数组后仍无法结束循环,将-1加在数组前可解决该问题

  40. 开始 (ARRAY_HEAD-2)←-1 初始化变址寄存器SI Y K<=N N 将N放在K的后面 K后移一个字单元 结束 修改地址 例5.4

  41. 例5.4 MOV AX,N MOV ARRAY_HEAD-2,-1 MOV SI,0 COMP:CMP ARRAY_END[SI],AX JLE INSERT MOV BX,ARRAY_END[SI] MOV ARRAY_END[SI+2],BX SUB SI,2 JMP COMP INSERT: MOV ARRAY_END[SI+2],AX RET MAIN ENDP PROGRAM ENDS END START DATAREA SEGMENT X DW ? ARRAY_HEAD DW 3,5,15,23,37,49 ARRAY_END DW 105 N DW 32 DATAREA ENDS PROGRAM SEGMENT MAIN PROC FAR ASSUME CS:PROGRAM,DS:DATAREA START: PUSH DS SUB AX,AX PUSH AX MOV AX,DATAREA MOV DS,AX MOV BX,ARRAY_END[SI] CMP BX,AX JLE INSERT

  42. 例5.4 将正数N插入一个已升序排列的字数组的正确位置。该数组的首地址和末地址分别为ARRAY_ HEAD 和ARRAY_ END,其中所有的数均为正数。 解法二: • 从数组的头部开始比较 N较小,则在比较对象前插入,结束循环 N较大,则把比较对象及其前元素前移一个字 可扫描整个数组,循环次数为数组元素个数 执行插入操作后结束循环 • 循环结束的控制: • 若N比所有元素都小,形成新的头;若N比所有元素都大,则被置于尾部

  43. MOV AX,N MOV SI,0 MOV CX,COUNT REPEAT: MOV BX,ARRAY_HEAD[SI] CMP BX,AX JAE INSERT ;N较小,则转插入操作 MOV ARRAY_HEAD[SI-2],BX ;数组元素前移1字单元 INC SI INC SI LOOP REPEAT INSERT: MOV ARRAY_HEAD[SI-2],AX ;将N加入到数组中 MOV AX,4C00H INT 21H MAIN ENDP CSEG ENDS END MAIN ;SET ENTRY POINT DSEG SEGMENT PARA 'DATA' DW ? ARRAY_HEAD DW 3,5,13H,23H,37H DW 49H,52H,65H,78H,99H,105H COUNT EQU ($-ARRAY_HEAD)/2 N DW 32H DSEG ENDS CSEG SEGMENT PARA 'CODE' ASSUME CS:CSEG ASSUME DS:DSEG,SS:SSEG MAIN PROC FAR ;MAKE NECCESSARY INITALIZALITION MOV AX,DSEG MOV DS,AX MOV ES,AX

  44. 例5.5 设有数组X和Y,每个数组都有10个元素,完成以下计算: Z1=X1+Y1 Z2=X2+Y2 Z3=X3-Y3 Z4=X4-Y4 Z5=X5-Y5 Z6=X6+Y6 Z7=X7-Y7 Z8=X8-Y8 Z9=X9+Y9 Z10=X10+Y10 结果存入数组Z。 比例尺:0000000011011100B

  45. MOV BX,0 MOV CX,10 MOV DX,FLAG NEXT: MOV AX,X[BX] SHR DX ,1 JC SUBTRACT ADD AX,Y[BX] JMP RESULT SUBTRACT : SUB AX,Y[BX] RESULT : MOV Z[BX],AX ADD BX,2 LOOP NEXT MOV AH,4CH INT 21H CODE ENDS END START DATA SEGMENT X DW 11,33,10,60,4,7,19,80,45,23 Y DW 44,5,2,90,78,32,12,10,100,98 Z DW 10H DUP(?) FLAG DW 0000000011011100B DATA ENDS STK SEGMENT STACK DW 20H DUP(0) STK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STK START: MOV AX,DATA MOV DS,AX

  46. 三、多重循环程序设计 • 例5.7 有一个首地址为A的N字数组,请编制程序使该数组中的数按照从大到小的次序整序 • 冒泡法从第一个元素开始,依次对相邻的两个元素进行比较,使前一个元素不小于后一个元素;将所有元素比较完之后,最小的元素排到了最后;然后,除掉最后一个元素之外的元素依上述方法再进行比较,得到次小的元素排在后面;如此重复,直至完成就实现元素从大到小的排序 • 这需要一个双重循环程序结构

  47. 冒泡法的排序

  48. CSEG SEGMENT PARA ‘CODE’ ASSUME CS:CSEG, DS:DSEG,SS:SSEG MAIN PROC FAR ;MAKE NECCESSARY INITALIZALITION PUSH DS XOR AX,AX PUSH AX MOV AX,DSEG MOV DS,AX MOV ES,AX MOV CX,N DEC CX LOOP1: MOV DI,CX ;保存计数器 MOV BX,0 ;数组地址指针清零 LOOP2: MOV AX,A[BX] CMP AX,A[BX+2] JGE COTINUE XCHG A[BX+2],AX ;交换 MOV A[BX],AX COTINUE: ADD BX,2 ;修改数组指针 LOOP LOOP2 MOV CX,DI ;恢复循环计数器 LOOP LOOP1 RET MAIN ENDP CSEG ENDS END MAIN ;SET ENTRY POINT

  49. CSEG SEGMENT PARA ‘CODE’ ASSUME CS:CSEG, DS:DSEG,SS:SSEG MAIN PROC FAR ;MAKE NECCESSARY INITALIZALITION PUSH DS XOR AX,AX PUSH AX MOV AX,DSEG MOV DS,AX MOV ES,AX MOV CX,N DEC CX LOOP1: MOV DI,CX;保存计数器 MOV BX,0 ;数组地址指针清零 MOV DL,0 LOOP2: MOV AX,A[BX] CMP AX,A[BX+2] JGE COTINUE XCHG A[BX+2],AX ;交换 MOV A[BX],AX INC DL ;交换次数计数器+1 COTINUE: ADD BX,2 ;修改数组指针 LOOP LOOP2 CMP DL,0 JZ EXIT0 ;数组已整序,则退出 MOV CX,DI;恢复循环计数器 LOOP LOOP1 EXIT0: RET MAIN ENDP CSEG ENDS END MAIN ;SET ENTRY POINT

  50. §5.3 分支程序设计 一、分支程序的结构形式 二、分支程序的设计 三、跳转表

More Related