汇编语言汇编程序设计课件 4_基本汇编语言程序设计_第1页
汇编语言汇编程序设计课件 4_基本汇编语言程序设计_第2页
汇编语言汇编程序设计课件 4_基本汇编语言程序设计_第3页
汇编语言汇编程序设计课件 4_基本汇编语言程序设计_第4页
汇编语言汇编程序设计课件 4_基本汇编语言程序设计_第5页
已阅读5页,还剩92页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、1,封面,第四章,基本汇编语言程序设计, ,2,第四章基本汇编语言程序设计,第四章 基本汇编语言程序设计 4.1顺序程序设计 4.2 分支程序设计 4.3 循环程序设计 4.4 子程序设计 4.4.1 过程定义伪指令 4.4.2 子程序的参数传递 4.4.3 子程序的嵌套、递归与重入 4.4.4 子程序的应用 本章要点及习题分析,3,4.1顺序程序设计(e),4.1顺序程序设计 指令按程序中的书写顺序逐条执行,称为顺序程序。除非编程解决非常简单的问题,顺序程序并不多见,但是顺序程序往往是复杂程序结构的一部分,如分支结构的一个分支,循环结构的循环体等。,返回第四章,4,例4.1,例4.1:设有3

2、个字变量x,y和z,求出三者之和,结果存入字变量w。 .model small .startup .stack mov ax,x .data add ax,y Xdw 5 add ax,z Ydw 6 mov w,ax Zdw 7 .exit 0 Wdw ? end .code,5,例4.2/1,例4.2 设有一个64位数据,将它整个左移8位。,6,例4.2/2,.model small .stack .data Qvar dq 1234567887654321h .code mov al,byte ptr qvar6 mov byte ptr qvar7,al mov al,byte ptr

3、 qvar5 mov byte ptr qvar6,al mov al,byte ptr qvar4 mov byte ptr qvar5,al mov al,byte ptr qvar3 mov byte ptr qvar4,al,7,例4.2/3,mov al,byte ptr qvar2 mov byte ptr qvar3,al mov al,byte ptr qvar1 mov byte ptr qvar2,al mov al,byte ptr qvar0 mov byte ptr qvar1,al mov byte ptr qvar0,0,(移位前),(移位后),返回第四章,8,4

4、.2分支程序设计,4.2 分支程序设计 条件转移指令Jcc和无条件转移指令JMP用于实现程序的分支结构,JMP不测试条件,Jcc可根据条件是否成立决定转移到指定位置或不转移而顺序执行后续指令。由于Jcc不支持条件表达式,而是以当前标志位的状态为条件,故Jcc之前一定要安排设置标志位的指令,如加减法、比较、测试等指令。基本分支类型分为单分支和双分支。,9,单分支,1. 单分支类型,对同一个问题,根据选择的条件不同,单分支结构的流程图有两种画法,对应的程序也有两种编法。如计算AX中的有符号数的绝对值。,10,单分支,cmp ax,0 jge noneg neg ax Noneg: mov resu

5、lt,ax,cmp ax,0 (教材有误) jnge yesneg jmp done yesneg: neg ax Done: mov result,ax,11,双分支,2.双分支程序,两个分支都有语句体,如何选择条件不重要。 流程图中分支体的位置就是程序的实际顺序,故分支语句体最后一定要有一条指令,跳过语句体,转移到“后续操作”。,12,双分支,双分支举例:显示BX的最高位。 shl bx,1 jc one ;转分支体 mov dl,0 ;分支体1 jmp next;转后续操作 One: mov dl,1 ;分支体2 next: mov ah,2 ;后续操作 int 21h .分支程序的其他

