循环和分支程序设计(书)_第1页
循环和分支程序设计(书)_第2页
循环和分支程序设计(书)_第3页
循环和分支程序设计(书)_第4页
循环和分支程序设计(书)_第5页
已阅读5页,还剩99页未读 继续免费阅读

下载本文档

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

文档简介

第5章

程序设计方法概述顺序程序设计分支程序设计循环程序设计子程序设计5.6模块化开

始5.1

概述汇编语言程序设计的一般步骤流程图返回本章首页5.1.1汇编语言程序设计的一般步骤返回本节汇编语言程序设计一般有以下几个步骤:分析题意,确定算法;分析和理解题意,找出合理的算法及适当的数据结构;根据算法画出程序流程图;根据流程图编制程序;上机调试程序;任何程序必须经过调试才能检查出你的设计思想是否正确,以及你的程序是否符合你的设计思想。调试时可用工具——DEBUG进行调试。程序结构有:顺序、循环、分支、和子程序四种数据结构。运行程序;5.1.2流程图流程图的概念流程图是由特定的几何图形、指向线、文字说明来表示数据处理的步骤,形象描述逻辑控制结构以及数据流程的示意图。流程图具有简洁、明了、直观的特点。流程图符号表示起止框:表示程序的开始和结束。起止框(2)判断框处理框调用框(5)指向线(6)连接框返回本节5.2

顺序程序设计下面举例说明顺序程序的设计。例5.1数组中存放若干个字节元素。将两个数组对应元素相加,运算结果存放在第三个数组相应结果单元中。本例每个数组有1个元素,每个元素占

1字节长。(1)

E:\MASM>EDITC100.ASMDATA

SEGMENTDATA1

DB1;被加数DATA2

DB5;加数DATA3

DB0;和初值DATACODEENDSSEGMENTASSUME

CS:CODE,

DS:DATASTART:

MOV

AX,

DATA;清进位标志AL,DATA1[SI]MOV

DS,

AXMOV

SI,

0CLCMOVADCAL,DATA2[SI]

;字节相加MOV

DATA3[SI],

AL;输出显示部MOV

BX,OFFSET

DATA3MOV

DL,

[BX]ADD

DL,

30HMOV

AH,

2INT

21H;返回DOSAX,

4C00H21HMOVINTCODE

ENDS(2)

E:\MASM>MASMC100.ASMC100E:\MASM>LINKE:\MASM>C100<ENTER>6(5)E:\MASM>DEBUG

C100.EXE5.2

顺序程序设计【例5.2】试编写一程序计算以下表达式的值。w=(v-(x*y+z-540))/x式中x、y、z、v均为有符号字数据。设x、y、z、v的值存放在字变量X、Y、Z、V中,结果存放在双字变量W之中,程序的流程图如图5.1返所回本示章。首页序运算程序源程序如下:DATAW

DWDATASTACKSEGMENTDW

200DW

100DW

3000V

DW

100002

DUP(?)ENDSSEGMENT

STACKDB

200DUP(0)ENDSSTACKCODE

SEGMENTASSUME

DS:DATA,CS:CODE,SS:STACKSTART:MOVMOVMOVDS,AXAX,XAX,DATA;DATA→AXIMULY;(X)*(Y)→DX:AXMOVCX,AXMOVBX,DX;(DX:AX)→(BX:CX)MOVAX,ZCWD;(Z)符号扩展ADDCX,AX→(BX:CX)ADCBX,DX;(BX:CX)+(DX:AX)SUBCX,540SBBBX,0;(BX:CX)-540→(BX:CX)CWD;(V)符号扩展SUB

AX,CXSBB

DX,BX;(DX:AX)-(BX:CX)→(DX:AX)IDIV

X;(DX:AX)/XMOV

W,AXMOV

W+2,DX;商→W;余数DX→W+2MOV

AH,4CHINT

21HCODE

ENDS ;退出DOS状态5.3

