程序.docx
《程序.docx》由会员分享,可在线阅读,更多相关《程序.docx(22页珍藏版)》请在冰豆网上搜索。
程序
字符串显示:
例:
编写一段显示字符串STRING的程序
DATASEGMENT
STRINGDB‘HAPPYNEWYEAR!
’,0DH,0AH,‘$’
COUNTDW17
DATAENDS
MOVCX,COUNT
MOVSI,0
NEXT:
MOVDL,STRING[SI]
MOVAH,2
INT21H;显示一个字符
INCSI
(2)DOS显示字符串功能
LEADX,STRING
MOVAH,9
INT21H;显示一串字符,串必须以$结束
;DS:
DX=串地址
字扩展
顺序结构程序设计
例编写程序,计算(W-(X*Y+Z-100))/W,其中W、X、Y、Z均为16位带符号数,计算结果的商存入AX,余数存入DX。
DATASEGMENT
WDW268
XDW–73
YDW48
ZDW–85
DATAENDS
STACKSEGMENT
DW100DUP(?
)
STACKENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK
START:
MOVAX,DATA
MOVDS,AX
MOVAX,X;计算X*Y
IMULY
MOVCX,AX;用CX存储结果低位
MOVBX,DX;用BX存储结果高位
MOVAX,Z;计算X*Y+Z
CWD
ADDCX,AX
ADCBX,DX
SUBCX,100;计算X*Y+Z-100
SBBBX,0
MOVAX,W;计算W-(X*Y+Z-100)
CWD
SUBAX,CX
SBBDX,BX
IDIVW;商送AX,余数送DX
MOVAH,4CH
INT21H
CODEENDS
ENDSTART
排序:
例4-23把从BUF单元开始的80个16位无符号数按从大到小的顺序排列。
分析:
Ø这是排序问题,无符号数的比较可以直接用比较指令CMP和条件转移指令JNC来实现
Ø这又是双重循环问题,内循环使第1个数与下一个数比较,若大于则位置保持不变,小于则将大数放低地址,小数放高地址(两数交换),外循环进行79次,完成对80个无符号数的大小排序
采用先执行后判断循环结构,程序流程图如图4-4所示。
DSEGSEGMENT
BUFDW80DUP(?
);已存入这80个字单元
DSEGENDS
CSEGSEGMENT
ASSUMECS:
CSEG,DS:
DSEG
START:
MOVAX,DSEG
MOVDS,AX
LEADI,BUF;DI指向要排序的数的首址
MOVBL,79;外循环只需79次即可
LOOP1:
MOVSI,DI;SI指向当前要比较的数
MOVCL,BL;CL为内循环计数器,循环次数每次少1
LOOP2:
MOVAX,[SI];取第一个数NI
ADDSI,2;指向下一个数NJ
CMPAX,[SI];NI≥NJ?
JNCNEXT;若大于,则不交换
MOVDX,[SI];否则,交换NI和NJ
MOV[SI-2],DX
MOV[SI],AX
NEXT:
DECCL;内循环结束?
JNZLOOP2;若未结束,则继续
DECBL;外循环结束?
JNZLOOP1;若未结束,则继续
MOVAH,4CH;返回DOS
INT21H
CSEGENDS
ENDSTART
逻辑尺:
例设有数组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
分析:
逻辑尺:
0011011100
1减法
0加法
XDWX1,X2,X3,X4,X5,X6,X7,X8,X9,X10
YDWY1,Y2,Y3,Y4,Y5,Y6,Y7,Y8,Y9,Y10
ZDWZ1,Z2,Z3,Z4,Z5,Z6,Z7,Z8,Z9,Z10
LOGIC_RULEDW00DCH
MOVBX,0
MOVCX,10
MOVDX,LOGIC_RULE
NEXT:
MOVAX,X[BX]
SHRDX,1
JCSUBTRACT
ADDAX,Y[BX]
JMPSHORTRESULT
SUBTRACT:
SUBAX,Y[BX]
RESULT:
MOVZ[BX],AX
ADDBX,2
LOOPNEXT
进制转换
例把BX中的二进制以十六进制的形式显示在屏幕上
MOVCH,4
ROTATE:
MOVCL,4
ROLBX,CL
MOVAL,BL
ANDAL,0FH
ADDAL,30H;’0’-’9’ASCII30H-39H
CMPAL,3AH
JLPRINTIT
ADDAL,7H;’A’-’F’ASCII41H-46H
PRINTIT:
MOVDL,AL
MOVAH,2
INT21H;附录4,P357
DECCH
JNZROTATE
例4-27把一个二进制数转换为BCD码。
DATASEGMENT
HEXDW1234H
BCDDW0,0
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA
MOVDS,AX
MOVAX,HEX
XORBX,BX;用于存结果
MOVCX,0404H;移位CL=4及循环次数CH=4
MOVBP,10;除数
LOOP1:
XORDX,DX
DIVBP
RORDX,CL
RORBX,CL
ORBX,DX
DECCH
JNZLOOP1
MOVBCD,BX
MOVBCD+2,AX
MOVAH,4CH
INT21H
CODEENDS
ENDSTART
;将AX中的4位BCD码装换成16进制
DATASEGMENT
NUMDW1234
DATAENDS
CODESEGMENT
ASSUMEDS:
DATA,CS:
CODE
START:
MOVAX,DATA
MOVDS,AX
MOVBX,NUM
MOVBP,0
MOVDI,4
L2:
MOVCX,4
XORAX,AX
L1:
RCLBX,1
RCLAX,1;AX=0001H
LOOPL1
XCHGAX,BP
MOVSI,10
MULSI
XCHGAX,BP
ADDBP,AX
DECDI
JNZL2
MOVAX,BP
MOVAH,4CH
INT21H
CODEENDS
ENDSTART
排序
例:
在自BLOCK开始的内存缓冲区中,有100个带符号的16位数,要找出其中的最大值,把它存放到MAX单元中。
MOVBX,OFFSETBLOCK
MOVAX,[BX]
INCBX
INCBX
MOVCX,99
L1:
CMPAX,[BX]
JGEL2(不小于则转移)
MOVAX,[BX]
L2:
INCBX
INCBX
DECCX
JNZL1
MOVMAX,AX
数据的输入与输出
输入一个字符:
01
使用中断21H,功能调用号为01H,将输入任意键入的字符,存入AL中(ASCII码)
MOVAH,01H
INT21H
输入字符串:
0A
DX=缓冲区首址
LEADX,BUF
MOVAH,0AH
INT21H
例:
输入字符串(AH=0ah)
缓冲区的第一个字节保存最大字符数,这个最大字符数由用户程序给出。
第二个字节是实际输入字符的个数,由功能A填入,不是由用户填入。
在这两个字节之后,字符串按字节存入缓冲区,结束字符串的回车符0DH还要占用一个字节。
(1)maxlendb32
actlendb?
stringdb32dup(?
)
leadx,maxlen
movah,0ah
int21h
输出一个字符:
02
使用02号功能,将DL中的字符显示出来
MOVDL,‘X’
MOVAH,02H
INT21H
输出字符串:
09
DX=串地址串必须以$结束,光标跟随串移动
LEADX,DATA
MOVAH,09H
INT21H
例:
显示单个字符(AH=2)
movah,2
movdl,‘A’
int21h
例:
显示字符串(AH=9)
stringdb‘HELLO’,0dh,0ah,‘$’
leadx,string
movah,9
int21h
EX1从键盘上键入20个字符,将键入的字符按相同的顺序显示出来。
键入时,每键入一个字符,输出一个空格。
DATADB20DUP(?
)
DSEGENDS
STACK1SEGMENT
DB200DUP(0)
STACK1ENDS
CSEGSEGMENT
ASSUMECS:
CSEG,DS:
DSEG,SS:
STACK1
START:
MOVAX,DSEG
MOVDS,AX
LEASI,DATA
MOVCX,20
LP1:
MOVAH,01H
INT21H
MOV[SI],AL
INCSI
MOVDL,20H
MOVAH,02H
INT21H
LOOPLP1
LEASI,DATA;若要相反顺序输出,此句省略
MOVCX,14H
MOVDL,0DH;回车
MOVAH,02H
INT21H
MOVDL,0AH;换行
MOVAH,02H
INT21H
LP2:
MOVDL,[SI]
MOVAH,02H
INT21H
INCSI;若要相反顺序输出,此句改为DECSI
LOOPLP2
MOVAH,4CH
INT21H
CSEGENDS
ENDSTART
NAME
DATASSEGMENT
STRINGDB'WHAT'SYOURNAME?
$';显示字符串!
!
注意要加$!
!
;输入字符串
DA1DB32;输入字符串最大长度为32位(字符串都用DB定义)
DB?
;输入字符串实际长度为?
DB32DUP(?
);最大长度32位下的实际语句定义
DATASENDS
CODESSEGMENT
ASSUMECS:
CODES,DS:
DATAS
START:
MOVAX,DATAS
MOVDS,AX;这里开始初始化
MOVDX,OFFSETSTRING
MOVAH,09H
INT21H;DOS功能调用,显示字符串WHAT'SYOURNAME?
LEADX,DA1
MOVAH,0AH
INT21H;键入到缓冲区,即把键入的字符串存到DS:
DX
MOVAH,4CH
INT21H
CODESENDS
ENDSTART
相加
例、1+2+3+……+100=?
并显示出来。
DATASEGMENT
BUFDB8DUP(0);最大长度8,初值0
DATAENDS
STACK1SEGMENT
DB200DUP(0)
STACK1ENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA,SS:
STACK1
START:
MOVAX,DATA
MOVDS,AX
MOVBX,1;加数
MOVAX,0;和
MOVCX,100;次数
L1:
ADDAX,BX
INCBX
LOOPL1;5050
MOVCX,0
MOVBX,10
LEASI,BUF
L2:
MOVDX,0
DIVBX
PUSHDX;保存余数
INCCX;保存个数计数
ORAX,AX
JNEL2;商AX不为0则循环
L3:
POPDX
ADDDL,30H
MOV[SI],DL
INCSI
DECCX
JNEL3
MOV[SI],BYTEPTR0DH先生成表格再输出
MOV[SI+1],BYTEPTR0AH
MOV[SI+2],BYTEPTR'$'
LEADX,BUF;
MOVAH,09H
INT21H
MOVAH,4CH
INT21H
CODEENDS
ENDSTART
MIN
DATASEGMENT;数据段
DAT1DB22H,1AH,4DH,6EH,9FH
DDB?
DATAENDS
CODESEGMENT;代码段
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA;初始化
MOVDS,AX
LEASI,DAT1
MOVCX,5
CLD
LODSB
MOVD,AL;将该数送至D
DECCX
NEXT:
LODSB;取下一个数
CMPAL,D
JLSMALL
JMPGOON
SMALL:
MOVD,AL
GOON:
LOOPNEXT
MOVAX,4C00H;退出程序
INT21H
CODEENDS
ENDSTART
STRING
DATASSEGMENT;数据段
STR1DB'ZIYUANAO'
STR2DB'ILOVEYOU'
DATASENDS
CODESSEGMENT;代码段
ASSUMECS:
CODES,DS:
DATAS
START:
MOVAX,DATAS;初始化
MOVDS,AX
LEASI,STR1
LEADI,STR2
MOVCX,10
CLD
REPMOVSB
MOVAX,4CH;退出程序
INT21H
CODESENDS
ENDSTART
WXYZ
DATASEGMENT;数据段
XDW0001H
YDW0002H
ZDW0003H
WDW0004H
DATAENDS
CODESEGMENT;代码段
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA;初始化
MOVDS,AX
MOVAX,X
IMULY
MOVBX,AX
MOVCX,DX
MOVAX,Z
CWD
ADDBX,AX
ADCCX,DX
SUBBX,100
SBBCX,0
MOVAX,W
CWD
SUBAX,BX
SBBDX,CX
IDIVX
MOVAX,4C00H;退出程序
INT21H
CODEENDS
ENDSTART
ZERO
DATASEGMENT;数据段
DDW?
ADW1
BDW2
CDW3
DATAENDS
CODESEGMENT;代码段
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA;初始化
MOVDS,AX
CMPA,0
JNZNEXT
CMPB,0
JNZZERO
CMPC,0
JNZZERO
ORA,1
ORB,1
ORC,1
JMPOK
NEXT:
CMPB,0
JZZERO
CMPC,0
JZZERO
MOVAX,A
ADDAX,B
ADDAX,C
MOVD,AX
JMPOK
ZERO:
ANDA,0
ANDB,0
ANDC,0
OK:
MOVAX,4C00H;退出程序
INT21H
CODEENDS
ENDSTART
串处理
编程实现两个长度都是10个字符的字符串str1(在数据段中)和str2(在附加段中)比较。
如果两串完全相等,则跳转到rout1执行,否则继续执行。
……
LEASI,STR1
LEADI,STR2
CLD
MOVCX,10
REPECMPSB
JCXZROUT1x
……
ROUT1:
……
例比较两个字符串是否有相同的元素,它们的首地址和目标地址分别为SRC和DEST,字符串的长度为N个字节。
CLD;DF=0,增量方向
LEASI,SRC;DS:
SI←字符串首地址
LEADI,ES:
DEST;ES:
DI←目标地址
MOVCX,N;字符串长度
REPNECMPSB;重复比较字符串
JNZNOT_FOUND;无相同的元素,
转NOT_FOUND,
否则继续执行下条指令
例在首地址为ES:
DEST的字符串中检查是否有字符’M’,字符串的长度为N个字节。
CLD;DF=0,增量方向
LEADI,ES:
DEST;ES:
DI←目标地址
MOVCX,N;字符串长度
MOVAL,’M’;AL←搜索字符
REPNESCASB;重复搜索字符串是否
有字符’M’
例将首地址为DS:
SRC的字节数据串中非0元素送到首地址为ES:
DEST的内存区中。
字符串长度为N。
CLD;DF=0,增量方向
LEASI,SRC;DS:
SI←字符串首地址
LEADI,ES:
DEST;ES:
DI←目标地址
MOVCX,N;字符串长度
GOON:
LODSB;取字符串的一个元素
CMPAL,0;字符串元素为0吗?
JZNEXT;是0,继续下一个元素
STOSB;非0,存入首地址为ES:
DEST的内存区中
NEXT:
DECCX
JNEGOON
分类
例若在内存缓冲区有一个数据块,起始地址为BLOCK,若数据块中有正负数,要把正负分开,正数放缓冲区的起始地址为PLVS_DATA,负的放MINVS_DATA
设SI——源数指针DI
BX——负数目的区指针
LODS指令把源数送到AL中
MOVSI,OFFSETBLOCK
MOVDI,OFFSETPLVS_DATA
MOVBX,OFFSETMINVS_DATA
MOVCX,COUNT循环次数
GOON:
LODSBLOCK
TESTAL,80H检查其符号位,为负,则MIVS
JNZMIVS
STOSB正数存入PLVS-DATA
JMPAGAIN
MIVS:
XCHGBX,DI
STOSB
XCHGBX,DI
AGAIN:
DECCX
JNZGOON
HLT
例在存储器中有一个首地址为ARRAY的N字数组,要求测试其中正数、0及负数的个数,正数的个数放在DI中,0的个数放在SI中,并根据N-(DI)-(SI)求得负数的个数放在AX中,如果有负数则转移到NEG_VAL中去执行。
MOVCX,NNEXT:
ADDBX,2
MOVBX,0DECCX
MOVDI,BXJNZAGAIN
MOVSI,BXMOVAX,N
AGAIN:
CMPARRAY[BX],0SUBAX,DI
JLELESS-OR-EQSUBAX,SI
INCDIJZSKIP
JMPSHORTNEXTJMPNEARPTRNEG-VAL
LESS-OR-EQ:
JLNEXTSKIP:
INCSINEG-VAL:
例3-54在以DATA为首地址的内存数据段中,存放有200个16位有符号数,试找出其中最大和最小的有符号数,并分别放在MAX和MIN为首的内存单元中
比较有符号数的大小,应采用JG和JL等用于有符号数的条件转移指令
START:
LEASI,DATA;(SI)←数据块首地址
MOVCX,200;(CX)←数据块长度
CLD;清方向标志DF
LODSW;(AX)←一个16位有符号数
MOVMAX,AX;将该数送MAX
MOVMIN,AX;将该数送MIN
DECCX;(CX)←(CX)-1
NEXT:
LODSW;取下一个16位有符号数
CMPAX,MAX;与MAX单元内容进行比较
JGLARGER;若大于则转LARGER
CMPAX,MIN;否则再与MIN单元内容进行比较
JLSMALL;若小于MIN的内容则转SMALL
JMPGOON;否则就转至GOON
LARGER:
MOVMAX,AX;(MAX)←(AX)
JMPGOON
SMALL:
MOVMIN,AX;(MIN)←(AX)
GOON:
LOOPNEXT;(CX)-1,若CX≠0,则转NEXT