6、问题 有些双分支问题可以先假设一种情况,把双分 支改成单分支问题。如上例,先假设BX最高位为0, 在分支外准备显示0;如最高位为0,即可直接跳到后 续操作;如最高位为1才需要执行分支体。,mov dl,0 shl bx,1 jnc next mov dl,1 next:mov ah,2 int 21h,13,多分支,分支的嵌套形成多分支,嵌套形式多种多样。 例1:求符号函数 1 当 X0 Y= 0 当 X=0 -1 当 X0,实际是双分支的组合。,14,多分支,例2:判断AL各位的值,D0=1,转移到L0;D1=1,转移到L1;D2=1,转移到L2,也可认为是双分支的组合,但为简化编程,实现左

7、图的分支结构可以在数据段设置转移地址表,如例题4.4,15,多分支,例4.4 使用地址表实现多分支。8个分支的标号分别为disp1,disp2 在代码段有: disp1:mov dx, disp2:mov 设disp1的偏移地址为2300h,disp2的偏移地址为2500h。 在数据段有: tabel dw disp1,disp2,16,多分支(e),转入分支:按输入的数字转入不同分支 按输入的数字求出分支相对tabel的偏移量:disp1为0,disp2为2,disp3为4,如输入数字2,则偏移量为(2-1)2=2,将求出的偏移量存入bx。 执行指令jmp tabelbx,设bx=02 则I

8、P tabel+bx 即IP 2500H CS:2500H为分支Disp2的入口,CPU即执行分支DISP2,返回第四章,17,4.3 循环程序设计,4.3 循环程序设计(重复执行的程序段) 1.循环程序的组成 初始化部分:设置循环条件、次数、初值等。 循环体部分:重复执行的代码,含循环条件的修改等。 循环控制部分:判断循环条件,决定是否继续。 2.两种循环结构 1) “先循环、后判断”结构 相当于高级语言的“直到型”循环 2) “先判断、后循环”结构 相当于高级语言的“当型循环”,可实现0次循环。,18,两种循环结构,19,循环程序设计,3.循环程序设计 编写循环程序的关键在于循环的控制。

9、循环次数已知:可用LOOP指令,CX计数。如教材例4.5。 循环次数和ZF标志:可用LOOPZ、LOOPNZ指令。如教材例4.6。 循环次数未知:通常要采用各类条件转移指令实现循环控制。如教材例4.7,字符串以0结尾;例4.9,字符串以$结尾。,20,例题分析,循环程序例题分析: 例4.5:计算100个数字之和。 仅用循环次数控制,且循环次数已知,比较简单。 例4.6:确定一个字变量中为1的最低位数。 从最低位向高位依次测试,最多测试16次;测试到某位为1,即可结束程序,测试结果用ZF标志反映,因此可用LOOPE或LOOPZ控制循环(结果非0,退出)。 例4.7:将一个字符串中的所有大写字母改

10、为小写字母,字符串以0结尾。 循环次数未知,应使用条件判断控制循环;循环结构应使用“先判断、后执行”的结构;通常,采用条件判断控制循环时,往往采用“先判断、后执行”的循环结构。,21,例题4.6,例4.6:确定一个字变量中为1的最低位数。 .startup mov ax,wordX;测试目标送AX mov cx,16;循环计数器置初值 mov dl,-1;计位器置初值 again:inc dl test ax,1 ror ax,1 ;循环指令不影响ZF loope again ;CX0且ZF=1(测试位为0),继续循环 je notfound ;退出循环,但0标志成立,没有1 mov byte

11、Y,dl jmp done notfound:mov byteY,-1;ZF=1,16个位均为0 done:.exit 0 end,22,例题4.7/1,例4.7:将一个字符串中的所有大写字母改为小写字母,字符串以0结尾。 .data Steing db xxxxxxxxxxxxxxxxxx,0 .code .startup mov bx,offset string again: mov al,bx ;取一个字符 or al,al ;是否为结尾符0 jz done ;是,退出循环,23,/2,cmp al,A ;是否为大写AZ jb next cmp al,Z ja next or al,20

