汇编语言小程序
1.编写统计AX中1、0个数的源程序。1的个数存入CH,0的个数存入CL。
CODE SEGMENT
ASSUME CS:CODE
START: MOV CX, 0
MOV DX,17
AA1: SUB DX, 1
JZ AA3
SHL AX, 1
JNC AA2
INC CH
JMP AA1
AA2: INC CL
JMP AA1
AA3: MOV AH,4CH
INT 21H
CODE ENDS
END START
2.编写比较两个字符串STRING1和STRING2所含字符是否完全相同的源程序,若相同则显示“MATCH”,若不相同则显示“NO MATCH”。
程序:
DATA SEGMENT
R1 DB ‘MATCH’,0AH,0DH
R2 DB ‘NO MATCH’,0AH,0DH
STRING1 DB ‘XXXXX’
N1 EQU $-STRING1
STRING2 DB ‘YYYYY’
N2 EQU $-STRING2
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
MOV AX,N1
CMP AX,N2
JNZ AA1
ADD AX,1
LEA SI,STRING1
LEA DI,STRING2
AA2: MOV BL,[SI]
MOV BH,[DI]
INC SI
INC DI
SUB AX,1
JZ AA3
CMP BL,BH
JZ AA2
JMP AA1
AA3: LEA BX,R1
MOV CX,7
AA4: MOV DL,[BX]
INC BX
MOV AH,2
INT 21H
LOOP AA4
JMP E
AA1: LEA BX,R2
MOV CX,10
AA5: MOV DL,[BX]
INC BX
MOV AH,2
INT 21H
LOOP AA5
E: MOV AH,4CH
INT 21H
CODE ENDS
END START
3.从键盘读入一个四位的十六进制数,CRT显示等值的二进制数.
由于每个十六进制数位对应4个二进制,所以每读入一个十六进制位后,即可将其对应的4个二进制位依次输出。由于数字‘0’~ ‘9’的ASCⅡ码为30H~39H,字母‘a’~‘f’与 ‘A’~‘F’的ASCⅡ码为61H~66H 与41H~46H ,因此,如果输入的字母为数字‘0’~‘9’,则其低4位即为对应的二进制位;如果输入的字符为字母‘a’~‘f’或‘A’~‘F’,则需要减7,然后通过移位将低4位依次输出。
汇编程序如下:
DATA SEGMENT
MSG1 DB ‘Hex:’, ‘$’
MSG2 DB 0DH, 0AH, ‘Binary:’, ‘$’
COUNT EQU 4
BUF DB 4 DUP(?)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX, DATA
MOV DS, AX
LEA DX, MSG1
MOV AH, 9
INT 21H
MOV CX, COUNT
MOV SI, 0
INPUT: ;通过四次循环从键盘读入四位十六进制数
MOV AH, 1
INT 21H
MOV BUF[SI], AL
DEC CX
INC SI
CMP CX, 0
JNZ INPUT
NEXT3: LEA DX, MSG2
MOV AH, 9
INT 21H
MOV CX, COUNT
MOV SI, 0
NEXT2: MOV BL, BUF[SI]
CMP BL , '9'
JBE OK ; 读入的字符<=9 转向 OK:
SUB BL, 7 ;读入字符>= 9 减7
OK: PUSH CX
MOV CL ,4
SHL BL, CL ; 逻辑左移4位,低4位à高4位
MOV CX, 4 ; 4次循环将当前处理字符的4位二进制输出
NEXT1: MOV DL, ‘0’
SHL BL, 1
JNC SKIP
INC DL
SKIP: MOV AH, 2
INT 21H
LOOP NEXT1
POP CX ;
INC SI
LOOP NEXT2 ; 4次循环将4位十六进制数,每位转换为对应的4位二进制
EXIT: MOV AH, 4CH
INT 21H
CODE ENDS
END START
4.设从STRING开始存放一个以$为结束标志的字符串,试编写把字符串中的字符进行分类的源程序,数字字符送入NUM开始的内存中,大写字母送入BCHAR开始的内存区中,小写字母存入LCHAR开始的内存中,其他字符存入OTHER开始的内存区中。
DATA SEGMENT
STRING DB ‘abc123ABC’,’$’
N EQU $-STRING
NUM DB N DUP(?)
BCHAR DB N DUP(?)
LCHAR DB N DUP(?)
OTHER DB N DUP(?)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
LEA BX,STRING
DEC BX
LEA SP,BCHAR
LEA CX,LCHAR
LEA DX,OTHER
LEA SI,NUM
AA1:INC BX
MOV AL,[BX] //判断是否为$,是否结束
CMP AL,’$’
JZ AA5
CMP AL,30H //判定数字字符
JC AA4
CMP AL,39H
JA AA2
MOV [SI],AL
INC SI
JMP AA1
AA2:CMP AL,41H //判定大写字母
JC AA4
CMP AL,5AH
JA AA3
MOV DI,SP
MOV [DI],AL
INC SP
JMP AA1
AA3:CMP AL,61H //判定小写字母
JC AA4
CMP AL,7AH
JA AA4
MOV DI,CX
MOV [DI],AL
INC CX
JMP AA1
AA4:MOV DI,DX //判定其他
MOV [DI],AL
INC DX
JMP AA1
AA5:MOV AH,4CH // 返回DOS 结束
INT 21H
CODE ENDS
END START
5.试编写找出首地址为BUF数据块中的最小偶数(该数据块中有100个带符号字节数),并以十六进制的形式显示在CRT上的源程序。
答:
DATA SEGMENT
BUF DB 100 DUP(?) ;要比较的数
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
LEA BX,BUF ;BUF首地址送BX
MOV CL,101 ;循环控制
MOV DL,126 ;DL存放最小偶数
MOV AH,0 ;标志是不是有偶数
LOOP1:
DEC CL ;循环计数减1
JZ TOEND ;ZF标志0则跳转
MOV AL,[BX] ;BX内存内容送AL
INC BX ;BX指向下一内存单元
SHR AL,1 ;AL逻辑右移一位
JC LOOP1 ;是基数则接着循环
SHL AL,1 ;是偶数,因为上面右移了 左移得到原数值
MOV AH,1 ;能进行这一步 则说明数值中有偶数
CMP AL,DL ;与CH比较大小
JGE LOOP1 ;AL大DL小 则循环
MOV DL,AL ;保证DL存放最小偶数
JMP LOOP1 ;CL不为0 继续循环
TOEND:
CMP AH,1
JC L ;有借位则说明数值中无偶数直接返DOS
MOV BL,DL
SHR DL,1
SHR DL,1
SHR DL,1
SHR DL,1
AND DL,0FH
CMP DL,10
JB L4
ADD DL,7
L4:
ADD DL,30H ;显示高四位对应的十六进制的ascii码
MOV AH,2
INT 21H
MOV DL,BL
AND DL,0FH
CMP DL,10
JB L6
ADD DL,7
L6:
ADD DL,30H ;显示低四位对应的十六进制的ascii码
MOV AH,2
INT 21H
MOV DL,'H' ;显示H
MOV AH,2
INT 21H
L:
MOV AH,4CH ;返回DOS
INT 21H
CODE ENDS
END START
- 已知数据块BUFA中存放15个互不相等的字节数据,BUFB中存放20个互不相等的字节数据,试编写将既在BUFA中出现,又在BUFB中出现的数据存放到BUFC开始的缓冲区中的源程序。
答:
DATA SEGMENT
BUFA DB 41H,42H,43H,44H,45H,46H,47H,48H,49H,4AH,4BH,4CH,4DH,4EH,4FH
BUFB DB 31H,32H,33H,41H,42H,43H,44H,45H,46H,47H,48H,49H,4AH,4BH,4CH
DB 50H,51H,52H,53H,54H
BUFC DB 15 DUP (0)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
LEA SI,BUFA
LEA BX,BUFC
MOV CX,15 ;外层循环计数
AA1: MOV AH,20 ;内层循环20次
MOV AL,[SI]
LEA DI,BUFB
AA2: CMP AL,[DI] :比较BUFA , BUFB内容
JNZ AA3 ;内容不同,跳至AA3
MOV [BX],AL ;内容相同,将其存入BUFC单元
INC BX
JMP AA4 ;找到相同内容,结束本次内层循环
AA3: INC DI
DEC AH ;内层循环计数减一
JNZ AA2 ;内层循环结束
AA4: INC SI
LOOP AA1 ;外层循环结束
MOV CX,15 ;此行以下将BUFC中的内容输出
LEA BX,BUFC
BB1: MOV DL,[BX]
INC BX
MOV AH,2
INT 21H
LOOP BB1
MOV AH,4CH
INT 21H
CODE ENDS
END START
7.试编写由键盘输入一个以回车作为结束的字符串,将其按ASCII码由大到小的顺序输入到CRT上的源程序。
答:
DATA SEGMENT;数据段
BUF DB 200 DUP(?)
DATA ENDS
CODE SEGMENT;代码段
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
MOV DI,0;记录输入的字符串个数
MOV BX,OFFSET BUF
AA1: MOV AH,1;键盘输入字符
INT 21H
CMP DI,201;是否超出缓冲区
JNC AA6 ;超过缓冲区大小
CMP AL,0DH;是否为回车,回车表输入结束
JZ AA6;是回车
MOV [BX],AL;将字符存入缓冲区
INC BX
INC DI
JMP AA1
AA6: MOV DX,DI
CMP DI,0;没有字符则无输出
JZ AA7
CMP DI,1;有一个字符则直接输出
JZ AA8
DEC DX;外循环计数初值,即遍数,数据个数减1
AA2: MOV BX,OFFSET BUF
MOV CX,DI
DEC CX;内循环计数初值,即比较次数,数据个数减1
AA3: MOV AL,[BX]
CMP AL,[BX+1];比较
JNC AA4;前大后小转
XCHG AL,[BX+1];前小后大交换
MOV [BX],AL
AA4: INC BX
LOOP AA3
DEC DX
JNZ AA2
AA8: MOV BX,OFFSET BUF;输出字符
MOV CX,DI;循环计数初值
AA5: MOV DL,[BX]
MOV AH,2
INT 21H
INC BX
LOOP AA5
AA7: MOV AH,4CH
INT 21H
CODE ENDS
END START
- 设从BUFFER开始存放若干个以$为结束标志的带符号字节数据,试编写将其中的正数按由大到小的顺序存入PLUS开始的缓冲区中的源程序。
答:
方法一
思路:将正数先存到目标地址,然后再排序。
DATA SEGMENT
BUFFER DB 1,2,3,4,5,6,7,-8,9,2,-1,-2,-3,-4,-5,-6,-7,-8,-9,1,’$’
PLUS DB (?)
DATA ENDS
CODE SEGMENT
ASSUME CS: CODE,DS: DATA
START: MOV AX,DATA
MOV DS,AX
MOV DI,-1 ;初始化外循环计数器
LEA BX,BUFFER
LEA SI,PLUS
L1: MOV AL,[BX]
XOR AL,'$' ;判断当前字符是否为'$'
JNZ L2 ;不是'$'转移
JMP L4
L2: MOV AL,[BX] ;判断当前字符是否为正数
ROL AL,1
JNC L3 ;是正数转移
INC BX
JMP L1
L3: ROR AL,1 ;恢复数据
MOV [SI],AL ;将数据存入目标地址
INC DI
INC SI
INC BX
JMP L1
L4: CMP DI,0
JG L5 ;正数个数>=2则开始排序
MOV AH,4CH
INT 21H ;正数个数为0或1均跳出
L5: LEA SI,PLUS ;以下为使用冒泡排序的方法对数据排序
MOV CX,DI
L6: MOV AL,[SI]
CMP AL,[SI+1]
JNC L7
XCHG AL,[SI+1]
MOV [SI],AL
L7: INC SI
LOOP L6
DEC DI
JNZ L5
MOV AH,4CH
INT 21H
CODE ENDS
END START
方法二
思路:在数据存放的原地址将数据进行由小到大的冒泡排序,则每次那循环可得到本次排序中的最大数,将其存入目的地址,直到得到一个非正的数后跳出。
DATA SEGMENT
BUFFER DB 1,2,3,4,5,6,7,-8,9,2,-1,-2,-3,-4,-5,-6,-7,-8,-9,1,’$’
PLUS DB (?)
DATA ENDS
CODE SEGMENT
ASSUME CS: CODE,DS: DATA
START: MOV AX,DATA
MOV DS,AX
MOV DI,-1 ;初始化外循环计数器
LEA SI,PLUS
LEA BX,BUFFER
L1: MOV AL,[BX]
XOR AL,'$' ;检查当前字符是否为'$'
JNZ L2
JMP L3
L2: INC DI
INC BX
JMP L1
L3: LEA BX,BUFFER ;开始排序
MOV CX,DI
L4: MOV AL,[BX]
CMP AL,[BX+1]
JLE L5 ;前小后大转移
XCHG AL,[BX+1]
MOV [BX],AL
L5: INC BX
LOOP L4
MOV AL,[BX] ;得到本次循环的最大数
ROL AL,1
JNC AA4 ;检验是否为正数,是则转移
MOV AH,4CH
INT 21H
L6: MOV DL,[BX]
MOV [SI],DL ;保存数据
INC SI
DEC DI
JNZ L3 ;进入下一次循环
MOV AH,4CH
INT 21H
CODE ENDS
END START
- 试编写一源程序,要求将一个包含有20个数据的数组M分成两个数组:正数数组P和负数组N,并分别把这两个数组中数据的个数在CRT上显示出来。
答:
DATA SEGMENT
ORG 100H
M DB 12,23,58,15,36,55,44,89,45,-23,-56,-47,-21,-65,32,69,82,58,29,-14 ;待处理数组
P DB 20 DUP(?) ;正数数组P
N DB 20 DUP(?) ;负数数组N
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START: MOV AX,DATA
MOV DS,AX
LEA SI,P ;P的首址送SI
LEA DI,N ;N的首址送DI
LEA BX,M ;M的首址送BX
XOR AX,AX ;AX清0
XOR DX,DX ;DX清0,DL/DH分别用于正/负数计数
MOV CX,20 ;分别处理M的20个数据
L1: MOV AL,[BX] ;取一个数组元素
TEST AL,80H ;AL,80H按位与
JZ L2 ;结果为0,则AL为正,转L2
MOV [DI],AL ;AL为负,送负数数组N
INC BX ;BX+1,准备取M的下一个元素
INC DI ;负数数组N写位置后移一位
INC DH ;负数计数DH+1
JMP L3 ;本次处理结束
L2: MOV [SI],AL ;AL为正,送正数数组P
INC BX
INC SI ;正数数组P写位置后移一位
INC DL ;正数计数DL+1
L3: LOOP L1 ;跳转进入下一次循环
MOV CX,2 ;二次输出循环,分别显示正负数的个数
L5: MOV BL,DL ;保存DL,实质是暂时保存DL的低4位
SHR DL,1
SHR DL,1
SHR DL,1
SHR DL,1 ;逻辑右移4位,即取高4位
CMP DL,10
JB L4 ;DL<10
ADD DL,7 ;DL>=10时,DL+7,9的ASCII码为39H,A的ASCII码为41H,相差8
L4: ADD DL,30H
MOV AH,2 ;输出DL,正/负数个数的高位
INT 21H
MOV DL,BL ;BL送DL,准备显示正/负数个数的低位
AND DL,0FH ;DL高4位置0,因为DL的高4位已显示
CMP DL,10
JB L6
ADD DL,7
L6: ADD DL,30H
MOV AH,2
INT 21H
MOV DL,0AH ;换行
MOV AH,2
INT 21H
MOV DL,0DH ;回车
MOV AH,2
INT 21H
MOV DL,DH ;DH送DL,准备显示负数的个数
LOOP L5
MOV AH,4CH ;返回DOS
INT 21H
CODE ENDS
END START
10.试编写一源程序,要求能从键盘接收一个个位数N,然后响铃N次(响铃的ASCII码为07)。
答:
CODE SEGMENT
ASSUME CS:CODE
START: MOV AH,1 ;输入一个个位数N
INT 21H
CMP AL,30H
JC START ;小于0,要求重新输入
CMP AL,3AH
JNC START ;大于9,要求重新输入
AND AL,0FH
XOR CX,CX ;CX清0
MOV CL,AL ;循环响铃N次
MOV DL,07H ;响铃的ASCII码为07
AA1:MOV AH,2
INT 21H
LOOP AA1 ;循环响铃
MOV AH,4CH
INT 21H
CODE ENDS
END START
11.在STRING到STRING+99单元中存放着一个字符串,试编制一程序测试该字符串中是否有数字。如有,则把CL置0FFH,否则将CL置0。
答:
DATAS SEGMENT
STRING DB 'XYZIL12LWR';' '内可以是任意字符串
N EQU $-STRING;字符串长度
DATAS ENDS
;
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS
START:
MOV AX,DATAS
MOV DS,AX
MOV CX,N
LEA BX,STRING
AA1:MOV AL,[BX]
CMP AL,30H;字符ASCII码小于30H,转移
JB AA2
CMP AL,39H;字符ASCII码大于39H,转移
JA AA2
JMP AA3;数字,符合条件
AA2:INC BX
LOOP AA1
MOV CL,0
JMP AA4
AA3:MOV CL,0FFH
AA4:MOV AH,4CH
INT 21H
CODES ENDS
END START
12.试编制一源程序,把DX中的十六进制数转换为ASCII码,并将对应的ASCII码依次存放到MEM数组中的4个字符中.例如,当DX=2A49H时,程序执行完后,MEM中的4个字节内容为39H、34H、41H、和32H。
答:
DATA SEGMENT
SOURCE DW 2A49H
MEM DB 4 DUP(?)
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
;
START:
MOV AX,DATA
MOV DS,AX
;
MOV DX,SOURCE
LEA BX,MEM
;
;set the loop
MOV CX,4
;the loop body
LB: MOV AX,DX
AND AX,000FH
CMP AL,10
JC AD
;
ADD AL,7
;
AD: ADD AL,30H
MOV [BX],AL
INC BX
;
SHR DX,1
SHR DX,1
SHR DX,1
SHR DX,1
LOOP LB
;the loop end, return to dos
MOV AH,4CH
INT 21H
CODE ENDS
END START
13.下面程序段是实现从键盘输入10个1位10进制数后累加。最后累加和以非压缩BCD码形式存放在AH(高位)和AL(低位)中。答:
XOR DX,DX
MOV CX 10
LOP1: MOV AH,01H;键盘字符输入
INT 21H
MOV AH,DH
ADD AL,DL
AAA
MOV DX,AX
LOOP LOP1