前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《汇编语言》课程设计2

《汇编语言》课程设计2

原创
作者头像
Hk_Mayfly
修改2019-07-30 19:15:49
6190
修改2019-07-30 19:15:49
举报
代码语言:javascript
复制
  1 assume cs:code,ss:stack
  2 stack segment
  3     db 128 dup (0)
  4 stack ends
  5 code segment
  6 start:
  7     mov ax,stack
  8     mov ss,ax
  9     mov sp,128
 10     
 11     call copy_boot
 12     
 13     ;设置CS:IP为0:7e00h
 14     mov ax,0
 15     push ax
 16     mov ax,7e00h
 17     push ax
 18     retf
 19     
 20     mov ax,4c00h
 21     int 21h
 22 ;org 7e00h
 23 ;引导程序
 24 boot:
 25     jmp boot_begin
 26     func0    db 'Hk_Mayfly----XIUXIUXIU~',0
 27     func1    db '1) reset pc',0
 28     func2    db '2) start system',0
 29     func3    db '3) clock',0
 30     func4    db '4) set clock',0
 31     ;相减得到的是标号的相对位置,+7e00h得到的绝对位置
 32     func_pos    dw offset func0-offset boot+7e00h
 33                 dw offset func1-offset boot+7e00h
 34                 dw offset func2-offset boot+7e00h
 35                 dw offset func3-offset boot+7e00h
 36                 dw offset func4-offset boot+7e00h
 37     time    db 'YY/MM/DD hh:mm:ss',0
 38     cmos    db 9,8,7,4,2,0
 39     clock1    db 'F1----change the color        ESC----return menu',0
 40     clock2    db 'Please input Date and Time,(YY MM DD hh mm ss):',0
 41     change    db 12 dup (0),0
 42 
 43 boot_begin:
 44     call init_boot
 45     call cls_screen
 46     call show_menu 
 47     jmp choose
 48     mov ax,4c00h
 49     int 21h
 50 
 51 choose:
 52     call clear_kb_buffer
 53     ;获取我们输入的操作,跳转到对于函数
 54     mov ah,0
 55     int 16h
 56     cmp al,'1'
 57     je choose_func1
 58     cmp al,'2'
 59     je choose_func2
 60     cmp al,'3'
 61     je choose_func3
 62     cmp al,'4'
 63     je choose_func4
 64     
 65     jmp choose
 66 
 67 ;在题中提到了,开机后进入到ffff:0处执行指令
 68 ;那我们也可以把重启理解为,跳转到ffff:0执行指令
 69 ;所以我们利用jmp dword跳转到ffff:0地址,模拟重启
 70 choose_func1:
 71     mov bx,0ffffh
 72     push bx
 73     mov bx,0
 74     push bx
 75     retf
 76     
 77     jmp choose
 78 
 79 ;题中对引导现有的操作系统的描述是调用int 19,这里为了方便就直接写成函数了
 80 choose_func2:
 81     mov bx,0
 82     mov es,bx
 83     mov bx,7c00h
 84     
 85     mov al,1;扇区数
 86     mov ch,0
 87     mov cl,1;扇区
 88     mov dl,0
 89     mov dh,0
 90     mov ah,2;读取
 91     int 13h
 92     
 93     mov bx,0
 94     push bx
 95     mov bx,7c00h
 96     push bx
 97     retf
 98     
 99     jmp choose