12、h ;是,转换为小写字母(使 D5=1) mov bx,al;仍保存在原位置 next: inc bx jmp again;继续循环 done: .exit 0 end,24,两重循环结构,4.多重循环:循环程序的嵌套构成多重(多层)循环。最常见的多重循环为两重循环。,25,“冒泡法”排序,例4.8:采用“冒泡法”排序(升序)。 冒泡法从第一个元素开始,依次对相邻的两个元素进行比较,使前一个元素不大于后一个元素;将所有元素比较完之后,最大的元素排到了最后;第一轮比较结束。然后,开始第二轮,除掉最后一个元素,其他元素依上述方法再进行比较,得到次大的元素排在后面;第二轮结束。如此重复,直至完成,就

13、实现了元素从小到大的排序 循环次数已知的双重循环程序。外层循环(轮)的次数为数据个数减1,每一轮外循环的内层循环次数等于剩下的外循环次数。如5个数据,外循环次数=4,第一轮中内循环次数也为4;第一轮作完,还剩下3轮,第二轮中内循环次数等于3,以次类推。,“冒泡法”排序,小数冒泡,大数沉底,排序示意图,须作4轮,第1轮,27,例4.8 排序/1,例4.8 对无符号字节数组元素由小到大排序。 .data Array db xx,xx,xx, Count equ ($-array)/(type array) .code mov cx,count;CX数组元素个数 dec cx ;元素个数减1为外循环

14、次数 outlp:mov dx,cx ;DX内循环次数 mov bx,offset array inlp:mov al,bx ;取前一个元素 cmp al,bx+1 ;与后一个元素比较 jna next ;前一个不大于后一个元素,则不进行交换 xchg al,bx+1;否则,进行交换 mov bx,al,28,例4.8 排序/2,next:inc bx;下一对元素 dec dx jnz inlp;内循环尾 loop outlp;外循环尾,29,例4.9 剔除空格程序,例4.9:剔除以结尾的字符串中的空格。 双重循环程序:外层循环负责搜索字符串中的空格;内层循环负责剔除搜索到的空格(由于空格后的

15、字符要依次向前移动一个字节,因而也是一个循环结构)。 无论是外层循环,还是内层循环,循环次数都未知,只能用“条件判断”控制循环。 外层循环采用“先判断、后循环”结构;对内层循环而言,由于搜索到空格才进入内循环,所以采用“先循环、后判断”结构。,30,例4.9/1,例4.9:现有一个以$结尾的字符串,要求剔除其中的空格。 .data stringdb Let us have a try !,$ .code .startup mov dx,offset string mov ah,9 int 21h ;显示原字符串 mov al, ;AL空格(ASCII码为20H) mov di,offset s

16、tring,31,例4.9/2,outlp:cmp byte ptr di,$;外循环,先判断后循环 jz done ;为$结束 cmp al,di ;检测是否是空格 jnz next ;不是空格继续外循环 mov si,di ;是空格,进入剔除空格分支 inlp:inc si ;该分支是循环程序段 mov ah,si ;取空格后的一个字符 mov si-1,ah ;向前移动一个字节 cmp byte ptr si,$;内循环,先循环后判断 jnz inlp,32,例4.9/3,next:inc di ;继续对后续字符进行处理 jmp outlp done:mov dx,offset stri

17、ng mov ah,9 int 21h ;显示处理后字符串 .exit 0 ;结束 end,返回第四章,33,4.4 (目录)子程序设计,4.4 子程序设计 把功能相对独立的程序段单独编写和调试,作为 一个相对独立的模块供程序使用,就形成子程序。 使用子程序:简化源程序结构;提高编程效率。 4.4.1 过程定义伪指令 4.4.2 子程序的参数传递 4.4.3 子程序的嵌套递归重入 4.4.4 子程序的应用,返回第四章,34,4.4.1 过程定义伪指令(1),4.4.1 过程定义伪指令 过程名 PROC NEAR|FAR 过程体 RET(RET N) 过程名 ENDP 过程名:符合语法的标识符;

