程序思路
我们有一个现成的指令jcxz 可以判断cx寄存器中是否0,可以将data段的数据一个一个放到cx中,紧接着调用jcxz指令,如果cx为0 跳出子程序,如果不为0进行大写转化!
这里为了方便展示,将转换前后的字符串都放到屏幕中进行展示,代码中有一定的注释。
程序代码
assume cs:code,ss:stack
data segment
db 'laymond',0
data ends
stack segment
db 128 dup(0)
stack ends
code segment
main:
mov ax,stack
mov ss,ax
mov sp,128
mov ax,data
mov ds,ax
call init_reg
call clear_screen
call show_1word
mov ax,4c00H
int 21H
;------------------------------
show_1word:
mov si,0 ;si 为源字符串的位置
mov di,160*10+40*2 ;显示在第10行中间位置
call show_string
call to_upper ;si to_upper参数,要转换字符串的起始位置
mov di,160*11+40*2 ;di show_string参数,显示的地址,将其显示到下一行
call show_string
ret
;------------------------------
;子程序功能 将字符串转换为大写
;参数寄存器 si 转换字符串的起始地址
to_upper:
push cx
push si
toUpper:
mov cx,0
mov cl,ds:[si]
jcxz upperRet
and byte ptr ds:[si],11011111B
inc si
jmp toUpper
upperRet:
pop si
pop cx
ret
;------------------------------
;子程序功能 显示指定位置的字符串
;参数寄存器 si 源字符串的位置
;参数寄存器 di 字符串显示的位置
show_string:
;将使用到的寄存器变量通过栈保存,使用完毕将可通过弹栈数据还原
push ax
push cx
push es
push ds
push di
push si
mov ax,0B800H
mov es,ax
showLetter:
mov cx,0
mov cl,ds:[si]
jcxz showRet
mov al,ds:[si] ;内存单元之间不能直接进行赋值!必须借助寄存器
mov es:[di],al
inc si
add di,2
jmp showLetter
showRet:
pop si
pop di
pop ds
pop es
pop cx
pop ax
ret
;------------------------------
init_reg:
mov bx,0B800H ;显存起始位置
mov es,bx
ret
;-------------------------------
clear_screen:
mov bx,0
mov dx,0700H ;黑底空字符,偶数字节为显示字符,奇数字节放显示方式
mov cx,2000 ;每页25行,每行可显示80个字符,2000个字符,循环2000次
clearScreen:
mov es:[bx],dx
add bx,2
loop clearScreen
ret
code ends
end main
运行结果
题目扩展
如果是多行字符串转换呢?还是一样的,由于我们上面写代码是按功能写的子程序,那么进行扩展就非常方便了!
多行字符串代码
assume cs:code,ss:stack
data segment
db 'aaaa',0
db 'bbbb',0
db 'cccc',0
db 'dddd',0
data ends
stack segment
db 128 dup(0)
stack ends
code segment
main:
mov ax,stack
mov ss,ax
mov sp,128
mov ax,data
mov ds,ax
call init_reg
call clear_screen
call show_4word
mov ax,4c00H
int 21H
;------------------------------
show_4word:
mov di,160*10+40*2 ;dos显存 每页25行 80字符/行,每个字符2个字节,从第10行开始显示
mov si,0
mov cx,4
show_word:
call show_string
call to_upper
call show_UpperString
add di,160 ;显示到下一行,每行160字节
add si,5 ;si 为to_upper参数 下一个字符串的起始位置
loop show_word
ret
show_UpperString:
push di
add di,20 ;di 为show_string参数 将大写后的字符串显示到 源字符串的后面
call show_string
pop di
ret
;------------------------------
;子程序功能 将字符串转换为大写
;参数寄存器 si 转换字符串的起始地址
to_upper:
push cx
push si
toUpper:
mov cx,0
mov cl,ds:[si]
jcxz upperRet
and byte ptr ds:[si],11011111B
inc si
jmp toUpper
upperRet:
pop si
pop cx
ret
;------------------------------
;子程序功能 显示指定位置的字符串
;参数寄存器 si 源字符串的位置
;参数寄存器 di 字符串显示的位置
show_string:
;将使用到的寄存器变量通过栈保存,使用完毕将可通过弹栈数据还原
push ax
push cx
push es
push ds
push di
push si
mov ax,0B800H
mov es,ax
showLetter:
mov cx,0
mov cl,ds:[si]
jcxz showRet
mov al,ds:[si] ;内存单元之间不能直接进行赋值!必须借助寄存器
mov es:[di],al
inc si
add di,2
jmp showLetter
showRet:
pop si
pop di
pop ds
pop es
pop cx
pop ax
ret
;------------------------------
init_reg:
mov bx,0B800H ;显存起始位置
mov es,bx
ret
;-------------------------------
clear_screen:
mov bx,0
mov dx,0700H ;黑底空字符,偶数字节为显示字符,奇数字节放显示方式
mov cx,2000 ;每页25行,每行可显示80个字符,2000个字符,循环2000次
clearScreen:
mov es:[bx],dx
add bx,2
loop clearScreen
ret
code ends
end main