




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第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
;
小于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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 安徽省阜阳市第一中学2025届高三第六次模拟考试化学试卷含解析
- 保险行业鼓励动员
- 贵州省黎平县第三中学2025届高三第二次诊断性检测化学试卷含解析
- 陕西省西北工业大学附中2025年高三3月份模拟考试化学试题含解析
- 2025年重水堆核电站及配套产品项目发展计划
- 河南省偃师市高级中学2025届高考适应性考试化学试卷含解析
- 恶心呕吐脑出血护理诊断
- 护理技能操作年终总结
- 2025届福建省福清福清华侨中学高考化学二模试卷含解析
- 小班德育教育
- 法院系统组成和职责解析
- 访谈记录表模板
- 油库消防安全知识培训
- 初高中物理的区别以及如何学好高中物理课件
- 六年级下册语文第三单元交流平台人教统编版课件
- 山东省烟台市牟平区(五四制)2023-2024学年七年级上学期期中考试历史试题
- 文件学生体质健康登记卡高中样表
- 撤销冒名登记(备案)申请表
- 资产评估常用数据与参数手册
- 非淹没矩形堰、三角堰、梯形堰流量计算
- 牛排培训大全课件
评论
0/150
提交评论