18、同模块唯一性。 距离属性:可省略,由汇编程序判断。 堆栈使用:平衡。才能保证RET指令弹出的是断点地址。 保护现场与恢复现场:子程序用到的寄存器或存储单元,注意:后进先出。 注意子程序的规范和格式,35,关于“距离属性”,关于“距离属性” NEAR属性(段内近调用)的过程只能被相同代码段的其他程序调用 FAR属性(段间远调用)的过程可以被相同或不同代码段的程序调用 对简化段定义格式,在微型、小型和紧凑存储模式下,过程的缺省属性为near;在中型、大型和巨型存储模式下,过程的缺省属性为far 对完整段定义格式,过程的缺省属性为near 用户可以在过程定义时用near或far改变缺省属性,36,子

19、程序规范,子程序规范 一个完整的子程序,特别是供其他编程人员使用的子程序,必须附有一个详细说明: 子程序名(过程名) 子程序功能介绍 子程序的入口参数 子程序的出口参数 子程序内使用的寄存器(存储单元) 使用该子程序的范例,37,子程序的常见格式,子程序的常见格式 ;子程序说明 ;子程序说明 subnameproc;具有缺省属性的subname过程 push ax;保护寄存器:顺序压入堆栈 push bx;ax/bx/cx仅是示例 push cx ;过程体 pop cx;恢复寄存器:逆序弹出堆栈 pop bx pop ax ret;过程返回 subnameendp;过程结束,38,简单子程序,

20、简单子程序 ;子程序功能:实现光标回车换行 dpcrlfproc ;过程开始 push ax ;保护寄存器AX和DX push dx mov dl,0dh ;显示回车 mov ah,2 int 21h mov dl,0ah ;显示换行 mov ah,2 int 21h pop dx ;恢复寄存器DX和AX pop ax ret ;子程序返回 dpcrlfendp ;过程结束,39,例4.10:编写子程序(e),例4.10:编写子程序,将AL寄存器内的二进制数 用十六进制数显示。 8位二进制数,可转换成两位十六进制数。 十六进制数ASCII码2#功能调用显示 1001B9H1001+0011 0

21、00039H(9的ASCII) 1010BAH1010+0011 011141H(A的ASCII) 注意:对0-9加30H,对A-F加37H,即+30H+07H 先转换高4位二进制数,并显示;然后转换低4位并显示。,例题410,回 4.4,40,4.4.2 子程序的参数传递,4.4.2 子程序的参数传递 主程序和子程序之间通常需要传递参数: 入口参数(输入参数):主程序提供给子程序 出口参数(输出参数):子程序返回给主程序 参数的形式: 数据本身(传值) 数据的地址(传址) 传递的方法: 寄存器 变量 堆栈,41,参数传递方法,1.用寄存器传递参数 方便、简单、易行。须要传递的参数较多时不适用

22、。见例题411a。 2.用变量传递参数 就是用存储器传递参数,当主程序与子程序在同一个模块时,即为共享数据段的变量;不在同一模块,需要用PUBLIC/EXTERN声明。 适用与参数较多情况。见例题411b。 3.用堆栈传递参数 常用方法。用BP访问堆栈段。须格外注意堆栈的平衡。(堆栈示意图),42,堆栈示意图,43,例题4.11c/1,例题4.11c:计算累加和 ;用堆栈传递参数 ;入口参数:数组首地址、数组元素个数 ;出口参数:AL 累加和 .model small .stack .data count equ 10 array db 12h,25h,0f0h,0a3h,03,68h,71h

23、,0cah,0ffh,90h result db ?,44,例题4.11c/2,.code .startup mov ax,offset array push ax ;首地址入栈 mov ax,count push ax ;元素个数入栈 call checksuma add sp,4 ;平衡两个参数占用的堆栈 mov result,al .exit 0,45,例题4.11c/3,checksuma proc push bp mov bp,sp;使BP指向刚进入子程序的堆栈顶, push bx push cx mov bx,bp+6 mov cx,bp+4 xor al,al suma: add

