彙編學習筆記(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