ADD MOV ADD STD REP RET ENDP ENDS
SI,199 DI,SI DI,8
MOVSB
;SI=10C7H ;DI=10CFH ;自动减量
MAIN CODE
END MAIN
简析:
由题意可知,源数据区(占用地址3DA0:1000H~3DA0:10C7H,共200个字节)与目标数据区(占用地址3DA0:1008H~3DA0:10CFH,共200个字节)是重叠的。若从首址开始增量传送(DF=0),将破坏1008H以后的源数据,所以必须从末址向首址减量传送(DF=1)。 数据段初始化时,有以下几点需注意:段基址规定为3DA0H,故应在段定义伪指令SEGMENT后加上AT语句;源数据区首址的偏移量规定为1000H,故应使用ORG语句指明;对源、目标数据区进行定义时,应注意目标数据区首址的偏移量是1008H。如果定义为:
ORG 1000H
SOUR DEST
DW DW
100 DUP(?) 100 DUP(?)
;源数据区 ;目标数据区
则目标数据区首址的偏移量实际上是10C8H,不合题意。可将它们统一定义为足够长度
(至少104字或208字节)的变量,如参考程序所示。
指针初始化时,可以将SI、DI分别置为10C7H、10CFH,且CX=200,即进行字节的传送,使用MOVSB;亦可将SI、DI分别置为10C6H、10CEH,且CX=100,即进行字的传送,相应使用MOVSW。
12. 从内存单元BUF开始的缓冲区中有7个8位无符号数,依次为13H、0D8H、92H、2AH、66H、0E0H、3FH。编程找出它们的中间值并放入RES单元,且将结果以“(RES) = ?”的格式显示在屏幕上。
答:一种可能的程序如下实现:
DATA
BUF RES STR STR1 DATA SSEG
SSEG CODE
MAIN
SEGMENT DB DB DB ENDS
SEGMENT PARA STACK‘SSEG’ DB ENDS SEGMENT
ASSUME CS:CODE,SS:SSEG,DS:DATA,ES:DATA PROC PUSH
FAR DS
;主程序
100 DUP(?)
13H,0D8H,92H,2AH,66H,0E0H,3FH ?
;中间数的存放单元
DB ‘(RES)=’
?,?,‘$’
;结果字符串
XOR PUSH MOV MOV MOV MOV MOV MOV INC MOV CMP JB
AX,AX AX AX,DATA DS,AX ES,AX CX,6 DI,SI DI
DX,6 AL,[SI] AL,[DI] UNCH
AL,[ DI ] [ SI ],AL SI DI DX AGN1 AGN RES,AL AL,0F0H CL,4 AL,CL BATR
;调子程序,将AL值转换为ASCII码 ;DI指向结果单元 ;存放转换结果 ;分离并转换低半字节
DI,STR1
;分离高半字节
;未处理完,继续内循环 ;外循环
;排序完成,取中间数
;两个无符号数相比较 ;小于则转,不互换 ;前1单元较大,则互换 ;大数放在后面
;修改指针,指向下一个数
;有STOS指令,需用ES ;外循环次数,比6次
;SI、DI指向相邻2数 ;内循环次数,比6次
AGN: SI,OFFSET BUF
AGN1: MOV
EXCH: XCHG
MOV INC DEC JNZ LOOP MOV AND MOV SHR CALL LEA CLD STOSB MOV AND CALL STOSB LEA MOV INT RET ENDP PROC CMP JB
ADD
UNCH: INC
DONE: MOV AL,[SI-3]
AL,RES AL,0FH BATR DX,STR AH,09H 21H
;主程序MAIN结束
;显示整个字符串
MAIN BATR
;子程序BATR,实现16进制数到ASCII码的转换
NEAR AL,10 NUM AL,’0’
;入口参数为AL ;是数字,则转NUM ;字母
AL,’A’-10-’0’
NUM: ADD
RET ENDP ENDS END MAIN
;子程序结束
BATR CODE
简析:
本例的基本思路是:先把7个无符号数按大小排序,排序完成之后取位于中间的一个数即为中间值。然后将该16进制数转换为两个对应的ASCII码,再与要求的格式字符一起输出送显即可。
数据排序可以是从大到小、或从小到大排列,本参考程序完成从小到大排序,由一个双重循环结构实现。内循环完成一个数与其它数之间的一一比较,并使每次比较所得的小数置于低地址单元。外循环实现所有数之间的两两相较。共7个数据,故内、外循环中的比较次数均为6次。
编程时需注意:无符号数比较大小应使用JA、JB、JAE、JBE指令,本例完成从小到大的排列,故用JB控制转移到UNCH;若要从大到小排列,则用JA代替JB即可。 对两个循环体进行初始化时,需仔细考虑指针和循环控制寄存器的初值。在数据段的定义中,分别定义STR、STR1两个变量名字,是为了便于在STR1处存放转换结果;显示时使DX直接指向STR,以STR1末尾的“$”为结束符。中间值找出之后,应把高、低半字节相分离,并分别转换为各所对应的ASCII码。
13. 设某测试系统中,1号端口为测试口,所得数据是0~9之间的十进制整数;2号端口为显示口,对应于数字0~9的LED七段共阴显示码依次为:3FH、06H、5BH、4FH、66H、6DH、3DH、07H、7FH、6FH。编写一段查表送显的程序,要求:先从测试口读入一个数据,再查表将相应的显示码从显示口送出,如此反复进行直至读入数据“0FFH”为止。
答:一种可能的程序如下实现:
DATA
TAB DATA STACK
STACK CODE
SEGMENT DB DB ENDS
SEGMENT PARA STACK‘STACK’ DW ENDS SEGMENT
ASSUME CS:CODE,SS:STACK,DS:DATA
AX,DATA DS,AX BX,TAB AL,1 STOP TAB 2,AL NEXT
AL,0FFH
;是0FFH,结束 ;不是0FFH,查表转换 ;向显示口输出七段码 ;继续测试
;BX指向表首址
;从测试口输入
MOV LEA
CMP JE XLAT OUT JMP
50
DUP(?)
3FH,06H,5BH,4FH,66H 6DH,3DH,07H,7FH,6FH
;0~9的七段码
START: MOV
NEXT: IN
STOP: MOV AH,4CH
INT ENDS
21H
CODE
END START
14. 编程实现以下操作:从键盘输入4个数字,分别作为2个10~99之间的十进制数。求它们的和,并把结果以三位十进制数的形式显示在屏幕上。要求:输入回显的两个加数与送显的和之间有适当的分隔,以示区别。格式可自行拟定。
答:一种可能的程序如下实现:
DATA
NUM1 NUM2 SUM DATA STACK
STACK CODE
SEGMENT DB DB DB ENDS
SEGMENT PARA STACK‘STACK’ DW ENDS SEGMENT
ASSUME CS:CODE,SS:STACK,DS:DATA,ES:DATA
AX,SEG NUM1 DS,AX ES,AX
CX,2 DI,NUM1 AH,1 21H AL,0FH IN1 DL,‘+’ AH,2 21H CX,2 DI,NUM2 AH,01H 21H AL,0FH IN2 DL,‘=’ AH,02H 21H SI,NUM1 SI
;SI指向加数1的低位
;输出等号,分隔加数与结果
;输入加数2
;输出加号,以分隔2个加数
;ASCII码转换为非组合BCD码
;输入加数1
;DOS功能调用,单字符输入
;有STOS指令,需用ES ;自动增量,先输入高位
MOV MOV CLD MOV LEA MOV INT AND STOSB LOOP MOV MOV INT MOV LEA MOV INT AND STOSB LOOP MOV MOV INT LEA INC
50 DUP(?) ?,? ?,?
;加数1,高位在前,以非组合BCD码存放 ;加数2,高位在前,以非组合BCD码存放 ;存放结果的ASCII码,以‘$’为结束符
?,?,?,‘$’
FIRST: MOV
IN1:
IN2:
LEA INC LEA ADD STD MOV CLC LODSB ADC AAA PUSHF ADD POPF
BX,NUM2 BX DI,SUM DI,2
CX,2
;DI指向结果的末单元 ;自动减量,由低向高相加 ;相加次数
;清进位,准备用ADC ;取加数1的低位,修改SI ;2数相加,带进位
;未组合BCD码的十进制调整 ;BCD码向ASCII码转换
;BX指向加数2的低位
AD:
AL,[BX]
AL,30H
;因未组合BCD码的高4位为0,故加30H不会影响CF
STOSB DEC LOOP ADC LEA MOV INT MOV INT ENDS END FIRST
AD
BYTE PTR [DI],30H DX,SUM AH,09H 21H AH,4CH 21H
;返回DOS
;BCD码向ASCII码转换 ;输出结果
;存和,并修改DI。CF不变 ;指向加数2的高位。CF不变
BX
;高位相加若产生进位,则使SUM单元加1(表示百位),故使用ADC指令
CODE
简析:
按照本参考程序,屏幕显示格式如“73+46=119”的样式。基本思路是:首先调用DOS功能,从键盘输入2个0~9之间的数字(字符串输入的AH调用号为10,单个字符输入的AH调用号为1),然后向CRT输出“+”(单个字符输出的AH调用号为2);再由键盘输入2个数,然后输出“=”。将两次输入的数分别作为2个加数相加,得到的和经十进制调整后,向CRT输出(字符串输出的AH调用号为9)。 以下几处需进行码制转换:调用单个字符输入功能后,AL中的出口参数为各数字键所对应的ASCII码,故应转换为BCD码才能进行加运算。转换方式:与0FH相与,所得为未组合BCD码。2个未组合BCD码相加,和应该用AAA指令进行十进制调整,调整结果反映在累加器和标志位CF上。加法完成之后,应将结果逐位转换为ASCII码,才可以向CRT输出。
做加法运算时还应注意:加数输入之后,先取两个低位相加,再取高位相加(同时加上低位相加产生的进位),需仔细检查指针。若用循环结构完成加运算,则进入循环之前必须清CF,方可在循环体中使用ADC指令。
15. 有一个长度不超过100字节的字符串,以回车符结尾。编程统计其中非空格的字符个数,并将统计结果以自拟格式显示在CRT上。
答:一种可能的程序如下实现: