0.前言

在整个课程中,我们一共有两个课程设计,这是第一个课程设计的简易版本。所谓简易,即数据不涉及到除法溢出,仅用前9个实验的内容即可完成的课程设计。

1.思路分析

课程设计1是在实验七+实验九所结合的实验。

以下是我们进行处理以后的数据,是不考虑除法溢出的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
data segment

db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
;以上是表示21年的21个字符串 year


dd 16,22,382,1356,2390,8000,16000,24486,50065,9749,14047,19751
dd 34598,59082,80353,11830,18430,27590,37530,46490,59370
;以上是表示21年公司总收入的21个dword数据 sum

dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 1154,1443,1525,1780

data ends

table segment

;0123456789ABCDEF
db 21 dup ('year summ ne ?? ')

table ends

stack segment stack
db 128 dup (0)
stack ends

为了实现书中如表格一样的效果,我们需要做以下两步:

  • 要将不规则的数据变成('year summ ne ?? ')形式储存的数据
  • ('year summ ne ?? ')形式的数据显示到屏幕上

1.1 将不规则的数据变成('year summ ne ?? ')形式储存的数据

此步骤乃实验七的内容,代码详见《汇编语言》王爽 实验7

1.2将('year summ ne ?? ')形式的数据显示到屏幕上

投屏乃实验九的内容,为总结,此处稍微提及。

​ 投屏:通常情况下,B8000H~B8F9FH中的4000个字节的内容会出现在显示器上,所以我们要向让我们的内容出现在屏幕中,那么就要将数据移动到B8000H开始的这4000个字节中。

​ 通常,一个字符占两个字节,低位字节存储字符的ascii码,高位字节存储字符的属性。

​ 属性字节的格式:7 6 5 4 3 2 1 0
​ BL R G B I R G B
​ 闪烁 背景RGB 高亮 字体RGB

如红底绿字的属性值为:01000010B

显示部分的思路:

首先要明确三点,数据从哪来,数据如何处理,数据到哪去。也就是输入,运算,输出三个过程。

毫无疑问的是,在显示算法的设计中,我们数据都是从已经整理好的table中来,最后的数据去想也都是到B8000H中去

运算则有些许不同,在后三个数据显示中说说明。

年份数据的显示:写一个show_year函数
首先,确立好数据的来源,之后直接将数据复制到B8000H即可
因为在内存中,year本身就是以字符存储,因此运算便是直接将数据复制到B8000H中

年总收入的显示:写一个show_money函数
首先,确立好数据的来源,之后直接将数字数据转换为字符数据
年总收入的存储,我们采用的是数字,存到内存中仍是数字
如何将数字转换为,我们采用short_div函数来实现

年员工人数的显示:写一个show_nfp函数
同年总收入,唯一的区别就是来源与去想稍微有些许不同

年平均人均收入的显示:写一个show_salary函数
同年总收入,唯一的区别就是来源与去想稍微有些许不同

将数字装化为字符:写一个short_div函数
不断的对储存的数据除10取余,依次余数分别为个位数,十位数,百位数,千位数……,每获得一个数,将数值+=30H,因为数字的ascii码是比数值大30H,也就是数字0对应的ascii码实际上为30H。我们+=后的数值放在B8000H段上,即可显示数据

这是大概的思路,详细的过程参照源码实现

3.源码实现

masm中标准的三个段:code data stack
再用不同的寄存器去表示不同的数据的位置 (对数据的格式化处理)
使用不同的名称+ret实现子程序(函数or方法)
使用call调用函数 (对代码块的格式化处理)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
assume cs:code,ds:data,ss:stack

data segment

db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
;以上是表示21年的21个字符串 year


dd 16,22,382,1356,2390,8000,16000,24486,50065,9749,14047,19751
dd 34598,59082,80353,11830,18430,27590,37530,46490,59370
;以上是表示21年公司总收入的21个dword数据 sum

dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 1154,1443,1525,1780

data ends

table segment

;0123456789ABCDEF
db 21 dup ('year summ ne ?? ')

table ends

stack segment stack
db 128 dup (0)
stack ends



code segment

start: mov ax,stack
mov ss,ax
mov sp,128

call set_table
call cls
call show_table

mov ax,4C00H
int 21H


;-----------set_table----
set_table:
mov ax,data
mov ds,ax

mov ax,table
mov es,ax



mov bx,0 ;year
mov si,84 ;money
mov di,168 ;pnumber
mov bp,0 ;result
mov cx,21
set_row:
push ds:[bx]
pop es:[bp]
push ds:[bx+2]
pop es:[bp+2]

mov ax,ds:[si]
mov es:[bp+5],ax
mov dx,ds:[si+2]
mov es:[bp+7],dx

push ds:[di]
pop es:[bp+10]

div word ptr ds:[di]
mov es:[bp+13],ax

add bx,4
add si,4
add di,2
add bp,16

loop set_row

ret
;-----------------------
;-------cls-------------
cls:
mov bx,0B800H
mov es,bx

mov bx,0
mov dx,0700H
mov cx,2000
clean:
mov es:[bx],dx
add bx,2
loop clean
ret
;-----------------------
;----------show_table---
show_table:
mov bx,table
mov ds,bx
mov si,0

mov bx,0B800H
mov es,bx
mov di,160*4

mov cx,21
show:
call show_year
call show_money
call show_nfp
call show_salary

add di,160
add si,16
loop show
ret

;-----------------
;------show_year
show_year:
push ax
push cx
push ds
push es
push si
push di

mov cx,4
showYear:
mov al,ds:[si]
mov es:[di],al
add di,2
inc si
loop showYear

pop di
pop si
pop es
pop ds
pop cx
pop ax
ret

;----------------
;------show_money---
show_money:
push ax
push bx
push cx
push dx
push ds
push es
push si
push di


mov ax,ds:[si+5]
mov dx,ds:[si+7]

add di,20*2

call short_div

pop di
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
ret
;------------------
;--------show_nfp
show_nfp:
push ax
push bx
push cx
push dx
push ds
push es
push si
push di

mov ax,ds:[si+0Ah]
mov dx,0

add di,20*4

call short_div

pop di
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
ret
;------------------
;------show_salary
show_salary:
push ax
push bx
push cx
push dx
push ds
push es
push si
push di

mov ax,ds:[si+0Dh]
mov dx,0

add di,20*6

call short_div

pop di
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
ret
;-------------------
;--------short_div
short_div:
mov cx,10
div cx
add dl,30h
mov es:[di],dl
mov cx,ax
jcxz shortDivOver
mov dx,0
sub di,2
jmp short_div
shortDivOver:
ret
;-------------------
code ends



end start

4.结果显示

result

5.收获感悟

简易版本的课程设计1,复习了实验7与实验9的内容,使对汇编程序的设计思路有了更深的理解,同时学会了当寄存器冲突时,灵活使用栈来存储值,来避免冲突。

正如在实验7中所说,学到了汇编语言中对数据的结构化处理的思想(在C语言中我们也学习了结构体来对相似属性的数据进行储存,在C++/Java等面向对象的语言中,我们使用类来对相同属性的数据进行分类,结构化)。

在第9章、第10章的学习中,我有学到了汇编语言中对代码结构化处理的方法(在C/C++中我们有函数对代码结构化处理,在Java/Python中我们有方法对代码结构化处理,因此结构化处理代码的思想我们同样不是第一次接触)

8086汇编语言至此已经学了一大半,语言语法只是一种工具,重要的是人想如何去做,就如mc中,每一个方砖都是工具,最后你想搭建成如何的建筑,还是看人是如何思考。

重温学习汇编语言的目的:充分获得底层编程的体验,深刻理解机器运行程序的机理。