《汇编语言程序设计基本程序设计.ppt》由会员分享,可在线阅读,更多相关《汇编语言程序设计基本程序设计.ppt(182页珍藏版)》请在三一办公上搜索。
1、本章概述 本章主要介绍汇编语言程序设计的基本方法。教学目标 熟练掌握微型机的汇编语言程序设计的基本方法。学习内容 简单程序设计 分支程序设计 循环程序设计 子程序设计,第九章 基本程序设计,一、简单程序(顺序程序)设计,1.简单程序的结构例如:将 VAR1、VAR2和VAR3 三个连续单元的内容相加,结果存入 RESULT单元中。SSEGSEGMENTPARA STACK STACKDB128DUP(?)SSEGENDSDSEGSEGMENTPARA PUBLIC DATAVAR1DB?;保存第一个数VAR2DB?;保存第二个数VAR3DB?;保存第三个数RESULTDB?;保存运算结果DSE
2、GENDS,CODESEGMENTPARAPUBLICCODEASSUMECS:CODE,DS:DSEG,SS:SSEGMAINPROCFARPUSHDSXORAX,0PUSHAXMOVAX,DSEGMOVDS,AXMOVBX,OFFSET VAR1;设地址指针MOVAL,BX;取第一个数送AL寄存器INCBX;修改地址指针ADDAL,BX;加入第二个数INCBX;修改地址指针ADDAL,BX;加入第三个数INCBX;修改地址指针MOVBX,AL;保存结果RETMAINENDPCODEENDSENDMAIN;,简单程序设计首先是要学会选择适当的指令构建程序。构建一个程序可选择的指令很多,只要正
3、确就行。初学者在程序模版的基础上,更改主要指令就可以了。上例中有8六条指令是直接与题目要求有关的:MOVBX,OFFSET VAR1MOVAL,BXINCBXADDAL,BXINCBXADDAL,BXINCBXMOVBX,AL,例如:将 DATA1 中的字节数据拆开,分别存于 DATA1 和 DATA2 单元中。假设设 DATA1 单元中的数为:A6 H,程序操作结果为:DATA2内容变成 0A H DATA3内容变成 06 HSSEG SEGMENTSTACK DB256 DUP()SSEG ENDSDSEG SEGMENTDATA1 DB0A6 HDATA2 DB?DATA3 DB?DSE
4、G ENDS,CSEGSEGMENTASSUMECS:CSEG,DS:DSEG,SS:SSEG1STARTPROCFARPUSHDSMOVAX,0PUSHAXMOVAX,DSEGMOVDS,AXMOVAL,DATA1;取数 A6HSHRAL,1;SHRAL,1;SHRAL,1;SHRAL,1;右移 4 位 MOVDATA2,AL;存第一个结果MOVAL,DATA1;取数A6H ANDAL,0FH;形成第二个数MOVDATA3,AL;保存RETSTARTENDPCSEGENDSENDSTART,2.查表程序设计例如 设在内存中有一个阶乘表(0!7!),DATA单元中有一个已知数X(设该数范围 为
5、 0 7).查表求该数的阶乘值x!。,STACK1 SEGMENT STACK DB256DUP()STACK1 ENDSDATA1SEGMENT TABLEDW1,1,2,6,24,120DW720,5040;阶乘表RESULTDW?;保存结果 X!DATA DB?;存已知数XDATA1 ENDS,用 DB定义阶乘表,可否?,CSEGSEGMENTASSUMECS:CSEG,DS:DATA1,SS:STACK1BEGIN PROCFARPUSHDSMOVAX,0PUSHAXMOVAX,MOVDS,AXMOVBH,0MOVBL,DATA LEASI,TABLEMOVAX,SI BXMOV RE
6、TBEGINENDPCSEGENDSENDBEGIN,DATA1,ADD BX,BX,RESULT,AX,3.汇编语言程序输入输出的实现 每一个最简单的程序都有基本的输入输出能力。一般,汇编语言程序的输入输出操作是通过对操作系统的子程序调用实现的。在DOS操作系统中,提供了功能丰富的子程序,包括输入输出管理、内存管理、文件操作、磁盘读写控制等,DOS操作系统将它们称为系统功能调。,DOS系统功能调用中的子功能有上百个,每一个子功能的具体作用、入口参数、出口参数都可通过查表获得。应用程序通过系统功能调用,能方便地完成输入输出操作。在汇编语言程序中,利用中断指令 INT 21H 实现对操作系统系统
7、功能调用中的子功能的调用。这里先介绍其中几个最常用的子功能。,1 单个字符输入子功能(1号子功能)P 这个子功能完成从键盘输入一个字符,将所输入字符的ASCII码送AL寄存器中,同时在显示器上显示这个字符。程序中的具体操作如下:(1)子功能号 1 送入 AH寄存器中;(2)执行 INT 21H 指令,调用此子功能,系统等待键盘输入,如果输入了一个字符,结果可以在AL寄存器中得到输入字符的ASCII码。MOV AH,1INT 21H 程序段执行完毕后,在AL寄存器中得到输入字符的ASCII码。,2单个字符输出显示子功能(2号子功能)P 这个子功能可以将一个字符送到显示器上显示出来。程序中的具体操
8、作要求如下:(1)子功能号 2 送入 AH寄存器中;(2)将被显示字符的ASCII码存入DL寄存器中;(3)执行 INT 21H 指令,调用2号子功能,将字符显示屏幕上。例如,有如下程序段:MOVDL,41H;41H 是字符”A”的 ASCII 码MOVAH,02HINT21H 程序段执行完毕后,在屏幕上显示字符A。,3 字符串输出显示子功能(9号子功能)P83 这个子功能将一个字符串显示在屏幕上。该字符串在内存中的起始地址由 DS:DX 指定.以“$”作为字符串结束标志。程序中的具体操作要求如下:(1)功能号 09H 送入 AH 寄存器中;(2)将待显示字符串的存储地址的段基值和偏移量分别送
9、人DS 段寄存器和 DX 寄存器中;(3)执行 INT 21H 指令,调用 9 号子功能,将字符串显示屏幕上。,例如,有如下程序段:STR1 DBCOMPUTERDB$LEA DX,OFFSET STR1;置字符串的偏移地址 MOV AH,09HINT 21H程序执行完时,将在屏幕上显示字符串“COMPUTER”。,4 程序终止子功能(4CH号子功能)P 这个子功能程序的作用是使系统从应用程序的运行状态返回DOS状态。例如:MOVAX,4C00H INT21H 程序执行完毕,程序从当前的运行状态返回DOS。,例 用汇编语言编程实现在屏幕上显示字符串“Hello World”。DATA SEGM
10、ENTSzHello DB Hello,world,0dh,0ah,$DATA ENDSCODE SEGMENT ASSUME CS:CODE,DS:DATASTART1:MOV AX,DATA;装入数据段的段地址 MOV DS,AXMOV AH,9;字符串输出MOV DX,OFFSET SzHello;字符串的地址INT 21HMOV AH,4CH INT 21H;返回DOSCODE ENDSEND START1,从这个程序中,可以看到汇编语言源程序的另一种写法,在这里没有定义过程,直接在代码段编写程序。程序将数据段段地址装入DS后,在后面的字符串显示时,就能正确寻址到字符串在数据段中的位置
11、,通过9号功能调用输出该字符串。在程序的最后,利用DOS的功能调用,返回DOS状态。,二、分支程序设计,1.分支程序的结构示例 2.简单分支程序3.多分支程序,1.分支程序的结构示例,分支程序结构有两种形式:双分支 多分支 特点:运行方向是向前的在某种条件下,有能执行多个分支中的一个分支,计算分段函数 Y=设 X 存于 DATA 中,Y 存于 RESULT 中。START:MOVAL,DATAORAL,ALJZZEROMOVRESULT,0FFHHLTZERO:MOVRESULT,0HLT,计算分段函数 Y=程序的另一种写法。START:MOVAL,DATAANDAL,ALJZZEROMOVA
12、L,0FFHZERO:MOVRESULT,ALHLT程序设计的方法是多种多样的!,2.简单分支程序,分支:依据不同的条件,选择不同的程序段,实现对被加工对象的不同处理。实现分支的关键:选择合适的指令影响状态标志。CF、ZF、SF、OF、PF、AF 选用恰当的跳转指令判断标志,实现分支。有条件转移指令与无条件转移指令相互配合。,简单分支程序结构,简单分支程序结构,汇编语言编程中,常用的分支判断:,比较两数是否相等(设两数在 AL 和 BL 中):,CMP AL,BLJE K1,比较两数是否相等(设两数在 AL 和 BL 中):,CMP AL,BLJNE K2,CMP AL,BLJNE K3,判断
13、某数是否为0(设该数在 AL 中):,AND AL,ALJZ N1,比较两个无符号数的大小(设两数在 AL 和 BL 中):,CMP AL,BLJAE M1,CMP AL,BLJB M2,例.设行李重量为 P,行李托运费为 M,行李托运计费规定如下:行李重量小于等于20公斤时,单价为2元;超过20公斤时,超出部分按每公斤3元计算。设 P 存于 DATA 单元,M 存于 RESULT 单元。编程,计算行李费。,KD1,题意分析:当 P 大于 50 时,M=2*50+(P 50)*3=P*2+P-50;否则,M=2*P,程序代码如下(1):,MAIN PROCFARMOVAL,DATA;取重量送A
14、LCMPAL,50JBEKD1;小于等于50,转KD1MOVBL,AL;ADDAL,BL;P+P 送 ALMOVCL,AL;2P 送 CLMOVAL,BL;P 送 AL,SUBAL,50;P-50ADDAL,CL;2P+P-50 送 ALMOVRESULT,AL;存结果RETKD1:ADDAL,AL;p+p 存入 AL MOVRESULT,AL;存结果RETMAIN ENDP,KD1,上述程序可以优化:,KD1,KD2,程序代码如下(2):,MAIN PROCFARMOVBL,DATAMOVAL,BLADDAL,BLMOVCL,AL;CL=2PMOVAL,BL;AL=PCMPAL,50JBEK
15、D2;小于等于50,转KD2,SUBAL,50;AL=P-50ADDAL,CL;MOVCL,ALKD2:MOVAL,CL;MOVRESULT,ALRETMAIN ENDP,KD2,上述程序进一步优化(3):,KD2,KD3,MAIN PROCFARMOVAL,DATA;AL=PMOVBL,ALCMPAL,50JBEKD3SUBAL,50;AL=P-50ADDAL,BL;AL=AL+PKD3:ADDAL,BL;AL=AL+PMOVRESULT,AL;存结果RETMAIN ENDP,KD3,判断某数的某位(或某几位)是否为1或为0(设该数在 AL 中):,例如 在DATA 单元中有一个带符号的八位
16、数,求其绝对值存于 RESULT 中。,MAINPROCMOVAL,DATAANDAL,80HMOVAL,DATAJZLL1NEGALLL1;MOVRESULT,ALRETMAINENDP,MAINPROCMOVAL,DATATESTAL,80HJZKK1NEGALKK1:MOVRESULT,ALRETMAINENDP,例.从键盘输入 0 9 中的任意一个数 X,判断此数是否在这个范围内,若是,则将该数的立方值送入变量 Y 中,显示“INPUT CORRECT!”;否则,显示“I NPUT ERROR!”。题目涉及的知识点:1)汇编语言程序输入输出的实现。利用系统功能调用的 1#子功能,输入的
17、实际上是ASCII字符。2)查表技术,包括在内存中建表,在程序中查表。3)分支程序设计,两次比较和判断。4)显示字符串。,K1,K2,DSEGSEGMENTINPUTDB“PLEASE INPUT X(09):$”TABDW0,1,8,27,64,125;立方表DW 216,343,512,729XDB?;YDW0CORDB0DH,OAH,”INPUT CORRECT!$”ERRDB0DH,0AH,”INPUT ERROR!$”DSEGENDSSSEGSEGMENTSTACKDW64 DUP(0)SSEGENDS,CSEGSEGMENTASSUME CS:CSEG,SS:SSEG,DS:DSE
18、GSTART PROCFARPUSHDSSUBAX,AXPUSHAXMOVAX,DSEGMOVDS,AXLEADX,INPUT;MOVAH,9;INT21H;显示提示信息,MOVAH,1INT21H;输入字符CMPAL,0;是否小于”0”JBK1;CMPAL,9;是否大于”9”JAK1;ANDAL,0FH;分离出低四位MOVX,AL;暂存于 XSHLAL,1;MOVBL,AL;MOVBH,0;形成查表索引值MOVAX,TABBX;查表MOVY,AX;立方值存入 Y,LEADX,COR;MOVAH,9 INT21H;显示RETK1:LEADX,ERR;MOVAH,9 INT21H;显示RETST
19、ARTENDPCODEENDSENDSTART,JMPK2,K2:,MOVAH,1INT21H;输入字符CMPAL,0;是否小于”0”JBK1;CMPAL,9;是否大于”9”JAK1;ANDAL,0FH;分离出低四位MOVX,AL;暂存于 XSHRAL,1;MOVBL,AL;MOVBH,0;形成查表索引值MOVAX,TABBX;查表MOVY,AX;立方值存入 Y,LEADX,COR;K2:MOVAH,9 INT21H;显示RETK1:LEADX,ERR;JMPK2STARTENDPCODEENDSENDSTART,3.多分支程序,具有二个以上分支的程序称为多分支程序。例 编写计算下面函数值的程
20、序:1 X 0Y=0 X=0-1 X 0 设输入数据为 X、输出数据 Y,且皆为字节变量。程序流程图如下所示。,多 分支运算程序流程图,Y=1,X 0,X=?,Y=0,Y=-1,X=0,X0,BEGIN PROCFARMOVAL,VAR1;取数 X ORAL,ALJNSADR1;正数(SF1)转JZADR2;为(ZF=1)转MOVBL,0FFH;X为负数时 JMPDONEADR2:MOVBL,0;X为0 时 JMPDONEADR1:MOVBL,1;X为正数时DONE:MOVVAR2,BLRET BEGINENDP,此程序有错!,BEGIN PROCFARMOVAL,VAR1;取数 X ORAL
21、,ALJNSADR1;正数(SF1)转MOVBL,0FFH;X为负数时 JMPDONEADR1:JZADR2;为(ZF=1)转 MOVBL,1;X为正数时 JMPDONEADR2:MOVBL,0;X为0 DONE:MOVVAR2,BLRET BEGINENDP,BEGIN PROCFAR MOVAL,VAR1 CMPAL,0 JGEBIGR;大于等于转 MOVAL,0FFH;X为负数EQUL:MOVVAR2,AL RETBIGR:JE EQUL;X 等于 0 转 MOVAL,1;X 大于 0 JMPEQULBEGIN ENDP,例:试编一程序,求三个带符号字数据中的最大值,并将最大值存入 MA
22、X 字单元中。设三个带符号数分别存放在三个字变量X、Y、Z中存储。,程序流程图,STACKSEGMENT STACK DB 200 DUP(0)STACKENDSDATASEGMENTX DW 00ABHY DW 5Z DW 200MAXDW?DATAENDSCODESEGMENT ASSUME CS:CODE,DS:DATA,SS:STACKSTART:PUSHDSMOVAX,0PUSHAX MOVAX,DATA MOVDS,AX,MOVAX,X;取数X送 AX CMPAX,Y;XY?JGL1;大于则转 MOVAX,Y;Y 大 CMPAX,Z;YZ?JGEXIT;Y 大则转,AX存大数L2:
23、MOVAX,Z;至此 Z大,送入AX JMPEXITL1:CMPAX,Z;XZ?JLEL2;X=Z 转EXIT:MOVMAX,AX;AX 存大数 RETCODE ENDS END START,4.用地址表(或转移表)实现多路分支,利用简单分支程序组合实现的多分支程序,要经过多次判断才能确定进入哪个分支运行,当程序分支过多时,这种判断花费的时间就可能较长。在多分支程序设计中,常用 地址表 或 转移表 法。地址表法是指:把转移到各分支程序的入口地址集中存放在一张表中,该表称为分支地址表。各分支转移程序的入口地址在表中的位置(离表首地址的位移量)作为条件。当进行多分支条件判断时,把当前条件位移量加上
24、表首地址作为转移地址,转到表的相应位置,取出所转向的子程序的入口地址,达到多分支的目的。,例:设计多分支程序,实现从键盘输入09之间的数码,根据输入的情况,转入到相应的分支程序运行,显示响应的提示信息:输入0时显示:The number is zero输入1时显示:The number is one输入9时显示:The number is nine,利用地址表法设计分支程序,根据输入的情况,转入到相应的分支程序运行。在不同的分支中显示不同的字符串。设 各分支程序的入口地址分别确定为:ADDR0、ADDR1、ADDR2、ADDR9。在数据段定义一张地址表,其起始地址为ADDRTABLE,将各分支
25、程序的入口地址存于表中。程序中利用DOS的1号功能调用,从键盘输入0到9之间的数据。,从键盘输入0到9之间的数据,求对应的键盘输入的数值,地址表实现多分支的程序流程图,计算转移表表项地址送入DI,查表取分支程序的入口地址送入BX,开 始,置地址MESG0,=0,结 束,置地址MESG1,=1,置地址MESG9,=9,利用JMP BX指令转入对应分支,显示字符串,DATA SEGMENT ADDRTABLE DWADDR0;地址表 DWADDR1.DWADDR9 MESG0DBThe number is zero,0dh,0ah,$;待显示的字符串MESG1 DB The number is o
26、ne,0dh,0ah,$.MESG9 DB The number is nine,0dh,0ah,$DATAENDS,CODE SEGMENT ASSUMECS:CODE,DS:DATASTARTPROCFAR MOV AX,DATA MOV DS,AX MOV AH,1;从键盘输入数码 INT 21H CMP AL,30H JBEXIT CMP AL,39H JA EXIT SUB AL,30H;将所输入的数,从其ASCII变为对应数值 MOV AH,0 SHL AX,1;AX中的内容乘以2 MOV DI,AX MOV BX,ADDRTABLEDI;分支的入口地址存入BX JMP BX;转移
27、到相应的分支,ADDR0:MOV DX,OFFSET MESG0;分支程序段1 JMP PRINTITADDR1:MOV DX,OFFSET MESG1;分支程序段2 JMP PRINTIT ADDR9:MOV DX,OFFSET MESG9;分支程序段9PRINTIT:MOV AH,9 INT 21H;显示字符串EXIT:MOV AX,4C00H INT 21HSTART ENDPCODE ENDSEND START,分支程序设计小结 实现分支转移的语句主要有比较语句、条件转移语句、无条件转移语句三种,其中比较语句有CMP、CMPS、TEST、SCAS等,条件转移语句比较多,其中使用最多的是
28、JZ、JC、JA、JG、JB、JL等,主要是根据标志寄存器的设置情况进行转移;无条件转移JMP指令,可以转移到程序中的任何位置。一般情况下,在程序设计中,都先使用比较指令,然后再使用条件转移指令完成程序的分支,因为条件转移指令是根据标志位的情况来进行转移,而比较指令都影响标志位。对于分支过多的情况,如果比较的条件经过简单运算就能跟转移地址联系起来,就尽量使用地址表法实现程序的分支。,三、循环程序设计,1.循环程序的结构2.单重循环程序设计3.多重循环程序设计,循环程序的结构 循环程序一般由 4 部分组成:,初始化部分循环体(工作)部分循环修改部分循环判终(控制)部分,循环程序的常见结构形式如下
29、。,直到型循环,当型循环,图中:,(a)为 直到型 循环特点:先执行,后判断(b)为 当型 循环特点:先判断,后执行,2.单重循环程序设计 P 循环程序实质上是一种特殊形式的分支程序。循环程序设计的关键是,必须准确地控制循环体的重复执行次数。一般循环控制的常见方法有两种:计数控制 和 条件控制。,1)计数控制法 P 计数控制常用于循环次数已知的循环程序。在程序中设置一个计数器。计数器可以用CPU的寄存器,也可以用存储单元实现;可以采用加计数方法计数,也可以采用减计数方法计数。,例:在数据段的ARRAY存储区中存放有100个字数据,计算这100个数据的和,并将其和放入SUM单元。编程思路:此程序
30、完成100个数据的累加,程序选用CX作计数器,以减计数的方式控制循环。选用 BX 作地址指针,指针初始应指向ARRAY。在循环体中修改地址指针 BX=BX+2;修改计数器 CX=CX-1。当 CX=0 时,退出循环。,STACKSEGMENT STACK DB 200 DUP(0)STACKENDS DATA SEGMENT ARRAY DW 100 DUP(?);100个已知数据 SUMDW 0;保存累加结果 DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATA,SS:STACK,STARTPROCFARMOV AX,DATA MOV DS,AX;设置段寄存
31、器初值 MOV CX,64H;循环次数送CX寄存器 LEA BX,ARRAY;置地址指针初值 MOV AX,0;累加器初始化LOOP1:ADD AX,BX;累加 ADD BX,2;修改地址指针 LOOP LOOP1;修改计数器,判循环结束否 MOV SUM,AX MOV AH,4CH;INT 21H;返回系统STARTENDPCODE ENDSEND START;结束汇编,在实际的程序设计中,只有分支没有循环或者只有循环没有分支的情况很少,大多数情况下分支和循环在程序中是共存的。下面的示例就是一个循环次数已知,既有分支又有循环的程序。,例:奖学金评定时,规定:总评成绩在 90到100之间获一等
32、奖,总评成绩在 80到89之间获二等奖,总评成绩在 70到79之间获三等奖。在缓冲区GRADE中放有10个学生的总评成绩,分别统计获一等奖、二等奖、三等奖的人数。P100,编程思路:此程序完成10个数据的判断、统计,程序选用CX作计数器,以减计数的方式控制循环。选用 SI 作地址指针,指针初始应指向GRADE。在循环体中修改地址指针 SI=SI+2;修改计数器 CX=CX-1。当 CX=0 时,退出循环。设 三个计数器:PRIZE_1 保留获一等奖人数 PRIZE_2保留获二等奖人数 PRIZE_3 保留获三等奖人数,FIRST,SECOND,ROTATE,COMPARE,程序如下:DATA
33、SEGMENTGRADE DB45,70,78,86,94,100,83,88,76,65PRIZE_1 DB 0;一等奖人数PRIZE_2DB 0;二等奖人数PRIZE_3 DB 0;三等奖人数DATAENDSCODESEGMENT ASSUME CS:CODE,DS:DATAMAINPROCFARPUSHDSXORAX,AX,PUSHAXMOV AX,DATA MOV DS,AXMOV CX,10;置循环计数器初值 LEA SI,GRADE;置地址指针SI初值 MOV BL,10COMPARE:MOV AL,SI;将成绩送入AL CBW DIV BL;成绩除10 CMP AL,9;商是否大
34、于等于9 JAE FIRST;是,转FIRST,CMP AL,8;商是否大于等于8 JAE SECOND;是,转SECOND CMP AL,7;商是否大于等于7 JB ROTATE;小 于7,进入下一轮循环 INC PRIZE_3;大于等于7,三等奖人数加1 JMP ROTATEFIRST:INC PRIZE_1;大于等于9,一等奖人数加1 JMP ROTATESECOND:INC PRIZE_2;大于等于8,二等奖人数加1ROTATE:INC SI;修改地址指针 LOOP COMPARE RETMAINENDP CODEENDSEND MAIN,例:编程将BX内的二进制数用十六进制数的形式在
35、屏幕上显示出来。,编程思路:把(BX)从左到右每四位一组在屏幕上显示出来。用循环,每次循环显示1个十六进制数位,循环次数为4。循环体:完成将 4 位二进制数转换成1位16进制数的ASCII码;用DOS功能调用将其显示出来(DL)=显示的ASCII码(AH)=216进制数 转换为对应的 ASCII 码0 9 的 ASCII码:30 39H,即 0 9+30HA F 的 ASCII码:41 46H,即 10 15+30H+7H,16进制数 转换为对应的 ASCII 码0000 30H 0001 31H0010 32H0011 33H0100 34H XXXX+30H 0101 35H0110 36
36、H0111 37H1000 38H1001 39H1010 41H(=3AH+7 H)1011 42H(=3BH+7H)1100 43H XXXX+30H+7H1101 44H1110 45H1111 46H,prognam segmentmain proc far assume cs:prognamstart:pusHdssubax,axpushaxmov bx,1234hmovch,4rotate:movcl,4rolbx,cl;循环左移moval,blandal,0fhaddal,30h,cmpal,3ah jlprintit;小于 3AH 转addal,7hprintit:movdl,
37、almovah,2int21hdecchjnzrotateretmainendpprognamends end start,例:已知有几个元素存放在以BUF为首址的字节存贮区中,试统计其中正元素的个数。每个元素为一个8位有符号二进制数;统计其中正元素的个数可用循环程序实现,其中:AX作为正数个数计数器,BX为指向BUF的地址指针,CX为循环计数器。,程序流程图,datsegsegmentBUFdb2,3,5,9,-1,-3,6,-8buflendb$-BUF;定义BUF长度datsegends;codsegsegmentassume ds:datseg,cs:codsegmainprocfar
38、start:pushdssubax,axpushaxmovax,datseg;设置DS的值movds,axmovbx,offset buf;bx作为BUF地址的指针,movcx,buflen;设置循环次数,即BUF的长度movax,0;正数的个数为0 again:cmpbyte ptr bx,0;比较是否为正数?jle next;0,(ax)+1axnext:incbx;修改地址 deccx;修改循环次数 jnzagain ret;返回DOSmain endpcodseg ends endstart;结束汇编,例:,试编写一程序,比较两个字符串 STR1 和STR2 所含字符是否相同,若相同则
39、显示MATCH!,不相同则显示NO MATCH!。STR1与STR2若匹配,则长度必须一致,先判断其长度是否相等;若长度相等,则遂个字符比较是否相同;循环控制次数由STR1长度控制。,程序流程图,datareasegmentstr1dbHellostr1lendb$-str1;存字符串长度str2dbHullostr2lendb$-str2;msg1dbMATCH!$msg2dbNO MATCH!$datareaends;codsegsegment assume ds:datarea,cs:codsegmainprocfarstart:pushdssubax,axpushax,movax,da
40、tareamovds,axmoval,str1lencmpal,str2len;串长度比较jnznomatch;不等,则转movsi,offset str1len;设地址指针movdi,offset str2len;设地址指针movah,0movcx,axagain:decsi;修改地址指针decdi;修改地址指针 moval,sicmpal,di;比较字符相等否?jnznomatch;不等,则转loopagain;修改计数器,判终,movah,9movdx,offset msg1int21h;显示jmpexit;nomatch:movah,9movdx,offset msg2int21h;显
41、示;exit:retmainendpcodsegendsendstart,;,例 编程完成:从键盘输入一个 065535之间的十进制数,并显示出对应该数的十六进制数.;转换算法:y=y*10+di(i=n,n-1,.,1)dsegsegmentin_buf1db6In_lengdb?buf1db6dup(0)resultdw0mes1dbplease input a number(065536):$mes2dbinput invalid,exit!,13,10,$dseg ends,;,ssegsegmentstackdb512 dup(?)ssegendsassumecs:cseg,ds:d
42、seg,ss:ssegcsegsegmentstr2binprocfarpushdsxorax,axpushaxmovax,dsegmovds,ax;经典的5条指令,;,movdx,offset mes1movah,9int21h;显示输入的提示信息movdx,offset buf1movah,10int21h;从键盘输入5位数,存于 buf1中subax,ax;将输入 的数转换成二进制数movsi,10subch,chmovcl,in_leng;取实际输入的字符个数movdi,offset buf1;设地址指针,;,loop_10:movbl,di;取一个字符cmpbl,30h;判是否非法字
43、符jbquit_ncmpbl,39h;jaquit_n;判是否非法字符subbh,bh;subbl,30h;转换成 0 9mulsi;乘 10jcquit_n;有进位,大于65535addax,bx;y=y+di(i=n,n-1,.,1)jcquit_n;相加有进位,大于65535incdilooploop_10;,;,movbx,ax;16位二进制数movch,4;下面转换成十六进制数rotate:movcl,4rolbx,cl;循环左移moval,blandal,0fhaddal,30hcmpal,3ah jlprintit;小于 3AH 转addal,7hprintit:movdl,al
44、,;,movah,2int21h;输出显示decchjnzrotate jmp quit_q quit_n:movdx,offset mes2movah,9int21hquit_qretstr2binendpcsegendsend str2bin,2)条件控制法(循环次数未知)P 在一些情况下,循环次数往往无法事先确定,不能用计数法控制循环。虽然循环次数无法预知,但它与问题中的某些条件有关,这些条件可以通过指令来测试。若测试比较的结果满足循环条件,则继续循环,否则结束循环。,例:在ADDR单元中存放着数Y的地址,试编制一程序,把Y中1的个数存入COUNT单元中。将 Y 为字数据,16位;用最高
45、有效位是否为1来判断,即Y是否为负数,使用移位的方法,使Y中每位都移到最高位去测试;条件控制循环:使用SHL移位,则移动16次或该数为0时,退出循环;测试的方法:TEST指令。,datareasegmentaddrdwnumber;addr 中存放 number 的偏移地址numberdw56h;存放数 Y countdw?;datareaends;prognamsegmentassumecs:prognam,ds:datareamainprocfarstart:pushds;为返回DOS设置参数subax,axpushax;movax,datarea;设置DS的值movds,ax,movcx
46、,0;初始设 1 的个数为 0movbx,addr;将BX存放number的地址movax,bx;Y 送 axrepeat:testax,0FFFFH;测试 ax 是否为0jzexit;为 0,则退出,jnsshift;非负,则去移位inccx;为负,cx 加1shift:shlax,1;移位1次jmprepeatexit:movcount,cxretmainendpprognamendsendstart,例:假设有一张很大的纸,其厚度为 0.1 mm,将它不停地对折。问对折多少次之后,纸的厚度可达珠穆朗玛峰的高度(8848 M)。,3)开关控制法,例:设 共有 12 个数据存于 BUF 区域
47、,分别用两种功能处理,要求:对前 5 个数据用第一种功能处理(例如 乘 2);对后 7 个数据用第二种功能处理(例如 乘 4)。处理结果存于 BLK 区域中。,DSEGSEGMENTBUFDWX0,X1,X2,X3,X4,X5,X6DWX7,X8,X9,X10,X11BLKDW12DUP(?)CO1EQU5CO2EQU7DSEGENDS,MOVDX,0MOVCX,CO1LEABX,BUFLEASI,BLKAG:MOVAX,BXCMPDX,0JNEANOADDAX,AXLOOPNEXTMOVDX,1MOVCX,CO2JMPAG,NEXT:MOVSI,AXINCBXINCBXINCSIINCSIJ
48、MPAGANO:ADDAX,AXADDAX,AXLOOPNEXTRET,此程序有错!,MOVDX,0MOVCX,CO1LEABX,BUFLEASI,BLKAG:MOVAX,BXCMPDX,0JNEANOADDAX,AXLOOPNEXTMOVDX,1MOVCX,CO2,NEXT:MOVSI,AXINCBXINCBXINCSIINCSIJMPAGANO:ADDAX,AXADDAX,AXLOOPNEXTMOVSI,AXRET,4)逻辑尺控制法,例:对上例中的数据,若要求程序 对第 1、2、5、7、10 个数据用第一种功能处理;对第 3、4、6、8、9、11、12 个数据用第二种功能处理。设 数据仍存
49、于 BUF 区域,结果存于 BLK区域中。,DSEGSEGMENTBUFDWX0,X1,X2,X3,X4,X5,X6DWX7,X8,X9,X10,X11BLKDW12DUP(?)LOGEQU0011010110110000 BCONEQU12DSEGENDS,0 0 1 1 0 1 0 1 1 0 1 1 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 12,MOVDX,LOGMOVCX,CONLEABX,BUFLEASI,BLKAG:MOVAX,BXRCLDX,1JCANOADDAX,AX,NEXT:MOVSI,AXINCBXINCBXINCSIINCSILOOPAGRETA
50、NO:ADDAX,AXADDAX,AXJMPNEXT,3.多重循环程序设计 P,例:在以AA为首址的字存储区中存放有N个有符号数,试编程将它们按从大到小的顺序排列在AA存储区中。冒泡法:从第一个数开始,依次对相邻两个数进行比较,若大小次序对,则不交换两数位置;若次序不对,则使这两个数交换位置。第一遍需比较(N-1)次,此时最小数放到了最后;第二遍只需比较剩下的(N-1)个数,即比较(N-2)次;第三遍只需比较(N-3)次,整个排序过程最多需(N-1)遍。,数 108163290第一遍101632908第二遍163290108第三遍329016108第四遍903216108程序流程图如下图所示。