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

说的多不如做的多,子程序的功能十分重要,这篇笔记用来记录书上练习题的代码,加强对子程序的应用。

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

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

 1 assume cs:codesg,ds:data
 2 
 3 data segment
 4 db 'welcome to masm!'
 5 data ends
 6 
 7 codesg segment
 8     
 9 start:  mov ax,data
10         mov ds,ax
11         mov bx,0
12         mov ax,0B800h
13         mov es,ax
14 
15         ;第10行中间显示绿色字体
16         mov si,10*160+32
17         mov cx,16
18     s:  mov al,ds:[bx]
19         mov es:[si+24],al
20         mov byte ptr es:[si+25],02h
21         inc bx
22         inc si
23         inc si
24         loop s
25 
26         ;第11行中间显示红底绿色字体
27         mov si,11*160+32
28         mov bx,0
29         mov cx,16
30     s1: mov al,ds:[bx]
31         mov es:[si+24],al
32         mov byte ptr es:[si+25],42h
33         inc bx
34         inc si
35         inc si
36         loop s1
37 
38         ;第12行中间显示白底蓝色字体
39         mov si,12*160+32
40         mov bx,0
41         mov cx,16
42     s2: mov al,ds:[bx]
43         mov es:[si+24],al
44         mov byte ptr es:[si+25],71h
45         inc bx
46         inc si
47         inc si
48         loop s2
49 
50         mov ax,4c00h
51         int 21h
52  
53 codesg ends
54 end start

 

在学习了子程序之后可以更简洁的代码实现该功能

 1 assume cs:codesg,ds:data
 2 
 3 
 4 data segment
 5 db 'welcome to masm!',0
 6 data ends
 7 
 8 codesg segment
 9     
10 start:  mov ax,data
11         mov ds,ax
12         mov ax,0B800h
13         mov es,ax
14         ;第10行中间显示绿色字体
15         mov dh,10D
16         mov dl,32D
17         mov bl,02h
18         call print
19         ;第11行中间显示红底绿色字体
20         mov dh,11D
21         mov dl,32D
22         mov bl,42h
23         call print
24         ;第12行中间显示白底蓝色字体
25         mov dh,12D
26         mov dl,32D
27         mov bl,71h
28         call print
29 
30         mov ax,4c00h
31         int 21h
32 
33 print:  push ax
34         push dx
35         push bx
36         mov al,160D
37         mul dh      
38         mov cl,dl
39         mov ch,0
40         add ax,cx  ;得到开始写入字符串的内存地址
41         mov si,ax
42         mov di,0
43     s:  mov cl,ds:[di]
44         mov ch,0
45         jcxz s1
46         mov es:[si],cl
47         mov byte ptr es:[si+1],bl
48         inc di
49         inc si
50         inc si
51         loop s
52     s1: pop bx
53         pop ax
54         pop dx
55         ret
56  
57 codesg ends
58 end start

 

数值转换

 1 assume cs:codesg,ds:data
 2 
 3 
 4 data segment
 5 db 10 dup(0)
 6 data ends
 7 
 8 codesg segment
 9     
10 start:  mov ax,data
11         mov ds,ax
12         mov si,0
13         mov ax,1266d
14         call doc
15 
16         ;第10行中间显示绿色字体
17         mov dh,10D
18         mov dl,32D
19         mov bl,02h
20         call print
21         
22 
23         mov ax,4c00h
24         int 21h
25 
26   doc:  push ax
27         push si
28     s0: mov bl,10d
29         div bl
30         add ah,30h
31         mov ds:[si],ah
32         mov ah,0
33         inc si
34         mov cl,al
35         mov ch,0
36         jcxz s2
37         jmp short s0
38 
39     s2: mov byte ptr ds:[si],0
40         pop si
41         pop ax
42         ret
43 
44 
45 print:  push ax
46         push dx
47         push bx
48         mov ax,0B800h
49         mov es,ax
50         mov al,160D
51         mul dh      
52         mov cl,dl
53         mov ch,0
54         add ax,cx  ;得到开始写入字符串的内存地址
55         mov si,ax
56         mov di,0
57     s:  mov cl,ds:[di]
58         mov ch,0
59         jcxz s1
60         mov es:[si],cl
61         mov byte ptr es:[si+1],bl
62         inc di
63         inc si
64         inc si
65         loop s
66     s1: pop bx
67         pop ax
68         pop dx
69         ret
70  
71 codesg ends
72 end start

 

课程设计1

  1 assume cs:codesg,es:data,ss:stack
  2 data segment
  3 ;年份
  4 db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
  5 db '1984','1985','1986','1987','1988','1989','1900','1991','1992'
  6 db '1993','1994','1995'
  7 ;公司总收入
  8 dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
  9 dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
 10 ;雇员
 11 dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
 12 dw 11542,14430,45257,17800
 13 data ends
 14 
 15 ;栈空间
 16 stack segment 
 17 db 16 dup(0)
 18 stack ends
 19 
 20 ;临时内存空间,将字符串后面加0
 21 temp segment
 22 db 8 dup(0)
 23 temp ends
 24 
 25 codesg segment
 26     
 27 start:  ;清除屏幕上的原有内容
 28         mov ax,0b800h
 29         mov es,ax
 30         mov si,0
 31         mov cx,25*80
 32     x:  mov byte ptr es:[si],' '
 33         mov byte ptr es:[si+1],0
 34         inc si
 35         inc si
 36         loop x
 37         ;分配栈空间
 38         mov ax,stack
 39         mov ss,ax
 40         mov sp,16
 41         ;指定数据入口
 42         mov ax,data
 43         mov es,ax
 44         mov ax,temp
 45         mov ds,ax
 46         mov si,0
 47         mov di,0
 48         mov bx,0
 49         mov dh,4
 50         ;循环21次,输出21年数据
 51         mov cx,21
 52 
 53     x1: push cx
 54         ;显示年份
 55         mov ax,es:[di]
 56         mov ds:[si],ax
 57         mov ax,es:[di+2]
 58         mov ds:[si+2],ax
 59         mov byte ptr ds:[si+4],0
 60         mov dl,10
 61         mov cl,02h
 62         call print 
 63 
 64         ;显示公司收入
 65         mov ax,es:[di+84]
 66         push dx
 67         mov dx,es:[di+84+2]
 68         call dword_str
 69         pop dx
 70         mov dl,20h
 71         call print
 72 
 73         ;显示雇员人数
 74         mov ax,es:[bx+84+84]
 75         call word_str
 76         mov dl,40h
 77         call print
 78 
 79         ;计算人均收入并显示
 80         mov ax,es:[di+84]
 81         push dx
 82         mov dx,es:[di+84+2]
 83         div word ptr es:[bx+84+84]
 84         call word_str
 85         pop dx
 86         mov dl,60h
 87         call print
 88         add di,4
 89         add bx,2
 90         inc dh
 91         pop cx
 92         loop x1
 93         
 94         mov ax,4c00h
 95         int 21h
 96 
 97 
 98 
 99 
100             ;显示ds:[si]开始的字符串
101 print:      push es
102             push ax
103             push dx
104             push bx
105             push si
106             push di
107             push cx
108             
109             mov ax,0B800h
110             mov es,ax
111             mov al,160D
112             mul dh      
113             mov bl,dl
114             mov bh,0
115             add ax,bx  ;得到开始写入字符串的内存地址
116             mov di,ax
117             mov si,0
118             mov ah,cl
119 print_s:    mov cl,ds:[si]
120             mov ch,0
121             jcxz print_s1
122             mov es:[di],cl
123             mov byte ptr es:[di+1],ah
124             inc si
125             inc di
126             inc di
127             loop print_s
128 print_s1:   pop cx
129             pop di
130             pop si
131             pop bx
132             pop dx
133             pop ax
134             pop es
135             ret
136 
137             ;不会溢出的除法,参考公式X/N = int(H/N)*65536 + [rem(H/N)*65536 + L]/N
138             ;65536=2^16=10000h
139             ;(dx)被除数高16位 (ax)被除数低16位,(cx)除数
140             ;返回(dx)商高16位 (ax)商低16位 (cx)余数
141     divdw:  push bx
142             push ax ;将被除数低16位入栈
143             mov ax,dx
144             mov dx,0
145             div cx ;处理被除数的高16位,商放在ax中,余数放在dx中
146             mov bx,ax;bx存储高16位的商,作为最终结果的高16位int(H/N)*65536
147             pop ax ;低16位出栈,这是(dx)=被除数高16位的余数即上面公式的rem(H/N)*65536
148             div cx ;处理低16位,[rem(H/N)*65536 + L]/N,余数放在dx中
149             mov cx,dx
150             mov dx,bx
151             pop bx
152             ret
153 
154             ;dword型数据转化为字符串,ds:[si]
155             ;(dx)高16位,(ax)低16位
156 dword_str:  push bx
157             push cx
158             push dx
159             push ax
160             push si
161             mov bx,0
162 
163 dword_str_x:mov cx,10;cx存储除数
164             call divdw
165             push cx;将余数入栈,若不用栈操作则显示时是相反的顺序
166             inc bx
167             mov cx,dx
168             jcxz dword_str_a;如果商的高16位等于0则验证低16位是否等于0
169             jmp near ptr dword_str_x
170 dword_str_a:mov cx,ax
171             jcxz dword_str_x1;如果商的低16位也等于0则退出循环
172             jmp near ptr dword_str_x
173 
174              
175 dword_str_x1:mov cx,bx;循环次数
176 dword_str_x2:pop ds:[si]
177              add byte ptr ds:[si],30h;将数字+30h变成相应的字符串
178              inc si
179              loop dword_str_x2
180 
181              pop si
182              pop ax
183              pop dx
184              pop cx
185              pop bx
186              ret
187 
188             ;word型数据转化为字符串
189 word_str:   push bx
190             push cx
191             push dx
192             push ax
193             push si
194             mov bx,0
195 word_str_s: mov dx,0;防止溢出用16位除法
196             mov cx,10
197             div cx
198             push dx
199             inc bx
200             mov cx,ax
201             jcxz word_str_x
202             jmp short word_str_s
203 
204 word_str_x: mov cx,bx
205 word_str_x1:pop ds:[si]
206             add byte ptr ds:[si],30h;将数字+30h变成相应的字符串
207             inc si
208             loop word_str_x1
209 
210             pop si
211             pop ax
212             pop dx
213             pop cx
214             pop bx
215             ret
216 
217 
218 codesg ends
219 
220 end start
View Code