分支程序设计用条件转移指令实现程序分支用跳转表实现多路分支返回本章首页1、分支程序的结构形式:分支程序结构可以有两种形式:一个是二路分支:IF—THEN—ELSE形式;一个是多路分支:CASE形式;5.3.1用条件转移指令实现程序分支JZ结果为常零用的语JN句Z

:结果不为零JS/结果为负JNS结果为正JL小于JLE小于等于JG大于JGE大于等于在某一种确定条件下,只能执行多个分之中一个分支。例5.3

已知X=80,

X值在数据段中定义,编写程序:若X>50则

Z

=X+Y,否则Z

=X-Y

,结果存入Z。X,Y,Z均为字数据。SEGMENT;数据段中DW

80ENDSDATAX

DATACODESEGMENTASSUME

DS:DATA,SS:STACK,CS:CODESTART:MOVAX,DATAMOVDS,AXMOVAX

,

XCMPAX,

50JGHIGHSUBAX

,

YJMPEXITHIGH:ADDAX,

YEXIT:MOVZ,AXCODEMOV

AH,4CHINT

21HENDSENDSTART【例5.4】编写计算下面函数值的程序:1Y=

0-1X>0X=0X<0设输入数据为X、输出数据Y,且皆为字节变量。程序流程图如图5.2所示。流程图如下:图5.2

分支运算程序流程图【例5.4】编写计算函数值的程序:程序如下:SEGMENTDB -10DATAXY DB

?DATA

ENDSSTACK SEGMENT

STACKDB 200

DUP(0)ENDSSTACKCODE

SEGMENTASSUME

DS:DATA,SS:STACK,CS:CODESTART:

MOV

AX,DATAMOV

DS,AXMOV

AL,

XCMP

AX,0JGE

A1MOV

Y,-1;与0进行比较;X≥0转A1;X<0时,-1→YJMPEXIT;X>0转;X=0时,0→YA1:JGA2A2MOVY,0JMPEXITA2:

MOV;X>0,1→YEXIT:

MOVINTY,1AH,4CH21HCODE

ENDSENDSTART【例5.5】求最值【例5.5】试编一程序,求三个带符号字数据中的最大值,并将最大值存入MAX字单元中。设三个带符号数分别在三个字变量X、Y、Z中存储。程序流程图如图5.5所示例5.5程序流程图MOV

AX,XCMP

AX,YL1Y;Y>Z?;X>Y?JGMOV

AX,CMPAX,ZJGEXITL2:

MOVAX,ZJMPEXITAX,ZL1:CMP;X>Z?JLEL2程序如下:STACKSEGMENT

STACKDB

200

DUP(0)STACKDATAENDSSEGMENTXDW30YDW20ZDW10MAXDW

?DATAENDSCODE

SEGMENTASSUME

DS:DATA,SS:STACK,CS:CODESTART:

MOVMOVMOVCMPAX,DATADS,AXAX,XAX,Y;X>Y?JGMOVL1AX,Y;Y>Z?L2:CMPJGMOVJMPAX,ZEXITAX,ZEXITL1:

CMP

AX,

Z;X>Z?JLE

L2EXIT:

MOV

MAX,AXMOV

AH,4CHCODEINT

21HENDSENDSTART返回本节2、多路分支程序设计方法.程序分支一般用条件转移命令来产生,连续用条件转移命令使程序产生多个分支。例5.6在DI寄存器中,数组中的第一个单元存放着数组长度,在AX中有一个无符号数,要求在数组中查找(AX),如找到则使CF=0,并在SI中给出该元素在数组中的偏移地址;如未找到则使

CF=1.方法:顺序折半法.折半查找法先取有序数组的中间元素与查找值比较,如相等则查找成功;如查找值大于中间元素,则再取高半部的中间元素与查找值相比较;如查找值小于中间元素,则再取低半部的中间元素与查找值比较;如此重复,直到查找成功或最终未找到该数为止。例5.6在附加段中,有一个按从小到大顺序排列的无符号数组,其首地址存放在DI寄存器中,数组中的第一个单元存放着数组长度,在AX中有一个无符号数,

要求在数组中查找(AX),如找到,则使CF=0,并在SI中给出该元素在数组中的偏移地址,如未找到,则使CF=1在一个长度为N的有序数据组R中,查找元素K的折半查找算法:n

;⑴初始化被查找数组的首尾下标,low

1,hig⑵若low>high,则查找失败,置CF=1,退出程序。否则,计算中点:mid

(low+high)/2;⑶K与中点元素r[mid]比较,若k=r[mid],则找成功,退出程序;若k<r[mid],则转步骤(4);high

mid-1,转若k>r[mid],则转步骤(5

);low

mid+1,转⑷低半部查找(lower),high

mid-1,返回步流程图如下:Dseg;低地址元素的下标.segmentLow_

idx dw

?High_

idx dw

?;高地址元素的下标.Dseg

ends.B_search

procnear;查找元素“55”(ax)Mov

ax

,

55Cmpax

,es:[di+2]

;(ax) 第一个元素,比较.Ja

chk_last ;(ax)>第一个元素,则Lea si

,es:[di+2]

;(ax)≤第一个元素,则第到chk_last一个元素

S;(ax)=第一个元素,则退出.;(ax)≠第一个元素,则CF=1,未找Je

exitStcJmp

exit;退出.Chk_last:Mov

si

,es:[di]Shl si

,1;

元素个数

S.;长度*2=到最后元素(下标)的字节数Add

si

,diCmp

ax

,es:[si];形成最后元素的地址;比较,<最后元素,则转searchSearch

:(low_idx)Movlow_idx

,1;最低元素下标=1Movbx

,es:[di];元素个数

(bx)Movhigh_idx

bx;最高元素下标(high_idx=元素个数)Movbx

,di;保存数组的起始地址(bx)mid:movcx

,low_idxmovdx

,high_idx;low

>high_idxcmpcx

,dx;若low>high,则转no_match,置cja

no_match:

int[(low+high)/2]

cx(中间)addcx

,dx;shrcx

,1;中间元素下标(si)movsi

,cx;shlsi

,1;将下标值*2形成元素compare:;数组基地址BX+元素偏偏移地址移量 元素地ax<中间元素:dec

cxmov high_idx

,cxjmp

mid;若(ax)<(mid),则;1、中间元素下标值:(cx)

(cx)-;

2、且(cx)

high_idx;3、转mid,将中间元素变为高地址higher:inc

cxmov low_idx

,cx变为低地址元素jmp

mid.;若(ax)>(mid);1、中间元素下标值:(cx)

(cx)+;2、low_idx (cx)将中间元素;3、转mid,计算中间元素;未找到,置cf=1;弹出dsNo_match:StcExit:Pop

dsRetB_searchendp程序首先把查找值与数组的第一个元素和最后

一个元素相比较,如果找到或该数小于第一个元素或大于最后一个元素,则结束查找,否则从SEARCH开始折半查找。SEARCH①从SEARCH开始,首先把数组长度作为数组中间元素下标,把它从数组的第一个单元中取出来,并使它成为偶数,然后再把下标加到DI中以形成数组的中间元素的地址并开始比较查找;②如果比较相等则转至ALL_DONE结束查找;③否则要确定下一步的查找是在数组的低半部还是高半部中进行。它们要做的工作是:①首先检查下标是否等于2,如果等于2则说明整个查找失败,应把CF置1并转至ALL_DONE结束查找;②其次,把下标除以2,以便做进一步的折半查找,然后使下标形成偶数值;③如果要在低半部查找,则从当前的地址(DI)中减去下标值(si)以形成新的查找地址;④如果要在高半部查找,则把下标值加到当前地址值中。以上过程重复进行直到下标值减到2或者查Dsegsegment定义数据段地址Starteddw?存放数组的首DsegendsCsegsegment代码段Bsearch

procAssumePushPushMovMovPopfarcs:

cseg

,

ds:

dsegdsaxax

,dsegds

,axax ;将已存入ax中的数弹出个元素吗?JaCmp ax