24、 al,bx inc bx loop suma,46,例题4.11c/4,pop cx pop bx pop bp ret ;可以用RET 4 checksuma endp end,47,编写子程序时应注意的问题,编写子程序时应注意的问题: 使用简化的段定义格式时,过程定义在程序中的位置要注意,可以放在1)主程序的最后,即“.EXIT 0”之后,END语句之前;2)放在主程序之前,即“.CODE”之后,“.STARTUP”之前。 使用寄存器传递参数时,带有入口参数的寄存器可以保护,也可以不保护;带有出口参数的寄存器则一定不可保护和恢复;其他与出口参数无关、而子程序中使用的寄存器,子程序开始处应

25、该保护,子程序结束、返回主程序之前应该恢复。,回 4.4,48,4.4.3 子程序的嵌套递归重入,4.4.3 子程序的嵌套、递归与重入 1.子程序的嵌套 子程序又调子程序称为子程序的嵌套,嵌套的层数取决于堆栈空间的大小。嵌套子程序的设计和一般子程序完全相同。 2.子程序的递归 子程序直接或间接地嵌套调用自己,称为递归调用。含有递归调用的子程序称为递归子程序。 每次调用时不能破坏以前调用所用的参数及中间结果,因此,调用参数及中间结果一般都放在堆栈中。不可放在固定的寄存器或存储单元中。 要控制递归的次数,避免陷入死循环。 递归深度受堆栈空间的限制。,49,例题4.12,例题4.12 用递归子程序求

26、N的阶乘,设N=3。 递归次数用N控制,由N=3,子程序共运行4次(主程 序调用1次,递归调用3次);入口参数及中间结果都 用堆栈保存。 注释:1)在进入子程序过程中,不计算阶乘值, 只求中间参数。第一次进入,求出中间参数2;第二 次进入求出中间参数1;第三次进入求出中间参数0; 第四次进入后,由于中间参数以为0,开始执行返回 处理。 2)在返回过程中计算阶乘:在过程3中计算1*1=1, 在过程2中计算1*2=2,在过程1中计算2*3=6。 3)递归子程序可设计出效率较高的程序,但是编程 较难,编出的程序易读性差,使用不多。,50,子程序的重入(e),3.子程序的重入 子程序被中断后,又被中断

27、服务程序所调用,称为子程序的重入。能够重入的子程序称为可重入子程序。当主机与外设采用中断方式交换信息时,外设的驱动程序应按“可重入原则”设计。 虽然重入与递归的概念不同,但递归子程序就是可重入子程序。设计可重入子程序与设计递归子程序的原则是相同的,即参数、中间结果等都用堆栈保存,不能用固定的存储单元或寄存器保存。,回 4.4,51,4.4.4 子程序的应用,4.4.4 子程序的应用 1)例题4.15 计算有符号数的平均值。 有时进行运算之前,需要符号扩展;对无符号数应进行0扩展。 2)具有局部变量的子程序(截取教材P123部分程序):当某些数据只有子程序自己使用时,可在代码段子程序后面定义数据

28、区。 3)具有多个出口的子程序:有的子程序具有多个出口,根据条件的不同,从不同的出口返回主程序。,52,例4.15 计算平均值/1,例4.15 计算有符号数的平均值。 ;入口参数用堆栈传递,出口参数用寄存器AX传递。 ;要计算16位有符号数的和,被加数一定要进行符号 扩展。 .model small .stack .data array dw 1234,-1234,1,1,-1,32767,-32768,5678, -5678,9000 count equ ($-array)/2 ;数据个数 wmed dw ?,53,/2,.code .startup mov ax,count push ax

29、 ;参数1 mov ax,offset array push ax ;参数2 call mean add sp,4 ;平衡堆栈 mov wmed,ax .exit 0,54,/3,mean proc push bp mov bp,sp push bx push cx push dx push si push di mov bx,bp+4;取参数2:偏移地址 mov cx,bp+6;取参数1:数据个数 xor si,si mov di,si,55,/4,mean1: mov ax,bx cwd add si,ax adc di,dx inc bx inc bx loop mean1 mov ax

