4.6.1顺序结构程序设计顺序结构程序也称为简单程序,这种结构的程序是按顺序执行下来的,程序本身的逻辑很简单,只要能正确安排有关语句的顺序,即可解决问题。4.6汇编语言程序设计在汇编语言程序中,主要有四种结构:顺序程序、分支程序、循环程序、子程序。顺序程序分支程序循环程序子程序图4-3四种基本程序结构的示意图例4-10编程实现123*456→MMDD?MOVAX,123MOVBX,456MULBXMOVM,AXMOVM+2,DX4.6.1顺序结构程序设计例4-11从键盘上键入0至9中任一个自然数,求其立方值。数据段定义如下:DATASEGMENTINPUTDB‘PLEASEINPUTX(0~9):$’TABDW0,1,8,27,64,125,216,343,512,729XDB?XXXDW?DATAENDS4.6.1顺序结构程序设计程序段如下:INT21H;用9号功能显示字符串MOVAH,1INT21H;从键盘输入一个字符ALANDAL,0FHMOVX,AL;将ASCII码转换成真值ADDAL,ALMOVBL,ALMOVBH,0;计算在表中的偏移量送BXMOVAX,TAB[BX];查表获得立方值MOVXXX,AX;将立方值保存在XXX单元4.6.1顺序结构程序设计4.6.2分支结构程序设计条件分支程序YNN分支1YNY分支2条件1.利用比较与条件转移实现分支例4-13求两个无符号数差的绝对值,结果存放在D1单元中。DATASEGMENTD1DB?D2DB0F5H,68HDATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXLEABX,D2MOVAL,[BX];取第1个数INCBX4.6.2分支结构程序设计MOVCL,[BX];取第2个数CMPAL,CL;两个数比较JAEBIGR;大于等于,则转BIGRSUBCL,AL;否则,第2个数减第1个数MOVD1,CL;两数差的绝对值存D1单元JMPRSTBIGR:SUBAL,CL;第1个数减去第2个数MOVD1,ALRST:MOVAH,4CHINT21HCODEENDSENDSTART4.6.2分支结构程序设计例4-14设在A、B、C字型变量中存放着3个数,若3个数均不为0,则求出它们的和(不考虑溢出)存入D单元。DATASEGMENTADW108BDW0CDW45DDW?DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AX4.6.2分支结构程序设计MOVBH,0;BH淸0MOVD,0;变量D淸0CMPA,0;判断变量A是否为0JNENT1;A非0则转去判断变量BINCBH;A为0则BH加1NT1:CMPB,0;判断变量B是否为0JNENT2;B非0则转去判断变量CINCBH;B为0则BH加1NT2:CMPC,0;判断变量C是否为0JNENT3;C非0则转去判断寄存器INCBH4.6.2分支结构程序设计NT3:CMPBH,0;判断寄存器BH是否为0JNEEXIT;BH非0则程序结束MOVAX,A;BH为0则求和并存入D单元ADDAX,BADDAX,CMOVD,AXEXIT:MOVAH,4CHINT21HCODEENDSENDSTART4.6.2分支结构程序设计2利用跳转表实现分支条件分支1分支2分支n……例4-15某工厂有n+1种产品R0、R1、R2、...、Rn的加工程序,分别存放在PR0、PR1、PR2、...PRn为首地址的内存区域中。而这n+1个首地址的偏移量连续存放在以BASE为基地址的跳转表中。已知产品编号存放在NUM单元中,要求编写程序,能够根据产品编号转至相应的处理程序。DATASEGMENTBASEDWPR0,PR1,PR2,...,PRn;定义跳转表NUMDB4DATAENDS4.6.2分支结构程序设计CODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXXORAX,AX;清AXMOVAL,NUM;取加工的产品编号iADDAX,AX;2*i,获得偏移量MOVBX,OFFSETBASE;获得跳转表首地址ADDBX,AX;获得对应的单元地址JMPBX;转入相应的加工子程序MOVAH,4CH;程序结束INT21H4.6.2分支结构程序设计PROPROCNEAR;加工子程序...PR0ENDP;PR1PROCNEAR...PR1ENDP;...PRnPROCNEAR...PRnENDPCODEENDSENDSTART4.6.2分支结构程序设计PR0BASEPR0PRnPR1PR2PRn….…4.6.2分支结构程序设计图4-5例4-15的跳转表4.6.3循环结构程序设计开始初始化部分循环工作部分循环控制部分循环结束部分循环修改部分未结束结束结束1.循环程序结构可分为五个部分。(1)初始化部分设置循环的初始值,是循环的准备部分。(2)循环体部分这是循环程序的主体,用来完成主要的计算任务和操作。(3)循环修改部分修改循环工作部分的变量地址等,为下一次循环作准备。(4)循环控制部分修改循环次数计数器并判断结束条件。(5)结束部分循环结束后,用于分析和存放结果。4.6.3循环结构程序设计2循环的控制方法(1)计数控制用于循环次数已知的情况。通常采用CX寄存器为循环计数器。循环计数控制一般用LOOP指令实现。(2)条件控制用于循环次数未知,但却已知一些循环或不循环的条件。(3)逻辑尺控制这是汇编语言循环程序设计独有的方式。所谓逻辑尺,是指具有一定长度的一串二进制数。该方式按照逻辑尺的指示,决定对循环体中某一部分的执行或不执行。4.6.3循环结构程序设计3.循环程序设计举例例4-16编程计算Y=a1+a2+…+a100。(其中ai为16位二进制整数,设和值不大于16位二进制整数表数范围)DATASEGMENTTABDWa1,a2,...,a100YDW?DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AX4.6.3循环结构程序设计XORAX,AX;初始化部分,累加和清0LEABX,TAB;BX指向加数首地址MOVCX,100;设置减计数初值LP:ADDAX,[BX];循环体开始,累加INCBX;修改部分,修改BXINCBXLOOPLP;控制部分,CX减计数MOVY,AX;结束部分,存放结果MOVAH,4CHINT21HCODEENDSENDSTART4.6.3循环结构程序设计例4-17写一个把字符串中的所有大写字母改写为小写字母的程序。设字符串以‘$’结尾。DATASEGMENTSTRINGDB‘IamAStudent!’,’$’DATAENDSCODESEGMENTASSUMECS:CODE,DS:DATASTART:MOVAX,DATAMOVDS,AXMOVSI,OFFSETSTRING;取串首地址AGAIN:MOVAL,[SI];取一字符CMPAL,‘$’;是否到字符串尾4.6.3循环结构程序设计JEOK;到字符串尾,跳出循环CMPAL,‘A’;否则,判断是否为大写字母JBNEXT;否,转继续CMPAL,‘Z’JANEXT;否,转继续ORAL,20H;是大写字母,改为小写字母NEXT:INCSI;调整指针JMPAGAIN;继续循环OK:MOVAH,4CH;结束INT21HCODEENDSENDSTART4.6.3循环结构程序设计例4-18设计一个程序判断无符号字型数组BUFFER的若干个元素中是否含有数字0,如有则把第一个0元素所在存储单元的偏移地址送字型变量ADDR,如没有则将该变量的值置为0FFFFH。数据段定义如下:DATASEGMENTBUFFERDW23,65,89,……COUNTEQU$-BUFFER;元素个数ADDDRDW?DATAENDS4.6.3循环结构程序设计程序段如下:MOVBX,OFFSETBUFFER;数组地址到BXMOVCX,COUNT;置循环最大次数AGAIN:MOVAX,[BX];取一元素CMPAX,0;与0比较JZYES;相等则跳出循环ADDBX,2;修改地址指针LOOPAGAIN;循环控制MOVADDR,0FFFFH;没找到JMPEXITYES:MOVADDR,BX;找到EXIT:......;结束4.6.3循环结构程序设计例4-19设字型数组X、Y分别有12个元素,试形成一个Z数组,使该数组的各元素满足以下关系:Z0=X0+Y0Z1=X1+Y1Z2=X2-Y2Z3=X3+Y3Z4=X4+Y4Z5=X5+Y5Z6=X6+Y6Z7=X7-Y7Z8=X8-Y8Z9=X9+Y9Z10=X10+Y10Z11=X11-Y11逻辑尺的定义:用0表示加运算,用1表示减运算,则12个式子的运算操作按Z11,Z10,Z9,…,Z0的顺序可表示为二进制数100110000100。为存放这个二进制数,可在内存中定义一个字变量,将二进制数作为该变量的低12位,变量的高4位无意义。4.6.3循环结构程序设计数据段定义如下:DATASEGMENTXDW3,65,96,45,86,8,50,7,76,45,75,5YDW9,45,23,6,74,8,21,45,12,4,64,87ZDW12DUP(?)RULERDW0000100110000100BDATAENDS主要程序段如下:……MOVBX,0;置地址指针MOVCX,12;置循环次数MOVDX,RULER4.6.3循环结构程序设计AGAIN:MOVAX,X[BX];取数组X一元素SHRDX,1;逻辑尺右移一位JCSUBS;移出位为1则相减ADDAX,Y[BX];否则相加JMPNEXTSUBS:SUBAX,Y[BX]NEXT:MOVZ[BX],AX;将结果存入Z数组ADDBX,2;修改地址指针LOOPAGAIN;循环控制EXIT:MOV......;结束4.6.3循环结构程序设计例4-20用冒泡排序法对有符号字型数组ARY按升序排列。下面是对有7个元素的无序表进行冒泡排序:表的初始状态:[36486698751328]第一遍比较之后:[364866751328]98第二遍比较之后:[3648661328]7598第三遍比较之后:[36481328]667598第四遍比较之后:[361328]48667598第五遍比较之后:[1328]3648667598第六遍比较之后:132836486675984.6.3循环结构程序设计数据段定义如下:DATASEGMENTARYDWn1,n2,n3,……NEQU($-ARY)/2;数组元素个数DATAENDS主要程序段定义如下:……MOVCX,N-1;置外循环次数LOOP1:PUSHCX;保存外循环计数器的值MOVBX,0;置地址指针4.6.3循环结构程序设计LOOP2:MOVAX,ARY[BX];取前面元素到AXCMPAX,ARY[BX+2];与后面元素比较JLEOK;次序正确则转到下一步XCHGAX,ARY[BX+2];否则,交换位置MOVARY[BX],AXOK:ADDBX,2;修改地址指针LOOPLOOP2;内循环控制POPCX;将CX恢复为外循环计数器值LOOPLOOP1;外循环控制……4.6.3循环结构程序设计4.6.4子程序设计1.子程序的调用和返回SP返回地址偏移CSIP返回地址偏移IPCSSP返回地址段值返回地址段值CALL指令执行后RET指令执行后要实现子程序的正确调用返回,必须注意:(1)正确定义子程序的类型。(2)CALL和RET指令必须成对出现。(3)正确使用堆栈。4.6.4子程序设计2.保存和恢复寄存器典型的保护和恢复寄存器编程举例如下:子程序名PROCNEAR(或FAR)PUSHAX;保护现场PUSHBXPUSHCXPUSHDXPUSHF...4.6.4子程序设计...POPF;恢复现场POPDXPOPCXPOPBXPOPAXRET子程序名ENDP