,es:[di+2] ;(ax)≤第一chklast ;到CHKLAST取偏移地址lea址存入siexitjestcjmpchklast:si

,es:[di+2] ;到≤时,则取地;=退出,CF=0不置位;<置CF=1,未找到转EXITexitmov si

,es

:[di] ;取第一单元中数组长度;长度*2=最后元素下标;形成最后元素地址;比较;<,则开始查找;=为最后一个元素,退出;>最后元素,置CF=1,退出jmpshl si

,1add si

,dcmp

ax

,es:[si]jb

searchje

exitstcexitsearch:

mov starad,di ;将起始地址存入startadmov si

,es

:[di] ;取长度

(si)evenr:jztest si

,1add

I;是偶数则第0位为1;当ZF=1时则为全0,为;为奇数+1形成偶数inc

siaddi

addcompare:

cmpdi

,siax

,es:[di];形成查找元素的地址;比较(ax)=?es:[di]alldonehighersi

,2idxok:=则转alldone;ax>则到高半部;si=2;不为2则继续查找;CF=1,未找到jejacmpjnenomatch:

stcjeidxok:alldoneshrsi

,1;(si)/2=’si’逻辑右0;为偶数吗?;是;否则加1;再低半部,di-si形成subidx:jmphigher:test si

,1je

subidxinc

sisub di

,sishart

comparecmp si

,2;元素地址;在高半部nomatchsi

,2;未找到,置CF=1;(si)/2

(si)jeshrjmpshort

evenisi;转eveni,将di+s高半部alldone:

movsi

,ddi

,startaddr 元素的位置

Sds 偏移位置movexit:

popretbsearch

endpcseg

endsend如果数组如下:List

Dw

12、11、22、33、44、55、66、77、88、99、111、222、333.要求查找的数为(ax)=55。数组长度为12,第一次比较的是数组的第6个元素66;因55<66,所以第二次用低半部折半查找,比较的是第3个元素33;因55>33.所以第三次用高半部折半查找,比较的是第五个元素55.这样经过三次比较后,因查找成功而退出程序。如果要查找的数是(ax)=57.则第二次比较的仍是第六个元素66;因57<66,第二次用低半部折半查找,比较的是第三个元素33;因57>33,所以第三次用低半部折半查找,比较的是第五个元素55;因55<57,第四次用高半部折半查找,比较的又是第六个元素66;因57<66,在转低半部查找时,因(si)=2而以查找失败退出程序。这个例子用CMP或TEST指令以及条件转移指令产生两个或多个程序分支。5.3.2用跳转表实现多路分支在实现CASE结构时还可以使用跳跃表法使程序能根据不同的条件转移到多个程序分支去。【例5.7】设某程序有8路分支,试根据给定的N值(1~8),将程序的执行转移到其中的一路分支。程序流程如图5.7所示。程序如下:DATA

SEGMENTTAB

DW

P1,P2,P3,P4,P5,P6,P7,P8NDB5S1DW?S2DW?S3DW?S4DW?S5DW?S6DW?S7DW?S8DW?DATAENDSSTACKSEGMENTSTACKCODEDB

200

DUP(0)ENDSSEGMENTASSUME

DS:DATA,SS:STACK,CS:START:

MOVAX,DATAMOV

DS,AXMOV

AL,NDEL

ALADD

AL,ALMOV

BL,ALMOV

BH,0JMP

TAB[BX]P1:MOVAX

,1MOVS1,AXJMPEXITP2:MOVAX

,2MOVS2,AXJMPEXITP3:MOVAX

,3MOVS3,AXJMPEXITP4:MOVAX

,4MOVS4,AXP5:

MOVAX

,5MOVS5,AXJMPEXITP6:

MOVAX

,6MOVS6,AXJMPEXITP7:

MOVAX

,7MOVS7,AXJMPEXITP8:

MOVAX

,8MOVS8,AXEXIT:MOVAH,4CHINT21HCODE

ENDSENDSTART上述程序中的无条件转移指令的转移地址采用的是变址寻址。同理,转移地址也可以用寄存器间接寻址或基