30、,si mov dx,di mov cx,bp+6,dx.ax + di.si di.si,56,/5,idiv cx ;求平均值,商在AX,余数在DX pop di pop si pop dx pop cx pop bx pop bp ret mean endp end,57,避免溢出的方法,为了避免有符号二进制数求和过程中溢出,被加数要进行符号扩展,得到倍长数据(大小没有变化),然后求和 如数据采用16位二进制数表示,数据个数也采用16位二进制数表示,则最多为216个数据。如将数据扩展到32位二进制数表示,求和时,就不会出现溢出。 考虑极端情况:数据全是215(-32768),共有216个

31、,求和结果是231,32位数据仍然可以表达。 对于无符号数,有时也需要得到倍长数据,应采用 “0扩展”,即将高位置0,如“MOV DX,0”。,;将AL低4位表达的一位16进制数转换为ASCII码 H2ASCproc push bx mov bx,offset ASCII;BX指向ASCII码表 and al,0fh;取得一位16进制数 xlat CS:ASCII ;换码:ALCS:BXAL,注意数据在代码段CS pop bx ret;子程序返回 ASCIIdb 30h,31h,32h,33h,34h,35h,36h,37h db 38h,39h,41h,42h,43h,44h,45h,46h

32、 H2ASCendp,例题 具有局部变量的子程序,因为数据区与子程序都在代码段,所以利用了换码指令XLAT的另一种助记格式(写出指向缓冲区的变量名,目的是便于指明段超越前缀)。串操作MOVS、LODS和CMPS指令也可以这样使用,以便使用段超越前缀 除采用段超越方法外,子程序与主程序的数据段不同时,我们还可以通过修改DS值实现数据存取;但需要保护和恢复DS寄存器,HTOASCproc ;将AL低4位表达的一位16进制数转换为ASCII码 and al,0fh cmp al,9 jbe htoasc1 add al,37h;是0AH0FH,加37H ret;子程序返回 htoasc1:add a

33、l,30h;是09,加30H ret;子程序返回 HTOASCendp,例题 具有多个出口的子程序,回 4.4,60,例4.13,例4.13 编写子程序从键盘输入一个有符号十进制数; 并将输入的ASCII码转换为二进制数。 输入时,负数用“”引导,正数直接输入或用“”引导 子程序用寄存器传递出口参数,主程序调用该子程序输入10个数据 将ASCII码转换为二进制数的过程 首先判断输入为正或负数,并用一个寄存器记录 接着输入09数字(ASCII码),并减30H转换为二进制数 然后将前面输入的数值乘10,并与刚输入的数字相加得到新的数值 重复、步,直到输入一个非数字字符结束 负数进行求补,转换成补码

34、;否则直接保存数值,61,输入和转换流程图,输入和转换流程图:,输入非数字字 符,结束输入,62,输入数字举例,设从键盘输入数字 258: 输入顺序:- 2 5 8 CX -1 -1 -1 -1 BX 0 0002 0019H=25 0102H=258 数字输入结束后,由于CX为负数标志, 再对BX求补。,63,程序/1,.data count= 10 arraydw count dup(0);预留数据存储空间 .code .startup mov cx,count mov bx,offset array again:call read;调用子程序输入一个数据 mov bx,ax;将出口参数存

35、放缓冲区 inc bx inc bx call dpcrlf ;调用子程序,光标回车换行以便输入下一个数据 loop again .exit 0,这是主程序,64,程序/2,;输入有符号10进制数的通用子程序 ;出口参数:AX补码表示的二进制数值 read proc push bx push cx push dx xor bx,bx;BX保存结果 xor cx,cx ;CX为正负标志,0为正,1为负 mov ah,1;输入一个字符 int 21h,65,程序/3,cmp al,+;是“”,继续输入字符 jz read1 cmp al,-;是“”,设置1标志 jnz read2;非“”和“”,转

