assume cs:codesg
datasg segment
db "Beginner's All-purpose Symbolic Instruction Code.",0
datasg ends
stack segment
dw 16 dup (0)
stack ends
codesg segment
begin:mov ax,datasg
mov ds,ax
mov si,0 ;ds:si指向字符串首地址
call letterc ;调用小写字母变大写字母子程序
mov ax,stack
mov ss,ax
mov sp,32 ;设置栈段
mov dh,8 ;(dh)=行号(取值范围0~24)
mov dl,3 ;(dl)=列号(取值范围0~79)
mov cl,2 ;(cl)=颜色
call show_str ;调用显示子程序
mov ax,4c00h
int 21h
letterc:push ax
push cx
push si
k0:mov cl,[si]
mov ch,0
jcxz k3 ;字符串遇到0就结束
mov al,[si]
cmp al,61h
jb k1 ;低于61h则转移到k1
cmp al,7ah
ja k1 ;高于7ah则转移到k1
and al,11011111b
mov [si],al ;小写字母变大写字母
inc si
jmp short k0 ;访问k0处理下一个字符
k1:inc si
jmp short k0
k3:pop si
pop cx
pop ax
ret
show_str:push es
push dx
push cx
push bx
push ax
push si ;子程序中会使用的寄存器入栈
mov al,dh
mov ah,0ah
mul ah ;第N行的段地址偏移量(相对于第0行的基础段地址)
add ax,0b800h ;第N行的段地址存入ax
mov es,ax ;屏幕上行号的段地址存入es
mov ah,cl ;将颜色存入ah,因后面要用到cx
mov bh,0
mov bl,dl
add bl,bl
sub bx,2 ;将列号存入bx,因内存寻址变量只能选bx、bp、si、di四个
s0:mov cl,[si]
mov ch,0
jcxz ok ;字符串中出现0,字符处理完毕,跳到ok处
mov al,[si] ;将字符存入al
mov es:[bx],ax ;将带属性的字符在屏幕上显示
inc si ;字符串列变量加1,指向下个字符
add bx,2 ;屏幕列变量指向下一个字节
jmp short s0 ;ip跳到s0处执行指令
ok:pop si
pop ax
pop bx
pop cx
pop dx
pop es ;子程序中会使用的寄存器出栈
ret ;ip跳到call指令的下一条指令执行
codesg ends
end begin