址加变址寻址,读者可自行考虑。返回本节5.4

循环程序设计循环程序的结构单重循环程序设计多重循环程序设计返回本章首页5.4.1循环程序的结构1、循环程序的常见结构形式如图5.5(a(b)所示。循环有两种结构形式.一种是DO_WHILE形式;另一种是

DO_UNTIL形式。当条件为真时执行循环体,为假时跳出循环体。DO—WHILEDO—WHILE型把对循环条件的判断放在循环的入口,先判断条件,DO—UNTIL结构则先执行循环体,然后再判断控制条件,不满足则继续执行循环操作,一旦满足循环条件则退出区别:DO—WHILE型有可能一次也不执行循环体;DO—UNTIL型则至少执行一次循环体;循环程序可由如下三部分组成:初始化部分循环体部分循环控制部分设置循环的初始状态;设置循环次数的计数值,以及为循环体正常进行工作而建立的初始状态。循环体这是工作的主体,它由循环的工作部分及修改部分组成。工作部分:完成程序功能。修改部分:保证每一次重复时,参加执行的信息能发生有规律的变化。循环控制部分程序设计的关键,控制循环的运行和结束。5.4.2单重循环程序设计1.计数控制2.条件控制data

segmentary

dbcount

db

3sum

db

?next:

addyadd

si,loop

nextmovsum,

al例

计算

sum=1+2+3数据段定义:ary

db1,2,31,2,3si←Ary首地址cl←元素数,al←0和初值求和:al←al+[si],求下一元素地址si←si+1si,

ary

ncl,

counCtx-1且cx=0?data

ends……leamovmov

al,

0al,存累[s加i和]:sum←al1显示累加和:sum结束例

计算

sum=1+2+3data

segmentarydb1,2,3countdb3sumdatadbends?segment

stack100

dup(0)endsstackdwstackcodemainsegmentproc

farassume

cs:code,ds:data,ss:stackstart:

mov

ax,

datamov

ds,

axnext:nextsum,

almaincodelea

si,

arymov

cl,

countmov

al,

0add

al,

[si]add

si,

1loopmovmov

al,

sumadd

al,

30hmov

dl,

almov

ah,

2int

21hmov

ah,

4chint

21hendpendsend

start1.计数控制【例5.7】已知有几个元素存放在以BUF为首址的字节存贮区中,试统计其中正元素的个数。显然,每个元素为一个8位有符号二进制数,统计其中正元素的个数可用循环程序实现。其程序流程图如图5.6所示。LEABX,BUFMOV

CX,NBYTE

PTR

[BX]L2MOV

AX,

0L1:

MOV

DL

,CMP

DL

,

0JLEINC

AX

;正元素个数L2:

INC

BX

;BX←元素地址+1LOOP

L1

MOV

NUM,AXDATASEGMENTBUFDB 1,3,5,,0,-1,-3,-5,NEQU $-BUFNUMDW

?DATAENDSSTACK

SEGMENT

STACKDB

200

DUP(0)STACKCODEENDSSEGMENTASSUME

DS:DATA,CS:CODE,SS:STACKSTART:MOVMOVLEAMOVAX

,

DATADS,

AXBX,

BUFCX,

N;元素起始地址;元素总个数值=0MOVAX,

0;正元素个数初L1:MOV

DL,BYTE

PTR

[BX]CMPDL

,

0JLEL2INCAX;正元素个数L2:向下一个元素INCBX;BX←元素地址+1,指LOOP

L1

;

DEC

CX;

JNEL1

;MOV

NUM,

AXMOV

AH,

4CH【例5.8】字符串比较【例5.8】试编写一程序,要求比较两个字符串STR1和STR所含字符是否相同,若相同则显示‘MATCH!’,若不相同则显示‘NO

MATCH!’。(程序略)其流程图如图5.7所示。程序data

segmentstring1MATCH

NOMATCHDB

"abcde"DB

"MATCH$"db

"no

match$"dataextraendssegmentstring2numdb

"abcde"db

"ok"extra

endsprogname

segmentmainproc

farassumecs:progname,ds:data,es:extrastart:pushmovpushmov

mov

mov

mov

movdsax,0axax,datads,axax,extraes,axal,match-string1;字符串1元素个数cmpjnelealeamoval,num-string2dispnosi,string1di,string2cx,match-string1rota:moval,[si]cmpal,[di]jnedispnoincsiincdilooprotadispma:movdx,offsetmatchmovah,9int21hjmpexitdispno:movdx,offsetnomatchmovah,9int21hexit:

retmain

endpprognameends

end

start例5.11、在ADDR单元中存放着数Y的地址,试编制一程序,把Y中1的个数存入COUNT单元中。要测出Y中1的个数,就应逐

位测试,一个比较简单的办法是可根据最高有效位是否为1来计数,然后用移位的方法把各位数逐次移到最高位去。循环的结束可以用计数值为16来控制,但更好的办法是结合上述方法可以用测试数是否为0来作为结束条件,这样可以在很多情况下缩短程序的执行时间。2.条件控制例5.11、在ADDR单元中存放着数Y的地址,试编制一程序,把Y中1的个数存入COUNT单元中。要测出Y中1的个数,就应逐

位测试,一个比较简单的办法是可根据最高有效位是否为1来计数,然后用移位的方法把各位数逐次移到最高位去。循环的结束可以用计数值为16来控制,但更好的办法是结合上述方法可以用测试数是否为0来作为结束条件,这样可以在很多情况下缩短程序的执行时间。例5.11、在ADDR单元中存放着数Y的地址,试编制一程序,把Y中1的个数存入COUNT单元中。DataAddrsegmentdwnumberNumberdw1100110011110000BCountdw?DataPrognamendssegmentMainproc

farAssameStart:

Mov

ax,

dataMov

ds,

axMovMovMovcx,

0

;bx,

addrax,

[bx];

ax

=

offffRepeat:jztest

ax,

offfffhexit

;为零则exit,ZF=1ax正数则转移(非负)shift:;

逻辑左移,最右添0exit:jns

shift

;inc

cxshl

ax

,1jmp

repeatcount

,cxmov

dl,

clmov

ah,

2mov

ah,4ch这个例子说明算法和循环控制条件的选择对程序的工作效率影响很大。在编程时,应据具体情况来确定循环控制条件。第二种解法:【例5.11】试编一个程序将字单元BUF中所含1的个数存入COUNT单元中。要测出BUF字单元所含1的个数,首先将BUF中的数送给寄存器AX,然后将AX寄存器逻辑左移一次,如果CF=1,则表明AX中的最高位为1,则计数器CL计数1次,如果CF=0,表明AX最高位为0,这样依次将最高位移入CF中去测试。移位之后,判断AX的值是否为0,如果为0则结束循环,不为0,则继续循环。其流程图如图5.8所示。程序如下:STACK

SEGMENT

STACKDB

200

DUP(0)STACK

EDNSDATA

SEGMENTDWBUF0011110010101011BCOUNTDB

?DATACODEENDSSEGMENTASSUME

DS:DATA,CS:CODE,SS:STACKSTART:MOV

AX,DATAMOV

DS,AXMOV

AX,BUFMOV

CL,0;计数器为0;(AX)=0,结束循环LOPA:

CMP

AX,0JE

EXITSHL

AX,1;AX左移一位JNC

LOPAINC

CL;产生进位,(CL)+1→CLJMP

LOPAEXIT:

MOV

COUNT,CLMOV

AH,4CHINT

21H3、循环条件设计方法综合举例例5.10、试编制一个程序把BX寄存器内的二进制数用十六进制数的形式在屏幕上显示出来。把BX的内容从左到右每4位为一组在屏幕上显示出来,显然这可以用循环结构来完成,每次循环显示一个十六进制数位,因而循环次数是已知的,BX中存放十六个二进制数位,故计数值为4。程序中用CH寄存器存放循环计数值:CH=

4,而用DEC及JNZ两条指令完成循环计数功能;因为循环移位要用CL寄存器,而LOOP指令也要使用CX,故循环不用LOOP语句。BX

0011,0110,0011,0111

显示为3637HBX

0110,0011,

0111,

0011

BL

0111,0011,左移4次and

al,ofH;00110000,

1111

al

0110000,

0011

al

0000,0011add

al,30H0011,00000011,0011al例1

将BX寄存器中的内容以十六进制形式显示出来。▲BX是一个16位寄存器二进制

1010

1001

0011

1110▲用十六进显示时,每4位用一个字符显示,共4个其中:

0000

→’0’30H

,1010

→’A’

41H0001

→’1’31H

,1011

→’B’

42H、、、、1001

→’9’39H

,1111

→’F’

46H?‘E’十六进制A9

3E屏幕上的显示对应的ASCII‘A’

‘9’41H

39H

33H‘3’45H0000

0001B

+

30H=

31H0001B

‘1’0000

1001B

+

30H=39H1001B‘9’(2)对于1010~1111(A~F),先扩展成一个字节,高4位清0,加上30H后,还要再加上07H,才能得到’A’~’F’对应的ASCII码0000

1010B+30H+07H

=

41H1010B

‘A’0000

1111B+30H+07H

=46H1111B‘F’算法:取出要显示的某4位,转换为对应的ASCII码,再调用DOS系统功能进行显示。(1)对于0000~1001(0~9),先扩展成一个字节,高4位清0,加上30H后,即可得字符’0’~’9’对应的ASCII码。这里采用了循环移位的方法,把所有显示的四位二进制数移到最右面,以便作数字到字符的转换工作。另外由于数字0~9的ASCII为30~39H,而字母A~F的ASCII为41~46H,所以在把四位二进制数加上30H后还需做一次判断,如果为字符A~F,则还应加上7才能显示出正确的十六进制数二进制到十六进制转换C显示字符个数CH=4循环移位次数CL=4BX循环左移4位,将要显示的值移至低4位,保存在DL中清DL的高4位,

只保留要显示位的值DL

DL+30H完成数值0~9的ASCII码转换N完成数值A~F的ASCII码转换用02功能显示DL中的字符NDL超出39H?YDL←DL+07HCH←CH-1转换结束?YRET返回list_bx

PROCMOV

CH,

4MOV

CL,

4next:ROL

BX,

CLMOV

DL,

BLAND

DL,

0FHADD

DL,

30HCMP

DL,

39HJLE

printADD

DL,

07Hprint:MOV

AH,

2HINT

21HDEC

CHJNZ

nextRET

;子程返回ENDPlist_bxcodeENDSEND

start例5.10、试编制一个程序把BX寄存器内的二进制数用十六进制数的形式在屏幕上显示出来。data

segmrntcount

dw

3637Hdata

endsprognam

segmentMain

proc

farassumestart:

pushcs:

prognam,ds:datadssub

ax,

axpush

axmov

bx,

countmov

ch,4;共显示4位数.next:

movrolmovcl,

4

;

计数为4.bx,

cl;

左移4次.dl,

bl

;

得到8位

ALanddl,ofh;取低4位.adddl,30h;变为ASCII码cmpdl,3ah

;

>9

?.jl

print

;

小于34h……add

dl,

07hPrint:Mov

ah,2;Ascii

dl,调中断显示Int21

h;Decch;显示4位吗?Jnz

nextRet;再执行显示二位.←

①mov

Ax,4c00h②Int21HMain

endpPrognam

ends例5.15、设有数组X和Y。X数组中有X1到X10;Y数组中有Y1到Y10;试编程计算:Z1=X1+Y1;

Z2=X2+Y2;

Z3=X3-Y3;Z4=X4-Y4;

Z5=X5-Y5;Z6=X6+Y6;Z7=X7-Y7;

Z8=X8-Y8;

Z9=X9+Y9;Z10=X10+Y10。结果存入Z数组,对于这种问题,我们也可用循环来完成;已知循环计数值为10,每次循环的操作数是可以顺序取出的,但所做的操作却有不同,这里有两种操作:加、减,为了区别每次应该做那一种操作,可以设置标志位,如标志为0作加法;为1则做减法,这样进入循环后只要判别标志位,就可确定应该做的操作了。把10次操作设立10个标志位,我们把它放在一个存储单元LOG中,这种存储单元一般称为逻辑尺,本例设定逻辑尺为:0000

0000

1101

1100从低位开始所设的标志位反映了每次要做的操作顺序,最高的6位没有意义,设为0。Zi=Xi+Yi4

s3s2s

1I=10s9s

8s

7s6s5s+操作设立10个标志位0+,--+-,--++10次0,1101,1100位=16

15

14

13s12

11

10

9s

8

7

6

5s3

2

1字:0

0

0

0

0

0

0

0,1

1

0

1,1

1

0

0=

0DCHZ1=X1+Y1;

Z2=X2+Y2;

Z3=X3-Y3;Z4=X4-Y4;Z5=X5-Y5;

Z6=X6+Y6;Z7=X7-Y7;Z8=X8-Y8;Z9=X9+Y9;

Z10=X10+Y10mov

bx,0mov

cx,10logmov

dx,next:

movax,

x[bx]shrdx

,

1jcsubtaddax,

y[bx]datasegment;数据段xdw2,3,4,5,6,7,8,9,10,11;ydw1,2,3,4,5,6,7,8,9,10;Zdw10dup(?);logdw00dchdataends;代码段prognammainprocsegmentfarassumecs:prognam,ds:datastart:pushdssubpushmova;初始化movax,

axaxax,

datds,

axnext:mov

bx,

0mov

cx,

10mov

dx,

logmov

ax,

x[bx];循环shr

dx

,

1jc

subtadd

ax,

y[bx]jmp

shortresultsubt:result:sub

ax

,

y[bx]mov

z[bx],axadd

bx

,2nextloopretmainprognamendpendpend例5.13、在附加段中,有一个首地址为list和未经排序的字数组,在数组的第一个字中存放着数组的长度,数组的首地址已存放在DI寄存器中。AX寄存器中存放着一个数。要求编制一程序;在数组中查找该数,如果找到该数则把它从数组中删除。分析:1、首先查找数组中是否有(AX),如果没有则不对数组做任何处理就结束程序;2、如果找到这一元素则应把数组中地址比该元素高(其前)的元素向低地址方向移动(后移一个

字),并修改数组长度值;3、如果找到的元素恰好位于数组的末尾,则不必移动任何元素,只要修改数组长度就可以了;所以程序第一部分——查找元素可以使用串处理命令;第二部分——删除元素则可以使用循环结构,因为查找结束时就可以知道该元素的位置,所segment‘personalDatareaMess

dbcomputer$’DatareaExtraListExtraendssegmentdw

5,

1,

2,

3,

4,

6endsCodeMainprocnear]segmentproc

far

;

[del_ulAssumc

cs:

code

,

ds:

datarea,

es:extraStart:PushdsSubax,axPushaxMovax,datareaMovds

,axlistMov

di

,

offsetCldMovax,2

;要删除的数为2Push

diMov

cx

,es

:

[di];元素个数5→

cxdi

,2;每个元素ax,

es:[di];

←RepneLop:Add占两个字节cmpscaswJe

delete;找到转deletedec

cxjnz

lopDelete:

jcxe

deccntNextel:mov

bx

,es

:

[di]Mov

es:

[di-2],

bxAdd

di

,2Loop

NextelDeccnt:

pop

didec

word

ptr

es:[di]Exit:

retMain

endp[

del_ulendp]Code

endsEnd

start用子程序方法编制程序如下:del_ul

proc

farCld

Push

di;DF=0时,向前查找。;右起始地址;Mov

cx,

es:[di] ;

取元素数;Add

di

,

2 ;

改变指针。Repne

scaswJz

delete

;结果为0,ZF=1.转,此时CX值

温馨提示

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

评论

0/150

提交评论