36、read2 mov cx,-1 read1:mov ah,1;继续输入字符 int 21h read2:cmp al,0 ;不是09之间的字符,则输入数据结束 jb read3 cmp al,9 ja read3,66,程序/4,sub al,30h ;是09之间的字符,则转换为二进制数 ;利用移位指令,实现数值乘10:BXBX10 shl bx,1 mov dx,bx shl bx,1 shl bx,1 add bx,dx mov ah,0 add bx,ax ;已输入数值乘10后,与新输入数值相加 jmp read1;继续输入字符,67,程序/5,read3:cmp cx,0 jz rea

37、d4 neg bx ;是负数,进行求补 read4:mov ax,bx;设置出口参数 pop dx pop cx pop bx ret ;子程序返回 readendp dpcrlfproc ;使光标回车换行的子程序 . ;省略 dpcrlfendp end,68,例 4.14,例4.14 编写子程序,将二进制数转换为10进制数的ASCII码,并在屏幕上显示一个有符号10进制数。 显示时,负数用“”引导,正数直接输出、没有前导字符。 子程序的入口参数用共享变量传递,主程序调用该子程序显示10个数据。 将二进制数转换为10进制数的ASCII码 首先判断数据是零、正数或负数,是零显示“0”退出 是负

38、数,显示“”,求数据的绝对值; 接着数据除以10,余数加30H转换为ASCII码压入堆栈 重复步,直到余数为0结束 依次从堆栈弹出各位数字,进行显示,69,显示数字举例,显示数字举例:设AX中数据为-258的补码 1.显示负号-。 2.求补,AX中得到-258的绝对值。 3.258/10,商为25,余数为8,此为个位。 8+30H,入栈。 4.25/10,商为2,余数为5,此为十位。 5变ASCII码入栈。 5.2/10,商为0,余数为2,此为百位。 2变ASCII码入栈。 6.由于商为0,变换结束。 7.顺序出栈显示。,70,程序/1,.data Count = 10 Array dw 12

39、34,-1234,0,1,-1,32767,-32768, dw 5678,-78,9000 Wtemp dw ? ;共享变量 .code .startup mov cx,count mov bx,offset array again:mov ax,bx mov wtemp,ax;将入口参数存入共享变量 call write;调用子程序显示一个数据 inc bx inc bx call dpcrlf;便于显示下一个数据 loop again .exit 0,71,程序/2,;显示有符号10进制数的通用子程序 ;入口参数:共享变量wtemp writeproc push ax push bx p

40、ush dx mov ax,wtemp;取出显示数据 test ax,ax;判断零、正数或负数 jnz write1 mov dl,0;是零,显示“0”后退出 mov ah,2 int 21h jmp write5 ;恢复现场后返回,72,程序/3,write1:jns write2;不是负数,转向数据转换。mov bx,ax ;是负数,显示“” mov dl,- mov ah,2 int 21h mov ax,bx neg ax ;求绝对值 write2:mov bx,10 ;准备除数 push bx ;10压入堆栈,作为退出标志,73,程序/4,write3:cmp ax,0;数据(商)为

41、零 jz write4;转向显示 sub dx,dx;扩展被除数DX.AX div bx ;数据除以10:DX.AX10 add dl,30h ;余数(09)转换为ASCII码 push dx ;数据各位先低位后高位压入堆栈 jmp write3,74,程序/5,write4:pop dx ;数据各位先高位后低位弹出堆栈 cmp dl,10 ;是结束标志10,则退出 je write5 mov ah,2 ;进行显示 int 21h jmp write4 write5:pop dx pop bx pop ax ret ;子程序返回 writeendp dpcrlfproc ;使光标回车换行的子程