100 
101 ;获取时间
102 choose_func3:
103     call show_time
104     
105     jmp choose
106 
107 show_time:
108     call init_boot
109     call cls_screen
110     ;显示按键信息
111     mov si,offset clock1-offset boot+7e00h
112     mov di,160*14+10*2;在14行10列显示
113     call show_line
114 show_time_start:
115     ;获取时间信息,并显示(将time中的未知字符替换为当前时间)
116     call get_time_info
117     mov di,160*10+30*2;屏幕显示的偏移地址
118     mov si,offset time-offset boot+7e00h;time标号的偏移地址
119     call show_line
120     
121     ;获取键盘缓存区的数据
122     mov ah,1
123     int 16h
124     ;没有数据就跳回show_time_start
125     jz show_time_start
126     ;判断是否按下F1
127     cmp ah,3bh
128     je change_color
129     ;判断是否按下ESC
130     cmp ah,1
131     je Return_Main
132     ;有数据,但是是无用的键盘中断,清除
133     cmp al,0
134     jne clear_kb_buffer2
135     ;返回开始,重复之前的操作,达到刷新时间的效果。
136     jmp show_time_start
137 
138 change_color:
139     call change_color_show
140 clear_kb_buffer2:
141     call clear_kb_buffer
142     jmp show_time_start
143 Return_Main:
144     ;返回到开始,重新打印菜单
145     jmp boot_begin
146     ret
147 
148 choose_func4:
149     call set_time
150     jmp boot_begin
151     
152 set_time:
153     call init_boot
154     call cls_screen
155     call clear_stack
156     
157     ;设置提示信息显示位置
158     mov di,160*10+13*2
159     mov si,offset clock2-offset boot+7e00h
160     call show_line
161     ;显示修改后change中的内容
162     mov di,160*12+26*2
163     mov si,offset change-offset boot+7e00h
164     call show_line
165     
166     call get_string
167 
168 get_string:
169     mov si,offset change - offset boot + 07e00H
170     mov bx,0
171 getstring:
172     ;获取键盘输入的时间信息
173     mov ah,0
174     int 16h
175     
176     ;输入的时间为数字0~9
177     cmp al,'0'
178     jb error_input
179     cmp al,'9'
180     ja error_input
181     ;将我们输入的时间字符入栈
182     call char_push
183     ;不能超过输入的数量
184     cmp bx,12
185     ja press_ENTER
186     mov di,160*12+26*2
187     call show_line
188     jmp getstring
189 error_input:
190     ;判断是不是按下退格或回车键
191     cmp ah,0eh
192     je press_BS
193     cmp ah,1ch
194     je press_ENTER
195 
196     jmp getstring
197 ;按下回车
198 press_BS:
199     call char_pop
200     mov di,160*12+26*2
201     call show_line
202     jmp getstring
203 ;按下enter就退出
204 press_ENTER:
205     ret
206 
207 char_push:
208     ;只能最多输入12个梳子
209     cmp bx,12
210     ja char_push_end
211     ;将数值移动到对应位置
212     mov ds:[si+bx],al
213     inc bx;表示我们输入了多少个字符
214 char_push_end:
215     ret
216 
217 char_pop:
218     ;判断是否输入了设置时间的数值,没有就相当于删完了
219     cmp bx,0
220     je char_pop_end
221     ;否则用星号替换,相当于删除
222     dec bx
223     mov byte ptr ds:[si+bx],'*'
224 char_pop_end:
225     ret
226 
227 clear_stack:
228     push bx
229     push cx
230     
231     mov bx,offset change-offset boot+7e00h
232     mov cx,12
233 cls_stack:
234     ;替换change段中内容
235     mov byte ptr ds:[bx],'*'
236     inc bx
237     loop cls_stack
238     
239     pop cx
240     pop bx
241     ret
242     
243 
244 ;获取时间
245 get_time_info:
246     ;从cmos ram获取年月日,时分秒6个数据
247     mov cx,6
248     ;获取存放单元地址
249     mov bx,offset cmos - offset boot + 7e00H
250     ;通过替换来显示
251     mov si,offset time - offset boot + 7e00H
252 next_point:   
253     push cx
254     ;获取单元号
255     mov al,ds:[bx]
256     ;向70h端口写入要访问的单元地址,并从71h端口读取数据
257     out 70H,al
258     in al,71H
259     ;右移4位获取十位
260     mov ah,al
261     mov cl,4
262     shr al,cl
263     and ah,00001111b
264     ;将BCD码转换为ASCII码
265     add ax,3030H
266      ;写入time中
267     mov word ptr ds:[si],ax
268     ;下一单元号
269     inc bx
270     ;每个数据之间距离都是3
271     add si,3
272     pop cx
273     loop next_point
274     ret
275 
276 ;改变颜色
277 change_color_show:
278     push bx
279     push cx
280  
281     mov cx,2000
282     mov bx,1
283 next:
284     ;属性值+1,改变颜色
285     add byte ptr es:[bx],1
286     ;当超出字体颜色的数值(0~111h)时,将数值重置
287     cmp byte ptr es:[bx],00001000b
288     jne change_end
289     ;因为背景是黑色,所以文字颜色就不设置成黑色了
290     mov byte ptr es:[bx],1
291 change_end:
292     add bx,2
293     loop next
294  
295     pop cx
296     pop bx
297     ret
298 
299 clear_kb_buffer:
300     ;1号程序,用来检测键盘缓冲区是否有数据
301     ;如果有的话ZF!=0,没有,ZF=0
302     mov ah,1
303     int 16h
304     ;通过ZF判断减缓缓冲区是否有数据,没有就跳出
305     jz clear_kb_bf_end
306     mov ah,0
307     int 16h
308     jmp clear_kb_buffer
309 clear_kb_bf_end:
310     ret
311 
312 init_boot:
313     ;基本设置,注意:程序的直接定址表默认段地址是CS
314     ;当程序转移到7c00h时,代码中CS值未发生改变,
315     ;所以需要我们指明段地址
316     mov bx,0b800h
317     mov es,bx
318     mov bx,0
319     mov ds,bx
320     ret
321     
322 ;清屏
323 cls_screen:
324     mov bx,0
325     mov cx,2000
326     mov dl,' '
327     mov dh,2;字体为绿色,不设置的话,在我们显示菜单时,字体和背景颜色相同
328 s:    mov es:[bx],dx
329     add bx,2
330     loop s
331 sret:
332     ret
333 
334 ;展示界面
335 show_menu:
336     ;在10行,30列显示菜单
337     mov di,160*10+30*2
338     ;保存在直接定址表的绝对位置
339     mov bx,offset func_pos-offset boot+7e00h
340     ;菜单有5行
341     mov cx,5
342 s1:
343     ;这里相当于外循环,每次一行
344     ;获取func_pos中每行的保存位置的偏移地址
345     mov si,ds:[bx]
346     ;调用内循环函数,输出一行的每个字符
347     call show_line
348     ;下一行偏移地址
349     add bx,2
350     ;下一行显示
351     add di,160
352     loop s1
353     ret
354     
355 show_line:
356     push ax
357     push di
358     push si
359 show_line_start:
360     ;获取这一行的第si+1个字符
361     mov al,ds:[si]
362     ;判断是否到末尾
363     cmp al,0
364     je show_line_end
365     ;保存字符到显示缓冲区
366     mov es:[di],al
367     add di,2
368     inc si
369     jmp show_line_start
370 show_line_end:
371     pop si
372     pop di
373     pop ax
374     ret
375 
376 boot_end:nop
377 
378 ;转存引导程序
379 copy_boot:
380     ;将引导程序储存到指定位置
381     mov ax,0
382     mov es,ax
383     mov di,7e00h
384     
385     mov ax,cs
386     mov ds,ax
387     mov si,offset boot
388     mov cx,offset boot_end-offset boot
389     cld
390     rep movsb
391     
392     ret
393 
394 code ends
395 end start

具体的在注释中都说明了。

jz指令:https://zhidao.baidu.com/question/564008138.html

int 16的1号程序:https://zhidao.baidu.com/question/511189643.html

总结

  汇编的难度并不大,我认为在有编程的基础上,学习汇编要做到细致,细致的理解计算机编程的编译过程,对于我理解其他编程语言也有很大的帮助。欢迎大家关注,一起交流。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档