1.
CRLF macro
MOV DL,0DH
MOV AH,02H
INT 21H
MOV DL,0AH
MOV AH,02H
INT 21H
ENDM
DATAS SEGMENT
dat1 db 'ksbcasubcoubciasu*'
na db ?
nb db ?
n1 db ?
DATAS ENDS
。。。。。。
mov si,offset dat1
mov cx,20
LOP:
MOV AL,[SI]
CMP AL,'A'
JB NEXT
CMP AL,'Z'
JA NEXT
INC NA
JMP NEXT2
NEXT:
CMP AL,'a'
JB NEXT1
CMP AL,'z'
JA NEXT1
INC NB
JMP NEXT2
NEXT1:
CMP AL,'0'
JB NEXT2
CMP AL,'9'
JA NEXT2
INC N1
JMP NEXT2
NEXT2:
INC SI
LOOP LOP
MOV BL,NA
CALL DISPP
CRLF
MOV BL,NB
CALL DISPP
CRLF
MOV BL,N1
CALL DISPP
MOV AH,4CH
INT 21H
DISPP PROC
MOV DL,BL
MOV CL,04
ROL DL,CL
AND DL,0FH
ADD DL,30H
CMP DL,3AH
JB BBB
ADD DL,07H
BBB:
MOV AH,02H
INT 21H
MOV DL,BL
AND DL,0FH
ADD DL,30H
CMP DL,3AH
JB BBB1
ADD DL,07H
BBB1:
MOV AH,02H
INT 21H
RET
DISPP ENDP
。。。。。。
2.
DATAS SEGMENT
string db 'AUHvxiagAJBDiscuaAJISGADKTfHVa'
DATAS ENDS
。。。。。。
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
MOV AX,DATAS
MOV DS,AX
mov si,offset string
mov cl,30
lop:
mov al,[si]
cmp al,'A'
jb next
cmp al,'Z'
ja next
add al,20h
mov [si],al
next:
inc si
loop lop
MOV AH,4CH
INT 21H
。。。。。。
下面是使用masm for Windows集成实验环境编写的代码:
.model small
.stack 100h
.data
DATA1 DB "ABCDefgHi1234JKlmnoPqRS56789tuvWxYZ", 0
NA DB 20 dup(0)
NB DB 20 dup(0)
N1 DB 20 dup(0)
STRING DB 30 dup(0)
.code
main PROC
; 统计大写字母、小写字母和数字个数
mov bx, offset DATA1
mov cx, 20
mov si, offset NA
mov di, offset NB
mov bp, offset N1
call CountChar
; 打印统计结果
mov ah, 9
lea dx, NA
int 21h
lea dx, NB
int 21h
lea dx, N1
int 21h
; 将字符串中的大写字母转换为小写字母
mov bx, offset STRING
mov cx, 30
call ConvertUpperToLower
; 打印转换后的字符串
mov ah, 9
lea dx, STRING
int 21h
mov ah, 4ch
int 21h
main ENDP
; 统计字符个数
CountChar PROC
push bx
push cx
push dx
xor ax, ax
xor bx, bx
xor cx, cx
xor dx, dx
; 统计大写字母、小写字母和数字个数
CountLoop:
mov al, [bx]
cmp al, 0
je CountEnd
cmp al, 'A'
jb NextChar
cmp al, 'Z'
ja NextChar
inc cx ; 大写字母个数加1
jmp NextChar
NextChar:
cmp al, 'a'
jb NextChar2
cmp al, 'z'
ja NextChar2
inc dx ; 小写字母个数加1
jmp NextChar2
NextChar2:
cmp al, '0'
jb NextChar3
cmp al, '9'
ja NextChar3
inc bx ; 数字个数加1
jmp NextChar3
NextChar3:
inc bx ; 跳过其他字符
jmp CountLoop
CountEnd:
; 将结果转换为十六进制,并存储到NA、NB和N1中
call WordToHex
mov si, offset HexResult
mov di, offset NA
mov cx, 2
rep movsb
call WordToHex
mov si, offset HexResult
mov di, offset NB
mov cx, 2
rep movsb
call WordToHex
mov si, offset HexResult
mov di, offset N1
mov cx, 2
rep movsb
pop dx
pop cx
pop bx
ret
CountChar ENDP
; 将字符串中的大写字母转换为小写字母
ConvertUpperToLower PROC
push bx
push cx
push dx
; 将大写字母转换为小写字
ConvertLoop:
mov al, [bx]
cmp al, 0
je ConvertEnd
cmp al, 'A'
jb NextChar
cmp al, 'Z'
ja NextChar
add al, 32 ; 大写字母转换为小写字母
mov [bx], al
NextChar:
inc bx ; 处理下一个字符
jmp ConvertLoop
ConvertEnd:
pop dx
pop cx
pop bx
ret
ConvertUpperToLower ENDP
; 将16位无符号整数转换为4位十六进制字符串
WordToHex PROC
push ax
push bx
push cx
push dx
; 将十六进制字符表存储到HexTable中
mov bx, offset HexTable
mov cx, 16
HexLoop:
mov dl, cl
and dl, 0fh
cmp dl, 10
jb NotLetter
add dl, 7 ; 转换为大写字母
NotLetter:
mov [bx], dl
add bx, 1
loop HexLoop
; 将16位无符号整数转换为4位十六进制字符串
mov ax, bx ; 将bx的值复制到ax中
mov bx, offset HexResult
mov cx, 4
HexConvertLoop:
mov dx, 0
mov si, 1000h
HexDivLoop:
cmp ax, si
jb HexDivEnd
sub ax, si
add dx, 1
jmp HexDivLoop
HexDivEnd:
mov al, dl
mov dl, [HexTable+ax]
mov [bx], dl
add bx, 1
dec cx
cmp cx, 0
jne HexConvertLoop
pop dx
pop cx
pop bx
pop ax
ret
WordToHex ENDP
; 数据区
HexTable DB '0123456789ABCDEF'
HexResult DB 4 dup(0)
END main
在这个程序中,使用了三个过程:
由于题目要求不使用int 21h功能号1和2,所以在打印字符串时使用了int 21h功能号9。此外,为了将十六进制结果存储到NA、NB和N1中,还需要使用WordToHex过程将结果转换为十六进制字符串。
引用chatGPT作答,
1.以下是汇编语言程序,可以实现您的要求:
ORG 0
MOV AX, DATA
MOV DS, AX ; 将DS寄存器设置为DATA段的基地址
MOV SI, OFFSET DATA1 ; 将SI寄存器设置为DATA1的偏移地址
MOV CX, 20 ; 循环20次,处理20个字符串
MOV AX, 0 ; 初始化NA、NB、N1为0
MOV BX, 0
MOV DX, 0
LOOP_START:
MOV AH, [SI] ; 读取当前字符串的第一个字符
CMP AH, 0 ; 判断字符串是否结束
JE LOOP_END ; 如果结束,跳出循环
CMP AH, 'A' ; 判断字符是否为大写字母
JB NOT_UPPER_CASE
CMP AH, 'Z'
JA NOT_UPPER_CASE
INC AX ; 如果是大写字母,NA加1
JMP CONTINUE_LOOP
NOT_UPPER_CASE:
CMP AH, 'a' ; 判断字符是否为小写字母
JB NOT_LOWER_CASE
CMP AH, 'z'
JA NOT_LOWER_CASE
INC BX ; 如果是小写字母,NB加1
JMP CONTINUE_LOOP
NOT_LOWER_CASE:
CMP AH, '0' ; 判断字符是否为数字
JB CONTINUE_LOOP
CMP AH, '9'
JA CONTINUE_LOOP
INC DX ; 如果是数字,N1加1
CONTINUE_LOOP:
INC SI ; 指向下一个字符
JMP LOOP_START
LOOP_END:
; 将NA、NB、N1转换成16进制并输出到屏幕上
MOV AH, 2 ; 选择2号功能,用于显示字符
MOV DL, 'A' ; 输出'A'
ADD AX, 55H ; 将NA转换成16进制,并加上偏移量
CMP AX, 7FH ; 判断是否为大写字母
JBE PRINT_HEX_DIGIT
ADD DL, 20H ; 如果不是大写字母,输出数字
JMP PRINT_BYTE
PRINT_HEX_DIGIT:
MOV DL, AH ; 将高4位转换成16进制并输出
AND DL, 0FH
CMP DL, 0AH
JBE PRINT_BYTE
ADD DL, 7 ; 输出A~F
PRINT_BYTE:
INT 21H ; 调用DOS系统中断,显示字符
MOV DL, ' '
INT 21H ; 输出一个空格
MOV AH, 2 ; 继续输出16进制数字
MOV DL, 'A' ; 输出'A'
ADD BX, 55H ; 将NB转换成16进制,并加上偏移量
CMP BX, 7FH ; 判断是否为大写字母
JBE PRINT_HEX_DIGIT
ADD DL, 20H ; 如果不是大写字母,输出数字
JMP PRINT_BYTE
PRINT_HEX_DIGIT:
MOV DL, BH ; 将高4位转换成16进制并输出
AND DL, 0FH
CMP DL, 0AH
JBE PRINT_BYTE
ADD DL, 7 ; 输出A~F
PRINT_BYTE:
INT 21H ; 调用DOS系统中断,显示字符
MOV DL, ' ' ; 输出一个空格
INT 21H
MOV AH, 4CH ; 选择4CH功能,程序结束
INT 21H
; 数据段定义
DATA SEGMENT
NA DB 0
NB DB 0
N1 DB 0
DATA1 DB 'AbCdEfGhIjKlMnOpQrStUvWxYz0123456789', '$'
DATA ENDS
END ; 程序结束符号
上述程序中,通过循环处理20个字符串,分别统计每个字符串中大写字母、小写字母和数字的个数,最后将结果转换成16进制并输出到屏幕上。程序中使用了以下指令和概念:
MOV
指令:用于将数据从一个寄存器或内存单元传送到另一个寄存器或内存单元中。CMP
指令:用于比较两个操作数的大小,并根据比较结果设置标志位。INC
指令:用于将指定操作数加1。JB
、JA
、JBE
、JAE
等条件跳转指令:根据标志位的值来决定是否跳转到指定的目标地址。OFFSET
运算符:用于获取某个变量在数据段中的偏移地址。2.以下是使用MASM for Windows集成实验环境完成题目要求的汇编程序:
.MODEL SMALL
.STACK 100H
.DATA
STRING DB 'AaBbCcDdEeFfGgHhIiJjKkLlMmNn', '$'
LENGTH DB 30
.CODE
MAIN PROC
MOV AX, @DATA ; 初始化数据段寄存器
MOV DS, AX
; 循环处理字符串中的每个字符
MOV CX, LENGTH ; 循环计数器,初始值为字符串长度
MOV SI, 0 ; SI寄存器指向字符串的第一个字符
LOOP_BEGIN:
MOV AL, [SI] ; 读取一个字符
CMP AL, 'A' ; 判断是否为大写字母
JB SKIP ; 如果不是大写字母,跳过转换
CMP AL, 'Z'
JA SKIP
ADD AL, 20H ; 转换成小写字母
SKIP:
MOV [SI], AL ; 将处理后的字符存回字符串
INC SI ; 指向下一个字符
LOOP LOOP_BEGIN ; 继续处理下一个字符
; 输出转换后的字符串
MOV AH, 9 ; 选择9号功能,用于输出字符串
MOV DX, OFFSET STRING ; 字符串存储的偏移地址
INT 21H ; 调用DOS系统中断
; 程序结束
MOV AH, 4CH
INT 21H
MAIN ENDP
END MAIN
在程序中,我们使用了以下指令和概念:
MOV 指令:用于将数据从一个寄存器或内存单元传送到另一个寄存器或内存单元中。
CMP 指令:用于比较两个操作数的大小,并根据比较结果设置标志位。
ADD 指令:用于将指定操作数加上一个值。
INC 指令:用于将指定操作数加1。
LOOP 指令:用于根据循环计数器的值来判断是否继续执行循环。
INT 21H:DOS系统中断,可以用于输出字符串、读取键盘输入等操作。
在处理字符串时,我们使用循环遍历每个字符,并通过比较ASCII码值来判断是否为大写字母。如果是大写字母,将其转换成小写字母(通过将其ASCII码值加上20H),并将处理后的字符存回字符串。最后,使用DOS系统中断将转换后的字符串输出到屏幕上。
MOV SI, OFFSET DATA1 ; 指向数据块开头
MOV DI, SI ; 复制指针到结果的目标位置
; 初始化计数器为零
MOV NA, 0 ; 大写字母个数
MOV NB, 0 ; 小写字母个数
MOV N1, 0 ; 数字 0~9 的个数
; 循环遍历所有 20 个字符串
FOR_LOOP:
MOV CX, 20 ; 每个字符串有 20 个字符
LOOP_START:
LODSB ; 从 AL 中加载下一个字符
CMP AL, 'A' ; 检查是否为大写字母
JB CHECK_LOWER ; 如果不是则跳过
CMP AL, 'Z'
JA CHECK_LOWER ; 如果不是则跳过
INC NA ; 增加大写字母计数
JMP NEXT_CHAR
CHECK_LOWER:
CMP AL, 'a' ; 检查是否为小写字母
JB CHECK_DIGIT ; 如果不是则跳过
CMP AL, 'z'
JA CHECK_DIGIT ; 如果不是则跳过
INC NB ; 增加小写字母计数
JMP NEXT_CHAR
CHECK_DIGIT:
CMP AL, '0' ; 检查是否为数字
JB NEXT_CHAR ; 如果不是则跳过
CMP AL, '9'
JA NEXT_CHAR ; 如果不是则跳过
INC N1 ; 增加数字计数
NEXT_CHAR:
LOOP LOOP_START
ADD DI, 5 ; 跳到下一个计数器组
CMP DI, OFFSET NA+15 ; 检查是否到达计数器的末尾
JB FOR_LOOP ; 如果没有则继续循环
MOV SI, OFFSET STRING ; 指向字符串开头
MOV CX, 30 ; 字符串长度
FOR_LOOP:
LODSB ; 从 AL 中加载下一个字符
CMP AL, 'A' ; 检查是否为大写字母
JB SKIP_CONVERT ; 如果不是则跳过
CMP AL, 'Z'
JA SKIP_CONVERT ; 如果不是则跳过
ADD AL, 32 ; 转换为小写字母
SKIP_CONVERT:
STOSB ; 将转换或未转换的字符存回
LOOP FOR_LOOP
; 首先,打印提示用户输入字符串的消息
MOV DX, OFFSET PROMPT ; PROMPT 是以 null 结尾的字符串
MOV AH, 09h ; 用于打印字符串的服务
INT 21h
; 其次,从用户获取输入
MOV DX, OFFSET BUFFER ; BUFFER 是一个 128 字节的字符数组
MOV AH, 0Ah ; 用于读取带缓存区的字符串的服务
INT 21h
; 第三,将字符串输出到屏幕上
MOV DX, OFFSET BUFFER+2 ; 缓冲区的前两个字节表示字符串的长度
ADD DX, 2 ; 跳过长度字节
MOV AH, 09h ; 用于打印字符串的服务
INT 21h