42、序 . ;省略 dpcrlfendp end,75,本章要点,本章要点: 分支程序设计: 单分支、双分支、多分支 单分支流程图的画法 用转移地址表法实现多分支 循环程序设计: 两种循环结构 循环程序的控制方法:计数法、条件判断法 单层循环和双层循环 子程序设计: 过程定义伪指令 子程序的参数传递:寄存器、变量、堆栈,76,习题分析:补充1,1.将AX中存放的无符号数除以2,如果是奇数,则加 1后除以2(单分支) test ax,01h;测试AX最低位 jz even ;最低位为0:AX为偶数 add ax,1 ;最低位为1:AX为奇数,需要加1 even:rcr ax,1;AXAX2 ;如果采

43、用SHR指令,则不能处理AXFFFFH的特殊情况,77,补充2/1,2.判断一元二次方程是否有实根。有,TAG置1; 无,TAG置0。(教材例题4.3:双分支) .data a db ? b db ? c db ? tag db ? .code .startup mov al,b imul al mov bx,ax;BX中为b2,78,补充2/2,mov al,a imul c mov cx,4 imul cx ;AX中为4ac(DX无有效数据) cmp bx,ax;比较二者大小 jge yes ;条件满足? mov tag,0 ;第一分支体:条件不满足,tag0 jmp done ;跳过第二

44、个分支体 yes:mov tag,1 ;第二分支体:条件满足,tag1 done:.exit 0 end,79,补充3/1,3.按键盘输入的数字1-8,转8个分支(显示不同的 信息)。(同教材例题4.4,但显示的信息不同) 分析过程见课件4.2节的“多分支部分” .data msg db Input number(18):,0dh,0ah,$ Msg1 db Chapter 1 : .,0dh,0ah,$ msg2 db Chapter 2 : .,0dh,0ah,$ . msg8 db Chapter 8 : . ,0dh,0ah,$ table dw disp1,disp2,disp3,d

45、isp4 dw disp5,disp6,disp7,disp8 ;取得各个标号的偏移地址,80,补充3/2, start1:mov dx,offset msg;提示输入数字 mov ah,9 int 21h mov ah,1;等待按键 int 21h cmp al,1;数字 8? ja start1 and ax,000fh;将ASCII码转换成数字,81,补充3/3,dec ax shl ax,1;等效于add ax,ax mov bx,ax jmp tablebx ;(段内)间接转移:IPtable+bx start2:mov ah,9 int 21h .exit 0 disp1: mov

46、 dx,offset msg1;处理程序1 jmp start2 Disp2: . end,82,习题4.4,习题分析 4.4 编写一个程序,把从键盘输入的一个小写字母用大写字母显示出来。 框图:(省略输入字符的判断:简单的顺序程序),83,4.5,4.5 已知用于LED数码管显示的代码表为: LEDTABEL DB 0C0H,0F9H(共16项数据) 依次表示09,AF这16个数码的显示代码,编写一个程序实现将lednum中的一个数字转换成对应的LED显示代码。(查表程序),84,4.8,4.8 如果在例题4.4的tabel中依次添入msg1msg8,程序应该如何修改?(Tabel dw m

47、sg1,.) mov bx,ax mov bx,ax jmp tabelbx mov dx,tabelbx Start2: mov ah,9 mov ah,9 int 21h int 21h .exit 0 .exit 0 end 程序变得更加简单。,取显示信息 偏移地址,取转移地 址送IP,85,4.9,4.9 编制一个程序,将变量BUFX、BUFY中较大者送入BUFZ;若两者相等,则把其中之一送入BUFZ中。设变量为无符号8位数。,86,4.10,4.10 设变量bufX为有符号数,编程将其符号状态保存在singX,如X大于等于0,保存0;如X小于0,保存-1。 该题为一个可以演变成单分支的双分支结构:,87,4.11,4.11 X、Y、Z是三个有符号16位数(教材误印为16进制数),编写程序: 1)三个数都不相等,显示0; 2)有两个数相等,显示1; 3)三个数都相等,显示2。 三个数比较,应有5种情况: X=Y=Z 显示2

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论