汇编语言程序结构

上传人:猪** 文档编号:243386025 上传时间:2024-09-22 格式:PPT 页数:102 大小:1.42MB
返回 下载 相关 举报
汇编语言程序结构_第1页
第1页 / 共102页
汇编语言程序结构_第2页
第2页 / 共102页
汇编语言程序结构_第3页
第3页 / 共102页
点击查看更多>>
资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第一章 基础知识,循环与分支程序设计,1),分析题意,确定算法。这一步是能否编制出高质量程序的关键,因此不应该一拿到题目就急于写程序,而是应该仔细地分析和理解题意,找出合理的算法及适当的数据结构。,2),根据算法画出程序框图。这一点对初学者特别重要,这样做可以减少出错的可能性。画框图时可以从粗到细把算法逐步地具体化。,3),根据框图编写程序。,4),上机调试程序。任何程序必须经过调试才能检查出你的设计思想是否正确以及你的程,序是否符合你的设汁思想。在调试程序的过程中应该善于利用机器提供的调试工具(如,DEBUG,),来进行工作,你会发现它会给你提供很大的帮助。,编制一个汇编语言程序的步骤,分析问题,寻找解决问题的思路、方法、算法,描述算法,编写程序实现算法,设计测试数据和预期计算结果,上机调试程序,程序设计的解题基本步骤如下,:,顺序,、,分支,、,循环,程序和,子程序,的设计是汇编语言程序设计的基本内容。,在此基础上还要掌握汇编语言程序设计的基本方法和技巧 ,包括,递归子程序,设计、,COM,和,EXE,格式程序,的结构和特点、,多模块程序,设计方法等。,一、汇编语言程序设计的基本方法,概述,概述,二、程序的基本结构,1,、顺序结构程序,2,、分支结构程序,3,、循环(重复)结构程序,顺序结构 分支结构 循环(重复)结构,第一节 顺序结构程序设计,顺序结构程序完全按指令书写的前后顺序执行每一条指令,是最基本、最常见的程序结构,特点,顺序性、结构简单,只适应于简单问题的处理,例,1,计算,例,2,移位,第二节:循环结构,结束,初始化,循环的初始状态,循环体,循环的工作部分,及修改部分,计数控制循环,条件控制循环,修改部分,控制条件,Y,N,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,循环程序设计,根据条件重复执行一段指令就构成了循环程序结构,。,MOV AX,,,0,;,累加求和寄存器清,0,MOV BX,,,OFFSET ARRAY,;,数组始址送,BX,中,MOV CX,,,50,;,循环控制计数初始化,AGAIN,:,ADD AX,,,BX,ADD BX,,,2,;,数组地址增,2,,,BX,指向下一个元素,DEC CX,;,循环控制计数减,1,JNZ AGAIN,;,计数不为,0,时继续循环,MOV S,,,AX,;,计数为,0,时循环结束,和存于,S,中,保证循环正常执行和结束的条件:,正确地,初始化,循环控制计数和初始条件,正确地,检测,循环条件,必须保证能,达到循环结束条件,(,例如在循环体内有,修改循环控制值,的指令),例:,将,ARRAY,数组中的,50,个数求和,并将和存入字变量,S,中,。,指令系统提供了专门用于循环结构的,循环控制指令,,更加简便的地实现循环结构。,循环控制指令,循环控制指令的转移范围为:,-,128,+127,字节,(,2,)等于继续循环指令,格式:,LOOPZ/LOOPE,标号,(,3,)不等于继续循环指令,格式:,LOOPNZ/LOOPNE,标号,LOOP AGAIN,(段内短转移),格式:,LOOP,标号,操作: 如图所示,(,1,),LOOP,指令,(CX),0,?,执行循环体,(CX) (CX),-,1,是,否,退出循环,(CX),0,且,ZF =1 ?,(CX),0,且,ZF=0 ?,在前面的求和例子中,可用一条循环指令代替两条指令:,DEC CX,JNZ AGAIN,MOV CX,,,80,MOV SI,,,-,1,MOV AL,,,$,AGAIN,:,INC SI,CMP AL,,,STRSSI,LOOPNE,AGAIN,MOV LEN,,,SI,循环程序设计方法,控制循环的方法可分为两类:,计数循环,用于循环次数已知的情况,条件循环,用于循环次数不确定的情况,设,: STRS,DB,string$,例,:,求,存放在,STRS,存储区中的,字符串长度。,例,:,将字变量,num,中的数按,16,位,二进制数位,分离开,,逐位,转换为,ASCII,码,,并从最高有效位开始依次逐位存入以,binbuf,为起始地址的,16,个字节单元中。,设:,(,num,),=,4230H,要求将,4230H=,0 1 0 0,0 0 1 0,0 0 1 1,0 0 0 0 B,逐位分离开,并转换为:,30 31 30,30,30 30 31 30,30 30 31 31,30 30 30 30,先将(,num,),-,(,DX,),再讨论如何分离开各二进制位并转换为,ASCII,码,,分析如下,:,根据上述分析,将(,DX,),中的二进制数依次,循环左移,1,位,,可以使得,各个数位的分离,(,AND,)和,ASCII,码转换,(,ADD,),操作完全相同,便于组织循环,并且,循环次数已知,(,16,次,)。,例,:,将,十进制数(,number,),转换为八进制数,方法,:,(,number,),/8,保留余数,,除法操作,循环次数事先未知,,仅当商为,0,时,循环结束。,此例为条件循环,此例为计数循环,next,(DX)= 0 1 0 0,0 0 1 0,0 0 1 1,0 0 0 0,1 0 0,0 0 1 0,0 0 1 1,0 0 0 0,0,(,ROL DX,,,1,),0 0 0 0,0 0 0 1,(,AND,?,,1,),0 0 0 0,0 0 0,0,+,0 0 1 1,0 0 0,0,(,ADD,?,,30H,),0 0 1 1 0 0 0,0,30,0 0,0 0 1 0,0 0 1 1,0 0 0 0,0 1,(,ROL DX,,,1,),0 0 0 0,0 0 0 1,(,AND,),0 0 0 0,0 0 0,1,+,0 0 1 1,0 0 0 0,(,ADD,),0 0 1 1 0 0 0,1,31,0 1 0 0,0 0 1 0,0 0 1 1,0 0 0 0,(ROL DX,1),0 0 0 0,0 0 0 1,(,AND,),0 0 0 0,0 0 0,0,+,0 0 1 1,0 0 0 0,(,ADD,),0 0 1 1 0 0 0,0, ,30 31 30,30,30,30,31 30,30,30,31,31,30,30,30,1.,2.,16.,binbuf,返回,30,例,统计,AX,中的二进制数含“,1,”,的总个数,程序段如下:,MOVCX,,,0,AGAIN,:,ANDAX,,,AX,;,(,AX,),=0?,JZQUIT,;,是,退出循环,SALAX,,,1,;,否,(,AX,),的最高位移入,CF,位,JNCNEXT,;,CF1,时,转向,NEXT,再次循环,INCCX,;,CF=1,,,计数器,(CX)(CX) +1,NEXT,:,JMPAGAIN,;,再次循环,QUIT,:,上述程序为,当型循环,程序结构:,先判断条件,后执行循环,。,课堂练习,:,采用循环结构完成自然数,1,到,100,的求和运算。,next,当型循环与直到型循环,:,存储模型与简化段定义伪指令,较新版本的汇编程序(,MASM5.0,与,MASM6.0,)除支持完整段定义伪指令外,还提供了一种新的简单易用的存储模型和简化的段定义伪指令。,1, 存储模型伪指令,存储模型的作用是什么呢?存储模型决定一个程序的规模,也确定进行子程序调用、指令转移和数据访问的缺省属性(,NEAR,或,FAR,)。当使用简化段定义的源程序格式时,在段定义语句之前必须有存储模型,.MODEL,语句,说明在存储器中应如何安放各个段。,MODEL,伪指令的常用格式如下: ,MODEL,存储模型,存储模型,功 能,适用操作系统,Tiny (,微型,),所有数据和代码都放在一个段内,其访问都为,NEAR,型,整个程序,64K,,并会产生,.COM,文件。,MS-DOS,Small (,小型,),所有代码在一个,64KB,的段内,所有数据在另一个,64KB,的段内(包括数据段,堆栈段和附加段)。,MS-DOSWindows,Medium (,中型,),所有代码,64K,时可放在多个代码段中,转移或调用可为,FAR,型。所有数据限在一个段内,,DS,可保持不变。,MS-DOSWindows,Compact(,紧凑型,),所有代码限在一个段内,转移或调用可为,NEAR,型。数据,64K,时,可放在多个段中。,MS-DOSWindows,Large (,大型,),允许代码段和数据段都可超过,64K,,被放置在有多个段内,所以数据和代码都是远访问。,MS-DOSWindows,Huge (,巨型,),单个数据项可以超过,64K,,其它同,Large,模型,MS-DOSWindows,Flat (,平展型,),所有代码和数据放置在一个段中,但段地址是,32,位的,所以整个程序可为,4GB,。,MASM 6.0,支持该模型。,OS/2,WindowsNT,在,DOS,下用汇编语言编程时,可根据程序的不同特点选择前,6,种模型,一般可以选用,SMALL,模型。另外,,TINY,模型将产生,COM,程序,其他模型产生,EXE,程序。,FLAT,模型只能运行在,32,位,x86 CPU,上,,DOS,下不允许使用这种模型。当与高级语言混合编程时,两者的存储模型应当一致,2, 简化的段伪指令,简化的段定义语句书写简短,语句,.CODE,、,.DATA,和,.STACK,分别表示代码数据段和堆栈段的开始,一个段的开始自动结束前面一个段。采用简化段指令之前必须有存储模型语句,.MODEL,。,简化段伪指令,功 能,注释,.CODE ,段名,创建一个代码段,段名为可选项,如不给出段名,则采用默认段名。对于多个代码段的模型,则应为每个代码段指定段名。,.DATA,创建一个数据段,段名是:,_DATA,.DATA?,创建无初值变量的数据段,段名是:,_BSS,.FARDATA ,段名,建立有初值的远调用数据段,可指定段名,如不指定,则将以,FAR_DATA,命名。,.FARDATA? ,段名,建立无初值的远调用数据段,可指定段名,如不指定,则将以,FAR_BSS,命名。,.CONST,建立只读的常量数据段,段名是:,CONST,.STACK ,大小,创建一个堆栈段并指定堆栈段大小,段名是:,stack,。如不指定堆栈段大小,则缺省值为,1KB,3,与简化段定义有关的预定义符号,汇编程序给出了与简化段定义有关的一组预定义符号,它们可在程序中出现,并由汇编程序识别使用。有关的预定义符号如下:(,1,),code,由,.CODE,伪指令定义的段名或段组名。(,2,),data,由,.DATA,伪指令定义的段名,或由,.DATA,、,.DATA?,、,.CONST,和,.STACK,所定义的段组名。(,3,),stack,堆栈段的段名或段组名。,在完整的段定义情况下,在程序的一开始,需要用段名装入数据段寄存器,例,mov,ax,data_seg1,mov,ds,ax,若用简化段定义,则数据段只用,.data,来定义,而并未给出段名,此时可用,mov,ax,data,mov,ds,ax,这里预定义符号,data,就给出了数据段的段名。,返回,参考答案,2,:,.model small,.code,mov,ax, data,mov,ds, ax,xor,ax, ax,mov,cx, 100,again: add ax,cx,loop again,mov,ax, 4c00h,int,21h,end,参考答案,1,:,.model small,.data,num,dw,1,.code,mov,ax, data,mov,ds, ax,mov,ax, 0,mov,cx, 100,again: add ax, num,inc num,loop again,mov,ax, 4c00h,int,21h,end,(,下述例子可用,5.X,或,6.X,版汇编程序汇编,),思考题:显示下面数组中的数据:,ARRAY DB 1,,,3,,,7,,,8,,,5,,,4,,,6,,,8,第一章 基础知识,循环与分支程序设计,循环程序设计方法,例 试编制一个程序把,BX,寄存器内的二进制数用十六进制数的形式在屏幕上显示出来。,code_seg,segment,main proc far,assume,cs:code_seg,start:,mov,bx, 8222h,mov,ch, 4 ;,四位循环一次,共进行,4,次循环即可以,rotate:,mov,cl, 4 ;,循环高,4,位到低,4,位,rol,bx,cl,;,对,BX,进行循环操作,mov,al ,bl,;,思路:,四位二进制对应一位十六进制。,循环,4,次,每次循环,4,位,高位先显示:,rol,判断结果和,10,比较。,第一章 基础知识,循环与分支程序设计,and al , 0fh;,取出要转换的,4,位二进制数,存入,al,寄存器中,cmp,al , 10;,判断是否为十进制数制的字符,jae,changetoa_f,;,如果大于,10,,跳转到,changetoa_f,进行十六进制的转换,add al , 30h ;0-9,的十六进制转换,jmp,disp,changetoa_f,:,add al , 37h ;a-f,的十六进制转换,disp,:,mov,dl , al ;,在屏幕上显示结果,mov,ah , 02,int,21h,dec,ch,;,利用,dec,和,jnz,来实现循环操作,代替,loop,的功能,jnz,rotate,第一章 基础知识,循环与分支程序设计,mov,ax , 4c00h,int,21h,main,endp,code_seg,ends,end start,;,程序结束,例 在,ADDR,单元中存放着数,Y,的地址,试编制一程序把,Y,中,1,的个数存入,COUNT,单元中。,算法:要测出,Y,中,1,的个数就应逐位测试,一个比较简单的办法是可根据最高有效位是否为,1,来记数,然后用移位的方法把各位数逐次移到最高位去。循环的结束可以用计数值为,16,来控制,但更好的办法是结合上述方法可以用测试数是否为,0,来作为结束条件,这样可以在很多情况下缩短程序的执行时间。此外考虑到,Y,本身为,0,的可能性,应该采用,WHILE,DO,的结构形式。,第一章 基础知识,循环与分支程序设计,程序框图,第一章 基础知识,循环与分支程序设计,程序:,data_seg,segment,Y,equ,020FH,number,dw,Y,addr,dw,number,count,dw,?,data_seg,ends,code_seg,segment,assume,cs:code_seg,ds:data_seg,main proc far,start:,mov,ax ,data_seg,mov,ds,ax,mov,cx,0,mov,bx,addr,mov,ax ,bx,repeat:,test ax,0ffffh,jz,result,jns,shift,inc,cx,shift:,shl,ax ,1,jmp,repeat,result:,mov,count ,cx,mov,ax,4c00h,第一章 基础知识,循环与分支程序设计,int,21h,main,endp,code_seg,ends,end start,例 在附加段中有一个首地址为,LIST,和未经排序的字数组,在数组的第一个字中存放着该数组的长度,数组的首地址已存放在,DI,寄存器中。,AX,寄存器中存放着一个数。要求编制一程序:在数组中查找该数,如果找到此数则把它从数组中删除。,算法: 这一程序应该首先查找数组中是否有,(AX),,,如果没有则不对数组作任何处理就结束程序。如果找到这一元素则应把数组中位于其前,(,指地址比该元素高,),的元素后移一个字,(,即向低,地址方向移动,),,并修改数组长度值。如果找到的元素正好位于数组末尾,则不必移动任何元素,只要修改数组长度值就可以。这里第一部分的查找元素可以使用串处理指令,第二部分的删除元素则可使用循环结构,,由于查找结束时就可以知道该元素的位置,因此可以作为循环次数已知的情况来设计。,第一章 基础知识,循环与分支程序设计,流程图:,第一章 基础知识,循环与分支程序设计,程序:,data_seg,segment,LIST,dw,10,0,11,22,33,44,55,66,77,88,99,data_seg,ends,code_seg,segment,assume,cs:code_seg,es:data_seg,main proc far,start:,mov,ax ,data_seg,;,代码段地址空间分配,mov,es, ax,cld,;,设置,DF=0,,,地址自动递增操作,mov,ax ,33,;,设置,AX,寄存器的数值,lea,di, LIST,第一章 基础知识,循环与分支程序设计,push,di,;将,LIST,的首地址压栈,为将来改变数组元素个数,就可以弹出该,;地址,mov,cx,es:di,;,数组个数放入,CX,中,add,di, 2,repnz,scasw,;将,AX,与,ES,:,DI,中的元素进行比较,若相等则跳转到,DELETE,;,结束否则,je,delete,pop,di,jmp,short exit,delete:,jcxz,del_last,;,判断要删除的元素是否为最后的数组元素,是就跳转到,;,DEL_LAST,执行,del_next:,第一章 基础知识,循环与分支程序设计,mov,bx,es:di,;,数组元素向前移动,mov,es:di-2 ,bx,add,di, 2,loop del_next,del_last:,pop,di,dec,word,ptr,es:di,;,改变数组元素的大小,exit:,mov,ax , 4c00h,int,21h,main,endp,code_seg,ends,end start,第一章 基础知识,循环与分支程序设计,例,试编制一程序;从键盘输入一行字符,要求第一个键入的字符必须是空格符,如不是则退出程序;如是则开始接收留入的字符并顺序存放在首地址为,BUFFER,的缓冲区中(空格符不存人),直到接收到第二个空格符时退出程序。,算法:,这一程序要求接收的字符从空格符开始又以空格符结束,因此程序中必须区分所接收的字符是否是第一个字符,为此设立作为标志的存储单元,FLAG,,,一开始将其置为,0,,接收第一个字符后可将其置,1,。,第一章 基础知识,循环与分支程序设计,data_seg,segment,buffer db 100 dup(?),flag db ?,data_seg,ends,code_seg,segment,assume,cs:code_seg,ds:data_seg,main proc far,start:,mov,ax ,data_seg,mov,ds,ax,lea,bx,buffer,mov,flag ,0,;,FLAG,初始化为,0,,准备接收第一个字符,next:,mov,ah ,01,第一章 基础知识,循环与分支程序设计,int,21h,;,从键盘输入一个字符,存放在,AL,寄存器中,test flag ,01h,;,判断是否为第一个字符,jnz,follow,;,不是第一个字符跳转到,FOLLOW,cmp,al,20h,;,是第一个字符,判断该字符是否为空格,jnz,exit,mov,flag ,1,jmp,next,follow:,cmp,al ,20h,;,判断是否为空格,jz,exit,;,是空格就退出,mov,bx,al,;,不是就将该字符的,ASC,码存入缓冲区内,inc,bx,jmp,next,第一章 基础知识,循环与分支程序设计,exit:,mov,ax , 4c00h,int,21h,main,endp,code_seg,ends,end start,第一章 基础知识,循环与分支程序设计,(,3,)多重循环,第一章 基础知识,循环与分支程序设计,例 有一个首地址为,A,的,N,字数组,请编制程序使该数组中的数按照从大到小的次序排序。,算法 : 我们采用起泡排序算法从第一个数开始依次对相邻两个数进行比较,如次序对则不做任何操作;如次序不对则使这两个数交换位置。下表表示了这种算法的例子,可以看出在做了第一遍的,(N,一,1),次比较后,最小的数已经放到了最后,所以第二遍比较只需要考虑,(N-1),个数,即只需要比较,(N,一,2),次,第三遍则只需要做,(N,一,3),次比较,总共最多,(N1),遍比较就可以完成排序。,第一章 基础知识,循环与分支程序设计,loop1:mov,dx,cx,mov,bx, 0,loop2:mov ax ,abx,cmp,ax ,abx+2,jge,continue,xchg,ax ,abx+2,mov,abx,ax,continue:,add,bx,2,loop loop2,mov,cx,dx,loop loop1,mov,cx,num,程序:,data_seg,segment,num,dw,10,a,dw,12,14,9,10,3,81,10,4,88,66,data_seg,ends,code_seg,segment,assume,cs:code_seg,ds:data_seg,main proc far,start:,mov,ax ,data_seg,mov,ds, ax,mov,cx, num,dec,cx,第一章 基础知识,循环与分支程序设计,mov,si,offset a,mov,bl,0ah,call,dispchar,mov,bl, 0dh,call,dispchar,dispdec2:,mov,bx,si,call,disp,mov,bl, ,call,dispchar,add,si,2,loop dispdec2,mov,ax ,4c00h,int,21h,main,endp,code_seg,ends,end start,第一章 基础知识,循环与分支程序设计,第二节 分支结构程序设计,第一章 基础知识,循环与分支程序设计,(,2,),分支程序设计方法,例,在附加段中,有一个按从小到大顺序排列的无符号数的数组,其首地址存放在,Dl,寄存器中,,数组中的第一个单元存放着数组长度。,在,AX,中有一个无符号数,要求在数组中查找,(AX),,,如找到则使,CF,0,,,并在,SI,中给出该元素在数组中的偏移地址,如末找到则使,CF,1,。,算法:,我们已经遇到过多个表格查找的例子,都是使用顺序查找的方法,本例是一个已经排序的数组,可以采用,折半查找法,以提高查找效率。折半查找法先取有序数组的中间元素与查找值进行比较,如相等则查找成功,如查找值大于中间元素,则再取高半部的中间元意与查找值相比较;如查找值小于中间元素,则再取低半部的中间元素与查找值相比较,如此重复直到查找成功或最终未找到该效,(,查找不成功,),为止。折半查找法的效率高于顺序查找法。,第一章 基础知识,循环与分支程序设计,流程图,:,第一章 基础知识,循环与分支程序设计,程序:,;,本模块功能是用寄存器,AX,的内容对字数组,(,从小到大顺序排列,),进行折半查找,;,其中查找的数组首地址位于寄存器,DI,内,;,数组的第一个元素为数组的长度,其余的为数组的具体内容,dseg,segment,start_addr,dw,?;,保存数组首地址用的变量,dseg,ends,cseg,segment,assume,cs:cseg,ds:dseg,b_search proc near,push,ds,push ax,mov,ax ,dseg,mov,ds,ax,第一章 基础知识,循环与分支程序设计,;,第一步,;,首先判断,AX,寄存器的数是否在该数组的范围内,.,;,即要判断是否小于数组元素的最小数或大于数组元素的最大数,cmp,ax ,es,: di+2;,和最小数据进行比较,ja,chk_last,;,若大于最小数,跳转到,CHK_LAST,,,同时,CF,为,0,lea,si,es,: di+2;,先把最小元素的地址存入,SI,寄存器中,je,exit_b;,在判断是否和最小元素相等,如果相等结束,stc,;,否则小于最小元素,设置,CF,为,1,jmp,exit_b;,程序结束,chk_last,:,mov,si,ES,: ,di;si,存放数组元素个数,shl,si,1;,也就是,2,。其结果就是数组占用的字节数量,add,si,di;SI,为数组下标最大的元素的地址,第一章 基础知识,循环与分支程序设计,cmp,ax,es:si,;,和最大数进行比较,同时,CF,为,1,jb,search;,若小于最大数,就进入折半查找,je,exit_b;/,否则等于最大值则退出结束,表明,AX,的数据与最大数组数据相同,.,stc,;,置,CF,为,1,jmp,exit_b,;,第一步结束,;,第二步,;,折半查找功能,search:,mov,start_addr,di,;,保存寄存器,DI,的字数组的首地址,mov,si,di,;,读取数组长度,第一章 基础知识,循环与分支程序设计,even_idx,:,test si,1;,判断是否为奇数,.,注意数组长度的地址指定数组中间的元素,(,因为数组是字数组,),jz,add_idx,inc,si,;,奇数就要加,1,以便能取到完整的数据,add_idx,:,add,di,si,;,数组首地址加上中间数组的偏移量,得到中间数组的有效地址,compare:,cmp,ax,es,: ,di,;,和寄存器数据进行比较,je,all_done;,相等,就结束操作,同时,CF,为,0,ja,highter,;,大就查找高段数组,cmp,si,2,jne,idx_ok,第一章 基础知识,循环与分支程序设计,no_match:,stc,je,all_done ;,寄存器,si,和,2,进行比较的结果,程序退出的标志,idx_ok,:,shr,si,1,test si,1,jz,sub_idx,inc,si,sub_idx,:,sub,di,si,jmp,short compare,第一章 基础知识,循环与分支程序设计,higher:,cmp,si,2;,je,no_match,shr,si,1;,数据元素除以,2,,减半,jmp,short,even_idx,all_done,mov,si,di,mov,di,start_addr,exit_b:,ret,b_search,endp,cseg,ends,end b_search,第一章 基础知识,循环与分支程序设计,(,3,)跳跃表法,第一章 基础知识,循环与分支程序设计,例:根据,bx,的数据进行跳转,从低位到高位分别判断,bx,寄存器的位数是否为,1,,为,1,跳转,否则继续判断,直到,bx,寄存器为,0,。,程序:,b_a segment,b_t,dw,r1,dw,r2,dw,r3,dw,r4,dw,r5,dw,r6,dw,r7,dw,r8,b_a ends,code segment,assume,cs:code,ds,: b_a,main proc far,start:,push,ds,xor,ax,ax,push ax,mov,ax , b_a,mov,ds, ax,第一章 基础知识,循环与分支程序设计,lea,si, b_t;,将表地址存入,si,寄存器,l:,cmp,bx, 0;,判断,bx,是否为零,jz,exit,shr,bx, 1;,将,bx,寄存器的最低位传入,CF,中,jnb,not_yet;,若,CF,为,0,,跳转不执行任何操作,jmp,word,ptrsi,not_yet:,add,si, type b_t,jmp,l,r1:,mov,dx,0,jmp,short exit,r2:,mov,dx,1,jmp,short exit,r3:,mov,dx,2,jmp,short exit,r4:,mov,dx,3,jmp,short exit,r5:,mov,dx,4,jmp,short exit,r6:,mov,dx,5,jmp,short exit,r7:,mov,dx,6,jmp,short exit,r8:,mov,dx,7,exit:,ret,main,endp,code ends,end start,第一章 基础知识,循环与分支程序设计,第三节 子程序结构,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,上述程序也可以采用如下方式:,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,;,SEGX,代码段,;,SEGY,代码段,;调用,SEGX,代码段的子过程,;,SUBT,必须具有,FAR,属性以适应,SEGY,段调用的需要。,SUBT,既有,PAR,属性,则不论在,SEGX,和,SEGY,段对,SUBT,的调用就都具有,FAR,属性了,这样不会发生什么错误,反之,如果这里的,SUBT,使用了,NEAR,属性,则在,SEGY,段内对它的调用就要出错了。,第一章 基础知识,循环与分支程序设计,(,1,)子程序使用过程中注意的问题,CALL,使返回地址入栈,所以,RET,时应该使返回地址出栈,如果子程序中不能正确使用堆栈而造成执行,RET,前,SP,并未指向进入子程序时的返回地址,则必然会导致运行出错,因此于程序中对堆栈的使用应该特别小心,以免发生错误。,CALL,指令和,RET,指令就完成了调用和返回的功能。为了保证其正确性,除,PROC,的属性要正确选取外,还应该注意子程序运行期间的堆栈状态。,第一章 基础知识,循环与分支程序设计,调用程序,(,又称主程序,),和子程序经常是分别编制的,所以它们所使用的寄存器往往,会发生冲突。,如果主程序在调用子程序以前的某个寄存器内容在从子程序返回后还有用而子程序又恰好使用了同一个寄存器,造成破坏了该寄存器的原有内容,那就会造成程序运行错误,这是不能允许的。,第一章 基础知识,循环与分支程序设计,为避免这种错误的产生在一进入子程序后就应该把子程序所需要使用的寄存器内容保存在堆栈中,而在退出子程序前把寄存器的内容恢复原状。,第一章 基础知识,循环与分支程序设计,(,2,)主程序与子程序参数传递,含义:将,dl,中的字符在屏幕上显示出来,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,程序:,decihex,segment,assume,cs:decihex,main proc far,mov,cx, 10,repeat:,call,decibin,call,crif,call,binihex,call,crif,loop repeat,mov,ax , 4c00h,int,21h,main,endp,decibin,proc near,;,十进制转换为二进制数据,mov,bx,0,;,转换结果存放在,BX,寄存器中,newchar,:,mov,ah,1,;,从键盘读取数据,int,21h,sub al,30h,;,转换为数制,jl,exit,;,小于,30H,不是数字键,cmp,al,9d,jg,exit,;,大于,9,也不是数字键,cbw,xchg,ax,bx,mov,cx,10d,mul,cx,xchg,ax,bx,add,bx,ax,;,加入,BX,中,jmp,newchar,exit:,ret,decibin,endp,第一章 基础知识,循环与分支程序设计,binihex,proc near,mov,ch,4,rotate:,mov,cl,4,rol,bx,cl,mov,al,bl,and al,0fh,add al,30h,cmp,al,3ah,jl,print,add al,7h,print:,mov,dl,al,mov,ah,2,int,21h,dec,ch,jnz,rotate,ret,binihex,endp,crif,proc near,mov,dl,0dh,;,换行,mov,ah,2,int,21h,mov,dl,0ah,;,mov,ah,2,int,21h,ret,crif,endp,decihex,ends,end main,远程调用,codeb,segment,assume,cs:codeb,btodecdisp,proc far,push ax,push,bx,push,cx,push,dx,mov,cx,0,;,mov,bx,1234h;,rotate1:,mov,ax,bx,cwd,mov,bx,10,div,bx,add dl,30h,push,dx,inc,cx,mov,bx,ax,;,mov,ax,bx,test ax,0ffffh,jnz,rotate1,repeat1:,pop,dx,mov,ah,2,int,21h,loop repeat1,pop,dx,pop,cx,pop,bx,pop ax,ret,btodecdisp,endp,btohexdisp,proc far,push ax,push,bx,push,cx,push,dx,mov,ch,4,mov,cl,4,rotate2:,rol,bx,cl,mov,al,bl,and al,0fh,cmp,al,10,jc,decimal2,add al,37h,jmp,dispp2,decimal2:,add al,30h,dispp2:,mov,dl,al,mov,ah,2,int,21h,dec,ch,jnz,rotate2,pop,dx,pop,cx,pop,bx,pop ax,ret,btohexdisp,endp,btoo,proc far,push ax,push,bx,push,cx,push,dx,mov,cl, 1,mov,ax ,bx,loopto,:,mov,bx, ax,rol,bx,cl,cmp,cl, 1,jz,too,and,bx, 0007h,jmp,tooo,too:,and,bx, 0001h,tooo,:,xchg,bl, dl,add dl , 30h,xchg,ax ,bx,mov,ah , 2,int,21h,xchg,ax ,bx,shl,ax ,cl,jz,exit3,mov,cl, 3,jmp,loopto,exit3:,pop,dx,pop,cx,pop,bx,pop ax,ret,btoo,endp,codeb,ends,code segment,assume,cs:code,main proc far,mov,bx,5678H,call,btodecdisp,call,btohexdisp,call,btoo,mov,ah,4ch,int,21h,main,endp,code ends,end main,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,例 从键盘输入十进制数据,以十六进制显示在屏幕上,文件,asm_0.asm,public xyz,public,crlf,data segment public,xyz,dw,9,data ends,decihex,segment public,assume,cs:decihex,crlf,proc near,mov,dl,0dh,mov,ah,2,int,21h,mov,dl,0ah,mov,ah,2,int,21h,ret,crlf,endp,decihex,ends,end,第一章 基础知识,循环与分支程序设计,文件,2,:,asm_1.asm,extrn,crlf:near,extrn,xyz:word,decihex,segment public,assume,cs:decihex,start:,mov,ax,seg,xyz,mov,ds, ax,mov,ax , xyz,call,decibin,call,crlf,call,binihex,call,crlf,mov,ax , 4c00h,int,21h,decibin,proc near,mov,bx,0,newchar,:,mov,ah,1,int,21h,sub al,30h,jl,exit,cmp,al,9d,jg,exit,cbw,xchg,ax,bx,mov,cx,10d,mul,cx,xchg,ax,bx,add,bx,ax,jmp,newchar,exit:,ret,decibin,endp,binihex,proc near,mov,ch,4,rotate:,mov,cl,4,rol,bx,cl,mov,al,bl,and al,0fh,add al,30h,cmp,al,3ah,jl,print,add al,7h,print:,mov,dl,al,mov,ah,2,int,21h,dec,ch,jnz,rotate,ret,binihex,endp,decihex,ends,end start,第一章 基础知识,循环与分支程序设计,运行:,masm,asm_0.asm,形成,asm_0.obj,masm,asm_1.asm,形成,asm_1.obj,link asm_0.obj asm_1.obj,形成,asm_0.exe,执行文件,link asm_1.obj asm_0.obj,形成,asm_1.exe,执行文件,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,code_seg,segment,org 100,table,dw,3 dup(?),ary1,dw,10,20,30,40,50,count1,dw,5,sum1,dw,?,ary2,dw,10,20,30,40,50,count2,dw,5,sum2,dw,?,assume,cs:code_seg,ds:code_seg,ss:code_seg,main proc far,start:,mov,ax,code_seg,mov,ds,ax,mov,ss,ax,mov,table ,offset ary1,mov,table+2 , offset count1,mov,table+4 , offset sum1,call near,ptr,proadd,mov,si, table+4,mov,bx, ,si,call,disp,mov,table ,offset ary2,mov,table+2 , offset count2,mov,table+4 , offset sum2,call,proadd,mov,si, table+4,mov,bx, ,si,call,disp,mov,ax,4c00h,int,21h,main,endp,第一章 基础知识,循环与分支程序设计,;,以十进制显示,BX,寄存器中,的数据,disp,proc near,push ax,push,dx,push,cx,mov,cx,0,disp_next,:,mov,ax,bx,cwd,mov,bx, 10,div,bx,add dl,30h,push,dx,inc,cl,mov,bx,ax,cmp,ax , 0000h,jz,exit,jmp,disp_next,exit:,mov,ah,02h,print:,pop,dx,int,21h,dec,cl,jnz,print,pop,cx,pop,dx,pop ax,ret,disp,endp,;,显示模块结束,proadd,proc near,push,si,push,di,push,cx,push ax,mov,si, table,mov,di, table+2,mov,cx,di,mov,di, table+4,xor,ax,ax,next:,add,ax,si,add,si,2,loop next,mov,di, ,ax,pop ax,pop,cx,pop,di,pop,si,ret,proadd,endp,code_seg,ends,end start,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,堆栈段最满时的状态:,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,可以由一连串常数表达式组成,每个字段用一个表达式,相互之间用逗号隔开,如果使用,STRUC,定义中的值则可不写任何值,(,缺省,),。,预赋值说明也可以使用,DUP,操作符。,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,第一章 基础知识,循环与分支程序设计,程序:,data_seg,segment,n_v,dw,6,result,dw,?,data_seg,ends,stack_seg,segment,;,定义堆栈段,dw,128 dup(?),tos,label word,;,确定栈顶指针,stack_seg,ends,code1_seg segment,assume cs:code1_seg ,ss:stack_seg,ds:data_seg,main proc far,start:,mov,ax ,data_seg,mov,ds, ax,mov,ax ,stack_seg,mov,ss, ax,mov,sp , offset top,mov,bx, offset result,push,bx,第一章 基础知识,循环与分支程序设计,mov,bx, n_v,push n_v,call far,ptr,fact,mov,bx, result,call near,ptr,disp,mov,ax , 4c00h,int,21h,ret,main,endp,;,以十进制显示,BX,寄存器中的数据,disp,proc near,push ax,push,dx,push,cx,mov,cx,0,disp_next,:,mov,ax,bx,cwd,mov,bx, 10,div,bx,add dl,30h,push,dx,inc,cl,mov,bx,ax,cmp,ax , 0000h,jz,exit,jm
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 小学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!