您的位置:首页 > 其它

汇编学习笔记(8)子程序

2014-01-09 22:43 267 查看
说的多不如做的多,子程序的功能十分重要,这篇笔记用来记录书上练习题的代码,加强对子程序的应用。

在屏幕上指定位置显示字符串

在转移指令那一章有个联系是要求在屏幕中间显示不同颜色的字体,当时我写的代码是这样

assume cs:codesg,ds:data

data segment
db 'welcome to masm!'
data ends

codesg segment

start:  mov ax,data
mov ds,ax
mov bx,0
mov ax,0B800h
mov es,ax

;第10行中间显示绿色字体
mov si,10*160+32
mov cx,16
s:  mov al,ds:[bx]
mov es:[si+24],al
mov byte ptr es:[si+25],02h
inc bx
inc si
inc si
loop s

;第11行中间显示红底绿色字体
mov si,11*160+32
mov bx,0
mov cx,16
s1: mov al,ds:[bx]
mov es:[si+24],al
mov byte ptr es:[si+25],42h
inc bx
inc si
inc si
loop s1

;第12行中间显示白底蓝色字体
mov si,12*160+32
mov bx,0
mov cx,16
s2: mov al,ds:[bx]
mov es:[si+24],al
mov byte ptr es:[si+25],71h
inc bx
inc si
inc si
loop s2

mov ax,4c00h
int 21h

codesg ends
end start


assume cs:codesg,es:data,ss:stack
data segment
;年份
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1900','1991','1992'
db '1993','1994','1995'
;公司总收入
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
;雇员
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11542,14430,45257,17800
data ends

;栈空间
stack segment
db 16 dup(0)
stack ends

;临时内存空间,将字符串后面加0
temp segment
db 8 dup(0)
temp ends

codesg segment

start:  ;清除屏幕上的原有内容
mov ax,0b800h
mov es,ax
mov si,0
mov cx,25*80
x:  mov byte ptr es:[si],' '
mov byte ptr es:[si+1],0
inc si
inc si
loop x
;分配栈空间
mov ax,stack
mov ss,ax
mov sp,16
;指定数据入口
mov ax,data
mov es,ax
mov ax,temp
mov ds,ax
mov si,0
mov di,0
mov bx,0
mov dh,4
;循环21次,输出21年数据
mov cx,21

x1: push cx
;显示年份
mov ax,es:[di]
mov ds:[si],ax
mov ax,es:[di+2]
mov ds:[si+2],ax
mov byte ptr ds:[si+4],0
mov dl,10
mov cl,02h
call print

;显示公司收入
mov ax,es:[di+84]
push dx
mov dx,es:[di+84+2]
call dword_str
pop dx
mov dl,20h
call print

;显示雇员人数
mov ax,es:[bx+84+84]
call word_str
mov dl,40h
call print

;计算人均收入并显示
mov ax,es:[di+84]
push dx
mov dx,es:[di+84+2]
div word ptr es:[bx+84+84]
call word_str
pop dx
mov dl,60h
call print
add di,4
add bx,2
inc dh
pop cx
loop x1

mov ax,4c00h
int 21h

;显示ds:[si]开始的字符串
print:      push es
push ax
push dx
push bx
push si
push di
push cx

mov ax,0B800h
mov es,ax
mov al,160D
mul dh
mov bl,dl
mov bh,0
add ax,bx  ;得到开始写入字符串的内存地址
mov di,ax
mov si,0
mov ah,cl
print_s:    mov cl,ds:[si]
mov ch,0
jcxz print_s1
mov es:[di],cl
mov byte ptr es:[di+1],ah
inc si
inc di
inc di
loop print_s
print_s1:   pop cx
pop di
pop si
pop bx
pop dx
pop ax
pop es
ret

;不会溢出的除法,参考公式X/N = int(H/N)*65536 + [rem(H/N)*65536 + L]/N
;65536=2^16=10000h
;(dx)被除数高16位 (ax)被除数低16位,(cx)除数
;返回(dx)商高16位 (ax)商低16位 (cx)余数
divdw:  push bx
push ax ;将被除数低16位入栈
mov ax,dx
mov dx,0
div cx ;处理被除数的高16位,商放在ax中,余数放在dx中
mov bx,ax;bx存储高16位的商,作为最终结果的高16位int(H/N)*65536
pop ax ;低16位出栈,这是(dx)=被除数高16位的余数即上面公式的rem(H/N)*65536
div cx ;处理低16位,[rem(H/N)*65536 + L]/N,余数放在dx中
mov cx,dx
mov dx,bx
pop bx
ret

;dword型数据转化为字符串,ds:[si]
;(dx)高16位,(ax)低16位
dword_str:  push bx
push cx
push dx
push ax
push si
mov bx,0

dword_str_x:mov cx,10;cx存储除数
call divdw
push cx;将余数入栈,若不用栈操作则显示时是相反的顺序
inc bx
mov cx,dx
jcxz dword_str_a;如果商的高16位等于0则验证低16位是否等于0
jmp near ptr dword_str_x
dword_str_a:mov cx,ax
jcxz dword_str_x1;如果商的低16位也等于0则退出循环
jmp near ptr dword_str_x

dword_str_x1:mov cx,bx;循环次数
dword_str_x2:pop ds:[si]
add byte ptr ds:[si],30h;将数字+30h变成相应的字符串
inc si
loop dword_str_x2

pop si
pop ax
pop dx
pop cx
pop bx
ret

;word型数据转化为字符串
word_str:   push bx
push cx
push dx
push ax
push si
mov bx,0
word_str_s: mov dx,0;防止溢出用16位除法
mov cx,10
div cx
push dx
inc bx
mov cx,ax
jcxz word_str_x
jmp short word_str_s

word_str_x: mov cx,bx
word_str_x1:pop ds:[si]
add byte ptr ds:[si],30h;将数字+30h变成相应的字符串
inc si
loop word_str_x1

pop si
pop ax
pop dx
pop cx
pop bx
ret

codesg ends

end start


View Code

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: