汇编学习笔记(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

 

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

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

 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

 

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

你可能感兴趣的:(学习笔记)