1 / 52

第五章 程序设计方法和上机调试

第五章 程序设计方法和上机调试. 5.1 程序设计方法 5.2 汇编语言上机调试过程. 5.1 程序设计方法. 编写汇编语言程序步骤 分析实际问题,抽象描述问题的模型 确定解决模型的算法 按算法画出程序流程图 按流程图编写程序 上机调试 , 运行程序. 判断程序质量的标准 程序的正确性 程序的可读性 程序的执行时间 程序所占内存大小. 流程图的组成. 执行框 判别框 开始结束框 连接点 指向线.

jude
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 汇编语言上机调试过程

  2. 5.1程序设计方法 • 编写汇编语言程序步骤 • 分析实际问题,抽象描述问题的模型 • 确定解决模型的算法 • 按算法画出程序流程图 • 按流程图编写程序 • 上机调试, 运行程序

  3. 判断程序质量的标准 • 程序的正确性 • 程序的可读性 • 程序的执行时间 • 程序所占内存大小

  4. 流程图的组成 执行框 判别框 开始结束框 连接点 指向线 用流程图表示算法直观形象,比较清楚地显示出各个框之间的逻辑关系。常用的还有N-S结构化流程图。程序编制人员都应当掌握传统流程图,会看会画。

  5. 顺序程序结构是一种最简单的程序结构。在流程图中,处理框一个接一个执行,既无分支,也无循环和转移。是一种简单的程序结构。顺序程序结构是一种最简单的程序结构。在流程图中,处理框一个接一个执行,既无分支,也无循环和转移。是一种简单的程序结构。 S 1 S2 S3 一、顺序结构

  6. 内存中TABLE开始存放0~9的平方值,通过人机对话,当任给定一个数X(0~9),查表得X的平方值,放在AL中。内存中TABLE开始存放0~9的平方值,通过人机对话,当任给定一个数X(0~9),查表得X的平方值,放在AL中。 例1: DATA SEGMENT TABLE DB 0,1,4,9,…81 BUF DB ‘Please input one number(0~9):’,0DH, 0AH, ‘$’ DATA ENDS STACK SEGMENT STACK ‘STACK’ DB 50 DUP (?) TOP LABEL WORD STACKENDS CODE SEGMENT MAIN PROC FAR ASSUME CS:CODE,DS:DATA,SS:STACK

  7. START: MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX MOV SP,OFFSET TOP MOV BX,OFFSET TABLE NEXT: MOV DX,OFFSET BUF MOV AH,9;输出提示 INT 21H MOV AH,1;键入一个数 INT 21H MOV AH,0 AND AL,0FH ADD BX,AX MOV AL,[BX] MOV AH,4CH INT 21H RET MAIN ENDP CODE ENDS END START

  8. 补充:有关字符、数码转换的处理 • 1.计算机处理字符时,常用的字符编码是ASCII 码。 • 2.数字和字母的ASCII码是一个有序序列 • 数字0~9 : 30H ~ 39H • 大写字母A~Z : 41H ~ 5AH • 小写字母a~z : 61H ~ 7AH

  9. 3.计算机处理信息时,其对象都是二进制数。 • 外设(显示器、打印机、键盘等) 用ASCII码与CPU进行信息传送。 • 例如: 1) 在键盘上按下某一字符键 (如’9’),键盘接口向 • 键盘缓冲区送去的是该字符的ASCII码(如39H), • 不是送数字09H。 • 2) 在文本方式下,要在显示器上显示某一字符(如’A’), • 须将该字符的ASCII码(如41H)送显示缓冲区, • 不是送数字0AH。 • 计算机要利用显示器、键盘等外设时,须据程序设计的需要进行有关转换。

  10. 将CPU运算的结果通过显示器显示时,如二进制数“A9” 需将结果转换成其对应的ASCII码才能进行显示。 CPU 运算后所得的二进制数 显示缓冲区 1 0 1 0 1 0 0 1 存放的内容 ( ASCII ) 字符的 码 十六进制形式显示 41 h 39 h , ’ A9 ’ 显示 2D h , 38 h , 37 h 31 h 36 h 39 h , , ’ 87 ’ 显示 - ’ 169 ’ 显示 十进制形式显示 ( 带符号数 ) ( 无符号数 ) 31 h, 30 h, 31 h, 30 h, 31 h, 30 h, 30 h, 31 h 二进制形式显示 ’ 10101001 ’ 显示

  11. 1234 ’ , 从键盘输入 缓冲区存放 CPU 处理时 31H, 32H, 33H, 34H 1234H 看作十六进制数输入 04D2H 看作十进制数输入 例 CPU要处理从键盘输入的某一数据,如键入“1234” 需将该数据串进行转换后才能应用。

  12. ? 例 将BX寄存器中的内容以十六进制形式显示出来。 • BX是一个16位寄存器 • 二进制 1010 1001 0011 1110 • 十六进制 A 9 3 E • 屏幕上的显示 ‘A’ ‘9’ ‘3’ ‘E’ 对应的ASCII 41H 39H 33H 45H • 用十六进制显示时,每4位用一个字符显示,共4个 • 其中 0000 →’0’ 30H , 1010 →’A’ 41H • 0001 →’1’ 31H, 1011 →’B’ 42H • 、、 、、 • 1001 →’9’ 39H, 1111 →’F’ 46H

  13. 算法: • 取出要显示的某4位,转换为对应的ASCII码, • 再调用DOS系统功能进行显示。 1) 对于0000~1001(0~9), 先扩展成一个字节,高4位清0, 加上30H后, 即可得字符’0’~’9’对应的ASCII码。 0000 0001B + 30H= 31H 0000 1001B + 30H=39H 0001B ‘1’ 1001B ‘9’ 2) 对于1010~1111(A~F), 先扩展成一个字节,高4位清0, 加上30H后, 还要再加上07H,才能得到’A’~’F’ 对应的ASCII码 0000 1010B+30H+07H = 41H 0000 1111B+30H+07H =46H 1010B ‘A’ 1111B ‘F’

  14. 开始 显示字符个数CH=4 循环移位次数CL=4 BX循环左移4位,将要显示的值移至低4位,保存在DL中 清DL 的高4位, 只保留要显示位的值 DL ← DL+30H 完成数值0~9的ASCII码转换 N DL超出39H? Y DL←DL+07H 完成数值A~F的ASCII码转换 用02功能显示DL中的字符 N CH←CH-1 结束? Y 返回DOS code SEGMENT ASSUME CS:code start: MOV CH, 4 ;字符个数 MOV CL, 4 ;循环移位次数 next: ROL BX, CL ;取显示位的值 MOV DL, BL;保存在DL中 AND DL, 0FH;清除高4位 ADD DL, 30H;转变为数字的ASCII CMP DL, 39H ;大于39H, 则应转变 JLE print ;为字母A~F的ASCII ADD DL, 07H print: MOV AH, 2H ;显示DL中的字符 INT 21H DEC CH ;显示结束? JNZ next MOV AH, 4CH ;返回DOS INT 21H code ENDS END start

  15. Y 1 (X>0) 0 (X=0) -1 (X<0) 1 X Y= -1 二、分支结构程序设计 1、 分支:分支程序结构要求程序在运行过程中需要根据不同的情况或条件作出判断,并转向相应的处理程序。分支是通过条件转移指令实现的。 例2:根据BUFFER中的数(X)对符号函数BX(Y)赋值。

  16. X→AX 并将AX的特征反映到FLAG Y JE (AX)=0? N N JNS (AX)<0? (AX)=0 (AX)>0 PLUS Y ZERO 1→BX 0FFH→BX 0→BX

  17. 初始化 A 取一字符送AL DH送内存 N (AL)≥30H Y N DL送内存 DH+1 (AL)>39H Y N AL=N-DH-DL (AL) ≥41H Y AL送内存 N DL+1 (AL)>5AH Y RET 修改BX及(CX)-1 N (CX)=0 Y A 例3:在以BUF为首地址的内存,存放着一个长度为N(N<256)的字符串,编程统计其中数字,字母和其它字符的个数,统计数存放在串后三个单元中。 ‘0’—‘9’ 30H—39H ‘A’—’Z’ 41H—5AH 初始化:N送CX; 0送DX; 0送BX; BX为串偏移量, MOV AL,BUF[BX]

  18. 先介绍第二种DOS返回方法:采用下面的程序框架先介绍第二种DOS返回方法:采用下面的程序框架 • code SEGMENT • ASSUME CS:code • main PROC FAR;使RET为远返回 • start: PUSH DS;入栈保存地址(DS的值= CS的值) • MOV AX, 0 ;程序段前缀的首地址(IP)=0 • PUSH AX • 、、 ;程序主体部分 • 、、 • RET;取程序段前缀首地址 • main ENDP • code ENDS • END start

  19. DATA SEGMENT BUF DB N DB 01H,38H,…76H NUM DB 3 DUP (?) DATA ENDS CODE SEGMENT MAIN PROC FAR ASSUME CS:CODE,DS:DATA START: PUSH DS SUB AX,AX PUSH AX MOV AX,DATA MOV DS,AX MOV CH,N MOV BX,1 MOV DX,0 LP: MOV AH,BUF[BX] CMP AH,30H JL NEXT ;小于‘0’转 CMP AH,39H JG ABC;大于‘9’转 INC DH JMP NEXT ABC: CMP AH,41H JL NEXT CMP AH,5AH JG NEXT INC DL NEXT: INC BX DEC CH JNZ LP MOV BUF[BX],DH MOV BUF[BX+1],DL MOV AH,N SUB AH,DH SUB AH,DL MOV BUF[BX+2],AH RET MAIN ENDP CODE ENDS END START

  20. 2、多分支 有的分支结构为多分支,可依次测试条件是否满足,若满足条件则转入相应分支入口,若不满足继续向下测试,直到全部测试完。简单,直观,速度慢。 例:有8个加工子程序,入口地址分别为P1,P2,… P8。编程实现检测键盘输入命令,使系统分别转向8个加工子程序。

  21. MOV AH,1 INT 21H ;1号功能调用,键盘输入 CMP AL,‘1’ JE P1 ;键值为1,转P1 CMP AL,‘2’ JE P2 ;键值为2,转P2 : CMP AL,‘8’ JE P8 ;键值为8,转P8 JMP ST ;非法键,转停机 P1:… ; 1号键加工子程序 P2:… ; 2号键加工子程序 P8:… ;8号键加工子程序 ST: HLT 局限性? ——利用跳转表实现多分支,可克服该方法的缺点。

  22. 开始 BASE+0 P0L P0H 输入键值 BASE+2 P1L P1H 表首地址BX . . . 求偏移量 P0 . . . 计算地址 P1 . . . 散转 跳转表在内存中的存放方法 3、跳转表实现多分支 利用跳转表实现多分支,可以直接找到相应入口,利用该法需建立一个跳转表,表中含每个分支的入口地址。 MOV BX,OFFSET BASE (1)根据表内地址分支 跳转表中存放了每个分支程序的入口地址,只要找到表地址,再将其内容取出,即可得到每个分支程序的入口地址。 表地址=跳转表首址+偏移地址 教材 P173 例5-4 AND AL,0FH ADD AL,AL ADD BX,AX JMP WORD PTR [BX]

  23. BASE JMP P1L P1H JMP P2L P2H . . . P1 . . . P2 . . . (2)根据表内指令分支 跳转表中存放着转移指令,查表后程序执行转移指令将转到相应的子程序去。教材 P174 例5-5 MOV AH,1 ;键入到AL INT 21H AND AL,0FH MOV AH,0 MOV BL,AL ADD AL,AL ADD AL,BL ;偏移量=键值*3 MOV BX,OFFSET BASE ADD BX,AX ;得转移地址 JMP BX ;转入转移指令 转移指令跳转表

  24. BASE 31 P1L 开始 P1H 32 输入关键字 P2L P2H Y 关键字=0 N . . . 首地址送BX P1 . . . 与关键字比较 P2 . . . Y 相等 N 指针加3 转移 (3)根据关键字分支 跳转表中存放关键字及相应分支地址。 分支流程图 关键字跳转表

  25. 循环初始化 循环体 循环工作部分 循环工作调整 N 循环结束判断 结 束 三、循环程序设计 循环初始化: 循环程序工作单元的初始化赋值。 循环体:重复执行的一段程序。 循环工作部分: 循环程序的核心。 循环工作调整:重复执行的环境调整。 循环结束判断:每一次循环要有二个出口。根据循环工作调整的情况,判断是否满足结束条件。若满足结束条件,退出循环;若不满足结束条件,继续循环。

  26. 循环初始设置 循环初始设置 N 循环体 Y N 循环体 循环条件判断? Y 循环条件判断? 循环程序可以有两种结构形式:DO WHILE结构、 DO UNTIL结构 循环结构 当型循环 (当条件成立进入循环) 直到型循环 (直到条件成立退出循环)

  27. 循环程序组成部分:1、循环初始化 2、循环体 3、循环修改 4、循环控制 循环程序设计举例 例 设计一个程序,完成从1连加到100(即1+2+…+99+100)的操作,结果保存在数据段的SUM单元。 分析:这样的问题如果采用顺序程序设计至少要一百条指令,并且程序的结构性和可读性差,而采用循环程序设计就会简洁明了,结果显示可考虑采用过程调用方式,程序清单如下:

  28. DATA SEGMENT SUM DW ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX ;数据段寄存器赋初值 ;循环初始化 SUB AX,AX ;工作寄存器清零 MOV CX,100 ;计数器赋初值 CLC ;清除进位标志 LP: INC AX ;循环体 ADC SUM,AX DEC CX ;循环修改 JNZ LP ;循环控制 ;******** ;插入显示程序的地方(预留位置) HLT CODE ENDS END START

  29. 注意: ① 本程序段采用了第三种退出方式,程序运行结束将由于执行HLT指令而进入停机状态,当键入Ctrl+Break组合键(键盘中断)后,返回DOS现场。 ② 用DEBUG跟踪,会发现(SUM)=13BAH。

  30. 子程序 SUB1 PROC 主程序 转向子程序 CALLSUB1 断点地址 RET 返回主程序 四、子程序 子程序是编程中常用的重要方法,它只需编写一次,测试一次而可以多次重复使用。把这些相同的计算机操作编成一个子程序(过程PROC)。使用CALL或RET指令调用或返回。

  31. 在编写子程序时,应写一个子程序说明,使子程序的模块结构及功能一目了然。在编写子程序时,应写一个子程序说明,使子程序的模块结构及功能一目了然。 * 子程序的名称,功能及性能 * 子程序中用到的寄存器和存储单元 * 子程序的入口参数,出口参数 * 子程序中调用其它子程序的名称 教材:P182例5-13 说明文档 注释改错 !

  32. 1、 子程序在调用和返回时注意堆栈的正确使用。 • 2、 现场保护与现场恢复 • 为避免出错,在进入子程序后应把子程序中用到的寄存器内容保存到堆栈中。在退出子程序前再将其恢复。 • 例: SUBT PROC • PUSH CX • PUSH DX • : • POP DX • POP CX • RET • SUBT ENDP

  33. 什么情况需要现场保护? • 保护和恢复的对象:在子程序中需要使用的内部寄存器。 • (1)一定要保护:子程序中使用的寄存器;在返回后主程序需继续使用的寄存器。 • (2)不用保护:作为子程序的结果传送给主程序的寄存器。 • (3)可随意处理:子程序中使用,返回主程序后不再使用的寄存器。

  34. 3、 子程与主程的参数传递 • 用寄存器传递:适合于参数较少的情况,传递速度较快。 • (例1 listbx子程序用BX寄存器传递参数) • 用定义的变量(存储器)传递:适合于参数较多的情况。 • (教材:P183例5-14) • 3) 用堆栈传递:适合于参数较多的情况,在子程序嵌套与递归调用的情况下使用,不容易出错。 • (教材:P184例5-15 )

  35. listbx PROC • PUSH CX ;保存寄存器 • PUSH BX • PUSH DX • PUSH AX • PUSHF • listbx PROC • MOV CH, 4 • MOV CL, 4 • next: ROL BX, CL • MOV DL, BL • AND DL, 0FH • ADD DL, 30H • CMP DL, 39H • JLE print • ADD DL,07H • print: MOV AH,2H • INT 21H • DEC CH • JNZ next • MOV DL, 20H ;显示空格符 • MOV AH, 02H • INT 21H • RET;子程返回 • listbx ENDP • code ENDS • END start • POPF ;恢复寄存器 • POP AX • POP DX • POP BX • POP CX • RET;子程返回 • listbx ENDP 例1:用十六进制显示 BX内容子程(用寄存器传递参数)

  36. 例5-14 :编程实现数组段分别求和(不计溢出)。(利用存储器来传递参数)提示:教材上有错误 DATA SEGMENT ARY1 DW 100 DUP(?) SUM1 DW ? ARY2 DW 100 DUP(?) SUM2 DW ? DATA ENDS STACK SEGMENT STACK SA DW 50 DUP(?) TOP EQU LENGTH SA STACK ENDS CODE SEGMENT ASSUME CS: CODE,DS:DATA,SS:STACK MAIN PROC FAR START: PUSH DS SUB AX,AX PUSH AX MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX MOV SP,TOP

  37. LEA SI,ARY1 MOV CX,LENGTH ARY1 CALL SUM LEA SI,ARY2 MOV CX,LENGTH ARY2 CALL SUM RET MAIN ENDP SUM PROC NEAR XOR AX,AX L1: ADD AX,WORD PTR[SI] INC SI INC SI LOOP L1 MOV WORD PTR [SI],AX RET SUM ENDP CODE ENDS END START 本例是利用存储器来传递参数,调用前将数组的偏移地址放入SI中,在过程中通过寄存器间址就可取得存储器中的操作数,并通过存储器返回。

  38. 教材上错误第二种改法: DATA SEGMENT ARY1 DW 100 DUP (?) SUM1 DW ? ARY2 DW 100 DUP (?) SUM2 DW ? DATA ENDS : ;堆栈段省略 CODE SEGMENT ASSUME CS:CODE,DS:DATA START: MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX MOV SP,TOP LEA SI, ARY1 MOV CX, LENGTH ARY1 CALL SUM

  39. LEA SI,ARY2 MOV CX,LENGTH ARY2 CALL SUM MOV AH,4CH INT 21H SUM PROC NEAR XOR AX,AX L1: ADD AX,WORD PTR [SI] INC SI INC SI LOOP L1 MOV WORD PTR [SI],AX RET SUM ENDP CODE ENDS END START

  40. 例5-15 :编程实现十进制数组求和,段间调用。(用堆栈传递) MDATA SEGMENT ARY1 DB 20 DUP(?) SUM1 DW ? ARY2 DW 100 DUP(?) SUM2 DW ? MDATA ENDS MSTACK SEGMENT STACK SB DW 100 DUP(?) TOP EQU LENGTH SB MSTACK ENDS MCODE SEGMENT ASSUME CS: MCODE,DS:MDATA,SS:MSTACK MAIN PROC FAR START: PUSH DS SUB AX,AX PUSH AX MOV AX,MDATA MOV DS,AX MOV AX,MSTACK MOV SS,AX MOV SP,TOP

  41. SP-10 F SP-E BP SP-C CX SP-A BX SP-8 IP SP-6 CS SP-4 SIZE1 SP-2 ARY1 SP MOV AX,OFFSET ARY1 PUSH AX MOV AX,SIZE ARY1 PUSH AX CALL FAR PTR PADD MOV AX,OFFSET ARY2 PUSH AX MOV AX,SIZE ARY2 PUSH AX CALL FAR PTR PADD RET MAIN ENDP MCODE ENDS PCODE SEGMENT ASSUME CS: PCODE,DS:MDATA,SS:MSTACK PADD PROC FAR PUSH BX PUSH CX PUSH BP MOV BP,SP PUSHF

  42. SP-10 F SP-E BP SP-C CX SP-A BX SP-8 IP SP-6 CS SP-4 SIZE1 SP-2 ARY1 SP MOV CX,[BP+10] MOV BX,[BP+12] MOV AX,0 NEXT: ADD AL,[BX] DAA MOV DL,AL MOV AL,0 ADC AL,AH DAA MOV AH,AL MOV AL,DL INC BX LOOP NEXT MOV [BX],AX POPF POP BP POP CX POP BX RET 4 PADD ENDP PCODE ENDS END START

  43. 4、子程序嵌套 子程序调用其他子程序,称子程序嵌套,子程序可多重嵌套调用。 *递归调用:子程序调用子程序本身。 例设从BUF开始存放若干无符号字节数据,找出其中的最小值并以十六进制形式输出。 分析:用子程序SEARCH来求最小值并输出。 DATA SEGMENT BUF DB 13,25,23,100,423,78,90,134 CNT EQU $-BUF DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA

  44. SATRT: MOV AX,DATA MOV DS,AX MOV CX, CNT-1 MOV SI, OFFSET BUF CALL SEARCH MOV AH, 4CH INT 21H SEARCH PROC NEAR MOV BL,[SI] SEAR1: INC SI CMP BL,[SI] JBE SEAR2 MOV BL,[SI] SEAR2: DEC CX JNZ SEAR1 MOV DL,BL MOV CL,4 SHR DL,CL CALL DISP;嵌套调用 MOV DL,BL AND DL,0FH CALL DISP RET SEARCH ENDP DISP PROC NEAR CMP DL,9 JBE DISP1 ADD DL,7 DISP1: ADD DL,30H MOV AH,2 INT 21H RET DISP ENDP CODE ENDS END START

  45. 教材 例5-16:两个无符号求和并转换成十六进制数在屏幕上显示。(嵌套调用) 主程序: DATA SEGMENT P DW 125,368 SUM DW ?DATA ENDS MOV SI,OFFSET P CALL PADD

  46. 子程序PADD: AX,BX,CX,DX入栈 MOV AX,[SI] ;取数 ADD AX,[SI+2] ;加法 MOV SUM,AX ;存数 CALL DISP; AX,BX,CX,DX出栈 RET 子程序DISP: 显示数送BX; 显示位数04H送CH ; 取四位二进制数转换成ASCII; 送显示; 四位数显示完?未完继续循环; RET

  47. 5、编写子程序的注意事项: 注意子程中PUSH、POP应成对,否则易造成死机。 SS:SP (IP) (AX) 执行push 后 SS:SP SS:SP 执行ret 后 (IP) 执行call 后 SS:SP 执行call 前 • data SEGMENT • string DB ‘Hello’,’$’ • data ENDS • code SEGMENT • ASSUME CS:code, DS:data • start: MOV AX, data • MOV DS, AX • CALL input • MOV AH, 4CH • INT 21H • input PROC • PUSH AX • LEA DX, string • MOV AH, 09H • INT 21H • RET • input ENDP • code ENDS • END start

  48. 思考如下程序的执行流程: • code SEGMENT • start: 、、 • CALL sub • 、、 • CALL sub • 、、 • ; MOV AH, 4CH • ; INT 21H • sub PROC • 、、 • 、、 • RET • sub ENDP • MOV AH, 4CH • INT 21H • code ENDS • END start 程序执行不到返回DOS功能调用处, 最后的结果是死机.

  49. 5.2 汇编语言上机调试过程(略)

  50. 上机环境 用户开发的程序:ABC.exe等 操作系统:DOS系统 编辑器:EDIT.exe 编程序: MASM.exe 连接程序:LINK.exe 调试程序:DEBUG.exe 应用软件 系统软件 硬件 CPU、存储器(ROM、RAM)、I/O接口、输入、输出设备

More Related