马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
assume cs:code,ds:data
data segment
db 10 dup(0)
data ends
code segment
start:
mov ax,12666 ;需要处理的字符
mov bx,data ;ds:si指向字符串的首地址
mov ds,bx
mov si,0
call dtoc ;dtoc子程序实现将word型整数转化为字符串并存储
mov dh,8 ;初始化打印(显示)的位置
mov dl,3
mov cl,0cah
call show_str ;开始打印字符串
mov ax,4c00h
int 21h
dtoc: ;数值显示的子程序定义
push dx
push cx
push ax
push si
push bx
mov bx,0 ;bx在子程序中用来存放位数,用栈来临时存放修改后的字符
s1: mov cx,10d ;d表示10进制(除数)
mov dx,0
div cx ;除以10
mov cx,ax ;得到的商赋值给cx
jcxz s2 ;当商为0的时候跳到s2(cx用来判断)已经到了个位(余数是个位)
add dx,30h ;将余数加上20h得到相应的ASCLL码
push dx ;将数据存放入栈
inc bx ;bx记录栈存放了多少位数
jmp short s1
s2: add dx,30h ;当商为0的时候,余数为个位
push dx
inc bx ;再进行一次栈操作(补充当“商为0而余数不为0时的情况”)
mov cx,bx ;总共有bx位进栈了,所以循环次数为bx
mov si,0
s3: pop ax ;s3实现将栈中的数据一次出栈放到指定内存中
mov [si],al
inc si
loop s3
okay: pop bx
pop si
pop ax
pop cx
pop dx
ret ;数值显示的子程序定义结束
show_str:
push cx
push si
mov al,0a0h ;每行有多少个字节(160)
dec dh ;行号从下标0开始,所以减1
mul dh ;相当于从第(n-1)* 0a0h个byte单元开始
;乘法之后默认放在ax中
mov bx,ax ;定位好的位置偏移地址存放在bx里(行)
mov al,2 ;每个字符占两个字节
mul dl ;定位列,结果ax存放的是定位好的列的位置
sub ax,2 ;列号在显存中下标从0开始,偶字节存放字符,所以减2
add bx,ax ;此时bx中存放的是行与列号的偏移地址(行的偏移地址加上列的偏移地址)
mov ax,0b800h ;显存开始的地址
mov es,ax ;es中存放的是显存的第0页(共0~7页)的起始的段地址
mov di,0 ;di指向显存的偏移地址,确定指向下一个要处理的字符的位置
mov al,cl ;cl是存放颜色的参数,这时候al存放颜色了
;因为下边cl要用来陇南市存放要处理的字符(判断跳转指令通过cx确定)
mov ch,0 ;下边cx存放的是每次准备处理的字符
s: mov cl,ds:[si] ;ds:[si]指向“Welcome 头 masm!”,0
jcxz ok ;当cl的值为0的时候,cx==0,则发生跳转,到0k处结束处理
mov es:[bx+di],cl ;偶地址存放字符
mov es:[bx+di+1],al ;奇地址存放字符的颜色属性
inc si ;指向下一个字符(源字符串)
add di,2 ;指向下一个字符(目的字符串)
jmp short s ;无条件跳转,jcxz是离开的关键跳
ok: pop si
pop cx
ret ;显示字符串的子程序【定义结束】
code ends
end start
感觉s2这个标记后面没必要,s1和s2进行的都是同一个操作,,为什么要分两个?应该可以合成一个循环中,不知道我的想法对不对??
|