第五节基本结构程序设计方法一、顺序程序设计二、分支程序设计三、循环程序设计四、子程序设计概述汇编语言程序设计的一般步骤流程图汇编语言程序设计的一般步骤汇编语言程序设计一般有以下几个步骤:1.分析问题,确定算法2.绘制流程图3.根据流程图编制程序4.调试程序流程图1.流程图的概念流程图是由特定的几何图形、指向线、文字说明来表示数据处理的步骤,形象描述逻辑控制结构以及数据流程的示意图。流程图具有简洁、明了、直观的特点。2.流程图符号表示(1)起止框:表示程序的开始和结束。•起止框(2)判断框(3)处理框(4)调用框(5)指向线(6)连接框一、顺序程序设计顺序结构顺序结构的程序一般是简单程序,其特点是程序顺序执行,无分支,无循环与转移。例4.4内存中TABLE开始存放0~9的平方值,通过人机对话,对任意给定的数(0~9),查表得的平方值,将其放在AL中。datasegmenttabledb0,1,4,9,16,25,36,49,64,81dufdb’pleaseinputontnumber(0~9):’0dh,0ah,’$’dataendsstacksegmentparastack’stack’stapadb100dup(?)codesegmentassumecs:code,ds:data,ss:stack8start:pushaxmovax,datamovds,axmovax,stackmovss,axmovsp,topmovbx,offsettablenext:movdx,offsetbuf;9号功能调用,显示字符串,提示输入一个数movah,9int21h9movah,1;1号功能调入,等待键入一个数且送ALint21hmovah,0;查表得键入数的平方值andal,0fh;屏蔽高4位addbx,axmoval,[bx]movah,4chint21hcodeendsendstart二、分支结构一个大的程序完全顺序结构实际上并不可能,经常会遇到有分支的情况,分支结构程序通常采用条件转移或转移表来实现。典型的分支结构如教材图4.3所示。下面举例说明分支结构:例4.5给符号函数建立标志。=1当>0符号函数y=0当=0=-1当<0要实现符号函数,只要把从内存中取出来,执行一次“与”或“或”操作,就可以把的数值特征反映在标志上,再根据标志来转移。程序框图如教材图4.4所示。源程序如下:datasegmentxdw15ydw?dataendsstacksegmentstack’stack’db100dup(?)stackendscodesegmentassumecs:code,ds:data,ss:stackstart:pushaxmovax,datamovds,axmovax,xandax,axjzxerojnszeromovbx,offffhjmpdonezero:movbx,0jmpdoneplus:movbx,1done:movy,bxmovah,4chint21hcodeendsendstart三、循环结构循环结构是程序设计中最常用的结构。凡需要重复做的工作,在计算机中都可以用循环结构程序来实现。循环程序有两种结构形式,一种是“先执行,后判断”,另一种为“先判断,后执行”。这后一种结构实现上允许0次循环,因而对有些程序更有效,它适合于循环次数不固定的程序。循环程序的常见结构形式无论哪种循环结构,都包括以下四个部分:(1)初始化:为循环作准备,设置循环计数值,设置变量初值。(2)循环体:循环部分的核心,包括循环的全部指令。(3)修改参数:修改操作数地址,为下次循环作准备。(4)循环控制:修改计数器值,判断循环控制条件,决定是否跳出循环。对“先执行,后判断”结构,进入循环后至少要执行一次循环体,再判判断循环是否结束。对“先判断,后执行”结构,进入循环后,先判断循环结构条件,再决定是否执行循环体,可能循环体一次也不执行,即循环次数为0。例4.6若将内存2000H:0100H开始的256个字节的数据块移动到内存2000H:0200Hmovax,2000h;初始化,为循环工作准备movds,axmovsi,0100h;设置源数据块地址指针movdi,0200h;设置目的地址指针movcx,100h;设置循环次数next:moval,[si];循环体mov[di],alincsi;修改参数incdiloopnext;循环控制movah,4chint21h18例4.7BX寄存器中有一个16位二进制数,编程统计该数中1的个数,将其结果放到CL寄存器中。xorcl,cl;初始化,为循环作准备lopl:andbx,bx;循环控制jzstopshlbx,1:循环体jnclop1inccljmplop1stop:movah,4ch;程序中止int21h有些循环结构比较复杂,需要用多重循环完成。多重循环设计方法与单重循环设计方法相,但应注意:(1)各重循环的初始控制条件及程序实现。(2)内循环可以嵌套在外循环中,也可以多层嵌套,但各层循环这间不能交叉,可以从内循环跳到外循环,不可以从外循环中直接跳进内循环。(3)防止出没死循环,即不能让循环回到初始条件,引起死循环。例4.8设有N个符号数,要求将这N个数由小到大排列。采用冒泡排序法。从第一个数据开始相信的数进行比较,若次序不对,两数交换位置。第一遍就完成了排序,这样共有两重循环datasegmentbufdb15h,37h,86hdb0a7h,0c8h,90h,7eh,50hdb80h,23hcoutequ$-bufdataendsstacksegmentstack’stack’sapdb100dup(?)topequlengthsapstackendscodesegmentassumecs:code,ds:data,ss:stackstart:movax,datamovds,axmovax,stackmovss,axmovsp,topmovbx,offsetbufmovcx,cout-122lpo1:movdx,cxlpo2:moval,[bx]cmpal,[bx+1]jlenextxchgal,[bx+1]mov[bx],almext:incbxlooplop2movcx,dxlooplop1movah,4chint21hcodeendsendstart四、子程序结构若一段指令语句在一个程序中多次使用,或在多个程序中用到,则通常把这段指令语句当作一个独立的模块处理,这段模块称为子程序或“过程”。需要执行这个模块时,就进行过程调用,执行完毕后,再返回原来调用它的程序。采用子程序结构编程,使程序结构模块化,清晰明了,容易修改。在汇编语言中,每一个子程序都包括在过程定义语句PROC…ENDP中间。过程定义有属性NEAR或FAR,若调用子程序的程序在同一代码段中,则用NEAR属性,若不在同一段中,使用FAR属性。1.子程序清单通常编写子程序或过程时,写一个子程序说明或清单,能使模块结构一目了然,且使调用者知道如何使用该程序。子程序清单包括:(1)子程序的名称,功能说明;(2)子程序中用到的寄存器和存储单元;(3)子程序的入口参数,出口参数;(4)子程序中调用其他子程序的名称。252.参数传递方法主程序与子程序相互之间可以传递参数。在许多情况下,希望子程序更具有通用性,更灵活,这时就希望子程序除了有使用说明外,还能够接受调用程序传来的入口参数,在子程序执行完毕后把出口参数传递给调用程序。参数的传递通有三种方法:(1)用寄存器传递:适合于参数较少的情况,传递速度较较快;(2)用存储器传递:适合参数较多的情况,需要先在存储器中建立一个参数表。(3)用堆栈传递:适合于参数较多且子程序有嵌套、递归调用的情况。26例4.11在数据段中定义了两个数组,编程实现数组分别求和。datasegmentart1db12,23,34,45,56,67,78,89,90,18contlequ$-ary1sum1dw?ary2db13h,24h,57h,68h,9ah,0bch,0cdh,0deh,80h,80hcont2equ$-ary2sum2dw?dataendscodesegmentassumecs:code,cs:data27start:movax,datamovds,axleasiary1;入口参数,数据块1首址movcx,cont1;入口参数,数据块1长度callsum;调用求和子程序leasi,ary2;入口参数,数据块2首址movcx,cont2;入口参数,数据块2长度callsummovah,4chint21hsumproc;子程序sumxorax,ax;ax清0,存放和next1:addal,[si];数组元素相加adcah,0;高位放在ah中incsiloopmext1mov[si],ax;数组和存入内存单元retsumendpcodeendsendstar【例4.8】试编写一程序,要求比较两个字符串STR1和STR所含字符是否相同,若相同则显示‘MATCH!’,若不相同则显示‘NOMATCH!’。(程序略)其流程图如图4.7所示。•图4.7程序流程图【例4.9】试编一个程序将字单元BUF中所含1的个数存入COUNT单元中。要测出BUF字单元所含1的个数,首先将BUF中的数送给寄存器AX,然后将AX寄存器逻辑左移一次,如果CF=1,则表明AX中的最高位为1,则计数器CL计数1次,如果CF=0,表明AX最高位为0,这样依次将最高位移入CF中去测试。移位之后,判断AX的值是否为0,如果为0则结束循环,不为0,则继续循环。其流程图如图4.8所示。2.条件控制程序如下:STACKSEGMENTSTACKDB200DUP(0)STACKEDNSDATASEGMENTBUFDW0011110010101011BCOUNTDB?DATAENDSCODESEGMENTASSUMEDS:DATA,CS:CODE,SS:STACKSTART:MOVAX,DATAMOVDS,AXMOVAX,BUFMOVCL,0;计数器为0LOPA:ANDAX,AX;使CF位为0JEEXIT;(AX)=0,结束循环SHLAX,1;AX左移一位JNCLOPAINCCL;产生进位,(CL)+1→CLJMPLOPAEXIT:MOVCOUNT,CLMOVAH,4CHINT21HCODEENDSENDSTART4.4.3多重循环程序设计【例4.10】在以BUF为首址的字存储区中存放有N个有符号数,现需将它们按大到小的顺序排列在BUF存储区中,试编写其程序。我们采用冒泡排序算法从第一个数开始依次对相邻两个数进行比较,如次序对,则不交换两数位置;如次序不对则使这两个数交换位置。可以看出,第一遍需比较(N-1)次,此时,最小的数已经放到了最后;第二遍比较只需考虑剩下的(N-1)个数,即只需比较(N-2)次;第三遍只需比较(N-3)次,……整个排序过程最多需(N-1)遍。如下面的4个数即是采用冒泡排序比较的例子。数108169032第一遍101690328第二遍169032108第三遍903216108程序流程图如图4.9所示。程序如下:DATASEGMENTBUFDW3,-4,6,7,9,2,0,-8,-9,-10,20N=($-BUF)/2DATAENDSSTACKSEGNMENTSTACKDB200DUP(0)STACKENDSCODESEGMENTASSUMECS:CODE,DS:DATA,SS:STACKSTART:MOVAX,DATAMOVDS,AXMOVCX,NDECCX;设计数器CX内循环40