DISPN: DISP:
STOP:
JNZ INPUT MOV CX, 16 MOV DL, 0 ROL BX, 1 RCL DL, 1 OR DL, 30H MOV AH, 2 INT 21H LOOP DISP RET
;将16位二进制数一位位地转换成ASCII码显示
;进行显示
5.10 设有一段英文,其字符变量名为ENG,并以$字符结束。试编写一程序,查对单词SUN在该文中的出现
次数,并以格式“SUN:xxxx”显示出次数。 答:程序如下:
DSEG SEGMENT ENG DB ‘Here is sun, sun ,?,$’ DISP DB ‘SUN:’ DAT DB ‘0000’ , 0DH, 0AH, ‘$’ KEYWORD DB ‘sun’ DSEG ENDS
;-------------------------------------------------------------------------- CSEG SEGMENT MAIN PROC FAR
ASSUME CS: CSEG, DS: DSEG, ES: DSEG
START: PUSH DS ;设置返回DOS
SUB AX, AX PUSH AX MOV AX, DSEG MOV DS, AX ;给DS赋值 MOV ES, AX ;给ES赋值
BEGIN:
MOV AX, 0
MOV DX, DISP-ENG-2 LEA BX, ENG
COMP: MOV DI, BX
LEA SI, KEYWORD MOV CX, 3 REPE CMPSB JNZ NOMATCH INC AX ADD BX, 2
NOMATCH: INC BX
DEC DX JNZ COMP
DONE: MOV CH, 4
MOV CL, 4 LEA BX, DAT
DONE1: ROL AX, CL
MOV DX, AX AND DL, 0FH ADD DL, 30H CMP DL, 39H JLE STORE ADD DL, 07H
STORE: MOV [BX], DL
INC BX DEC CH
;计算ENG的长度(每次比较sun,因此比较次数-2)
;串比较
;是,SUN的个数加1 ;指向ENG的下一个字母
;将次数转换为16进制数的ASCII码
;转换结果存入DAT单元中
;取一位16进制数
;是“A~F”所以要加7
;转换结果存入DAT单元中
26
JNZ DONE1
DISPLAY: LEA DX, DISP ;显示字符串程序(将DISP和DAT一起显示)
MOV AH, 09H INT 21H RET
MAIN ENDP CSEG ENDS ;以上定义代码段
;--------------------------------------------------------------------------
END START
5.11 从键盘输入一系列以$为结束符的字符串,然后对其中的非数字字符计数,并显示出计数结果。
答:程序段如下:
DSEG SEGMENT BUFF DB 50 DUP (‘ ’) COUNT DW 0 DSEG ENDS
┇
BEGIN: LEA BX, BUFF
MOV COUNT, 0
INPUT: MOV AH, 01 ;从键盘输入一个字符的功能调用
INT 21H MOV [BX], AL INC BX
CMP AL, ‘$’ ;是$结束符吗? JNZ INPUT ;不是,继续输入 LEA BX, BUFF ;对非数字字符进行计数
NEXT: MOV CL, [BX]
INC BX
CMP CL, ‘$’ ;是$结束符,则转去显示 JZ DISP CMP CL, 30H ;小于0是非数字字符 JB NEXT CMP CL, 39H ;大于9是非数字字符 JA NEXT INC COUNT ;个数+1 JMP NEXT
DISP: ┇ ;16进制数显示程序段(省略) 5.12 有一个首地址为MEM的100D字数组,试编制程序删除数组中所有为0的项,并将后续项向前压缩,最后将数组的剩余部分补上0。 答:程序如下:
DSEG SEGMENT MEM DW 100 DUP (?) DSEG ENDS
;-------------------------------------------------------------------------- CSEG SEGMENT MAIN PROC FAR
ASSUME CS: CSEG, DS: DSEG
START: PUSH DS ;设置返回DOS
SUB AX, AX PUSH AX MOV AX, DSEG MOV DS, AX ;给DS赋值
BEGIN: MOV SI, (100-1)*2 ;(SI)指向MEM的末元素的首地址
MOV BX, -2 ;地址指针的初值 MOV CX, 100
27
ADD BX, 2
CMP MEM [BX], 0 JZ CONS LOOP COMP JMP FINISH ;比较完了,已无0则结束
CONS: MOV DI, BX CONS1: CMP DI, SI ;到了最后单元码?
JAE NOMOV
MOV AX, MEM [DI+2] ;后面的元素向前移位 MOV MEM [DI], AX ADD DI, 2 JMP CONS1
NOMOV: MOV WORD PTR [SI], 0 ;最后单元补0
LOOP COMP
FINISH: RET MAIN ENDP CSEG ENDS ;以上定义代码段
;--------------------------------------------------------------------------
END START
5.13 在STRING到STRING+99单元中存放着一个字符串,试编制一个程序测试该字符串中是否存在数字,如
有则把CL的第5位置1,否则将该位置0。 答:程序如下:
DSEG SEGMENT
STRING DB 100 DUP (?) DSEG ENDS
;-------------------------------------------------------------------------- CSEG SEGMENT MAIN PROC FAR
ASSUME CS: CSEG, DS: DSEG
START: PUSH DS ;设置返回DOS
SUB AX, AX PUSH AX MOV AX, DSEG MOV DS, AX ;给DS赋值
BEGIN: MOV SI, 0 ;(SI)作为地址指针的变化值
MOV CX, 100
REPEAT: MOV AL, STRING [SI]
CMP AL, 30H JB GO_ON CMP AL, 39H JA GO_ON OR CL, 20H ;存在数字把CL的第5位置1 JMP EXIT
GO_ON: INC SI
LOOP REPEAT AND CL, 0DFH ;不存在数字把CL的第5位置0
EXIT: RET MAIN ENDP CSEG ENDS ;以上定义代码段
;--------------------------------------------------------------------------
END START 5.14 在首地址为TABLE的数组中按递增次序存放着100H个16位补码数,试编写一个程序把出现次数最多
的数及其出现次数分别存放于AX和CX中。 答:程序如下:
28
COMP:
DSEG SEGMENT TABLE DW 100H DUP (?) ;数组中的数据是按增序排列的 DATA DW ? COUNT DW 0 DSEG ENDS
;-------------------------------------------------------------------------- CSEG SEGMENT MAIN PROC FAR
ASSUME CS: CSEG, DS: DSEG
START: PUSH DS ;设置返回DOS
SUB AX, AX PUSH AX MOV AX, DSEG MOV DS, AX ;给DS赋值
BEGIN: MOV CX, 100H ;循环计数器
MOV SI, 0
NEXT: MOV DX, 0
MOV AX, TABLE [SI]
COMP: CMP TABLE [SI], AX ;计算一个数的出现次数
JNE ADDR INC DX ADD SI, 2 LOOP COMP
ADDR: CMP DX, COUNT ;此数出现的次数最多吗?
JLE DONE
MOV COUNT, DX ;目前此数出现的次数最多,记下次数 MOV DATA, AX ;记下此数
DONE: LOOP NEXT ;准备取下一个数
MOV CX, COUNT ;出现最多的次数存入(CX) MOV AX, DATA ;出现最多的数存入(AX) RET
MAIN ENDP CSEG ENDS ;以上定义代码段
;--------------------------------------------------------------------------
END START
5.15 数据段中已定义了一个有n个字数据的数组M,试编写一程序求出M中绝对值最大的数,把它放在数据
段的M+2n单元中,并将该数的偏移地址存放在M+2(n+1)单元中。 答:程序如下:
DSEG SEGMENT n EQU 100H ;假设n=100H M DW n DUP (?) DATA DW ? ;M+2n单元 ADDR DW ? ;M+2(n+1)单元 DSEG ENDS
;-------------------------------------------------------------------------- CSEG SEGMENT MAIN PROC FAR
ASSUME CS: CSEG, DS: DSEG
START: PUSH DS ;设置返回DOS
SUB AX, AX PUSH AX MOV AX, DSEG MOV DS, AX ;给DS赋值
29
MOV CX, n ;循环计数器 LEA DI, M MOV AX, [DI] ;取第一个数 MOV ADDR, DI ;记下绝对值最大的数的地址 CMP AX, 0 ;此数是正数吗? JNS ZHEN ;是正数,即为绝对值,转去判断下一个数 NEG AX ;不是正数,变为其绝对值
ZHEN: MOV BX, [DI]
CMP BX, 0 ;此数是正数吗? JNS COMP ;是正数,即为绝对值,转去比较绝对值大小 NEG BX ;不是正数,变为其绝对值
COMP: CMP AX, BX ;判断绝对值大小
JAE ADDRESS MOV AX, BX ;(AX)<(BX),使(AX)中为绝对值最大的数 MOV ADDR, DI ;记下绝对值最大的数的地址
ADDRESS: ADD DI, 2
LOOP ZHEN MOV DATA, AX ;记下此数 RET
MAIN ENDP CSEG ENDS ;以上定义代码段
;--------------------------------------------------------------------------
END START
5.16 在首地址为DATA的字数组中存放着100H个16位补码数,试编写一个程序求出它们的平均值放在AX
寄存器中;并求出数组中有多少个数小于此平均值,将结果放在BX寄存器中。 答:程序如下:
DSEG SEGMENT DATA DW 100H DUP (?) DSEG ENDS
;-------------------------------------------------------------------------- CSEG SEGMENT MAIN PROC FAR
ASSUME CS: CSEG, DS: DSEG
START: PUSH DS ;设置返回DOS
SUB AX, AX PUSH AX MOV AX, DSEG MOV DS, AX ;给DS赋值
BEGIN: MOV CX, 100H ;循环计数器
MOV SI, 0 MOV BX, 0 ;和((DI),(BX))的初始值 MOV DI, 0
NEXT: MOV AX, DATA [SI]
CWD
ADD BX, AX ;求和 ADC DI, DX ;加上进位位 ADD SI, 2 LOOP NEXT MOV DX, DI ;将((DI),(BX))中的累加和放入((DX),(AX))中 MOV AX, BX MOV CX, 100H IDIV CX ;带符号数求平均值,放入(AX)中
MOV BX, 0 MOV SI, 0
30
BEGIN: