王爽汇编语言课程设计2

王爽汇编语言 第二版 课程设计2

编写一个可以自行启动的计算机,不需要在现有操作系统环境中运行的程序

一、相关资料

系统启动初始化完成后最终调用19h,该中断读取软盘的第一扇区或硬盘的第一扇区到0:7c00开始的512个字节的内存空间中,并将cs:ip指向0:7c00执行。

更详细参考王爽汇编语言第二版,课程设计2,p.312

二、设计思路

将安装程序分为三个段,

1、第一个段为安装程序,负责将第二个段写入第一扇区,第三个段写入2-17扇区;

2、第二个段是主引导程序,存在于软盘第一扇区,由BIOS的19h中断读取到0:7c00开始的内存单元中,并执行0:7c00的第一行代码。这一段的任务是将软盘2-17扇区的数据读入内存,并执行。(这里读入到了2000:0开始的内存中)

3、第三个段是系统程序,存放所有引导所需的程序和子程序

三、详细设计

assume cs:setupsg

;安装程序
;将引导所需的程序写入到软盘
setupsg segment
assume cs:setupsg
setup:
 ;主引导程序安装到第一扇区
 mov ax,initsg
 mov es,ax
 mov bx,0

 mov al,1
 mov ch,0
 mov cl,1
 mov dl,0
 mov dh,0

 mov ah,3
 int 13h

 ;子程序安装到从第2扇区开始的扇区
 mov ax,syssg
 mov es,ax
 mov al,15
 mov cl,2

 mov ah,3
 int 13h

 ;安装结束,返回
 mov ax,4c00h
 int 21h

setupsg ends


;主引导程序
;包含所有子程序的直接定址表,扇区加载程序,菜单
initsg segment
assume cs:initsg
init:
 call loadsys

 mov ax,2000h
 push ax
 mov ax,0
 push ax
 retf


loadsys:
 mov ax,2000h  ;软盘数据读取到2000:0
 mov es,ax
 mov bx,0

 mov al,15  ;读取的扇区数
 mov ch,0  ;0磁道
 mov cl,2  ;2扇区
 mov dl,0  ;0号驱动器
 mov dh,0  ;0面

 mov ah,2
 int 13h

 ret


initsg ends



;子程序
;包含所有菜单需要调用的子过程
syssg segment
assume cs:syssg

;菜单显示功能
menu:
 jmp near ptr menushow
 menudata dw offset md0,offset md1,offset md2,offset md3,offset md4,offset md5
 md0 db "------ welcome ------",0
 md1 db "1) reset pc",0
 md2 db "2) start system",0
 md3 db "3) clock",0
 md4 db "4) set clock",0
 md5 db "copyright @ 2010 Shiying,Inc.All rights reserved.",0
 systable dw sys_restart,sys_disksys,sys_showclock,sys_setclock
menushow:
 mov dh,5
 mov dl,30
 mov bp,0
 mov ax,cs
 mov ds,ax
 mov cx,5
menushow_s:
 push cx
 mov si,menudata[bp]
 mov cl,02h
 call sys_showstr
 add bp,2
 add dh,2
 pop cx
 loop menushow_s
 mov si,offset md5
 mov dh,23
 mov dl,28
 mov cl,02h
 call sys_showstr


;处理用户输入
sys_input:
 mov ah,0
 int 16h
 mov bx,0
 mov bl,al
 mov al,30h
 sub bl,al ;ascii转换为序列号
 sub bl,1 ;1-4转换为0-3

 cmp bx,0
 jb cycle
 cmp bx,3
 ja cycle
 add bx,bx
 call word ptr systable[bx]  ;调用菜单功能

cycle:
 jmp short sys_input


;重启计算机
sys_restart:
 mov ax,0ffffh
 push ax
 mov ax,0h
 push ax
 retf


;从硬盘引导
sys_disksys:
 call cls

 mov ax,0h  ;硬盘数据读取到0:7c00
 mov es,ax
 mov bx,7c00h

 mov al,1  ;读取的扇区数
 mov ch,0  ;0磁道
 mov cl,1  ;1扇区
 mov dl,80h  ;c盘
 mov dh,0  ;0面

 mov ah,2
 int 13h

 mov ax,0h
 push ax
 mov ax,7c00h
 push ax
 retf


;显示时钟
sys_showclock:
 call cls
 jmp short clockread
clockdata:
 clockstr dw offset cl1,offset cl2,offset cl3
 clockcolor db 02h
 cl1 db '00/00/00 00:00:00',0
 cl2 db 'press ESC return menu!',0
 cl3 db 'press F1 change color!',0
 cltable db 9,8,7,4,2,0
clockread:
 mov si,0        ;si指向'yy/mm/dd hh:mm:ss'的首地址
 mov di,0        ;di指向9,8,7,4,2,0的首地址
 mov cx,6        ;循环次数
clockread_s:
 push cx
 mov al,cltable[di]    ;从CMOS中读出年份的BCD码
 out 70h,al        
 in al,71h
 mov ah,al        ;al中位读出的数据
 mov cl,4        
 shr ah,cl        ;ah中为年份的十位数
 and al,00001111b    ;al中为年份的个位数
 add ah,30h        ;把数值转换为对应的ASCII码
 add al,30h        ;同上
 mov byte ptr cl1[si],ah    ;把读出的时间写入
 mov byte ptr cl1[si+1],al
 add si,3
 inc di
 pop cx
 loop clockread_s
clockprint:
 mov dh,6
 mov dl,30
 mov bp,0
 mov ax,cs
 mov ds,ax
 mov cx,3
clockprint_s:
 push cx
 mov si,clockstr[bp]
 mov cl,clockcolor[0]  ;将颜色值赋值给cl
 call sys_showstr
 add bp,2
 add dh,2
 pop cx
 loop clockprint_s
 mov ah,1 ;调用16h中断的1号功能(非阻塞)
 int 16h
 cmp al,1bh ;判断是否为ESC
 je clockreturn ;若是ESC,回到菜单
 cmp ah,3bh ;判断是否为F1
 je changecolor
 jmp short clockread
clockreturn:
 call cls
 mov ah,0    ;16h中断的1号功能不会清除键盘缓冲区,下次读取还会读出
 int 16h     ;调用0号功能清除一次
 jmp near ptr menu
changecolor:
 inc clockcolor
 mov ah,0    ;16h中断的1号功能不会清除键盘缓冲区,下次读取还会读出
 int 16h     ;调用0号功能清除一次
 jmp near ptr clockread


;设置时钟
sys_setclock:
 jmp short setclock
 setclockdata db 'Please input time like "yy/mm/dd hh:mm:ss"',0
 setsuccess   db  'Set clock successful! Press any key return...',0
setclock:
 call cls
 mov dh,6
 mov dl,20
 mov cl,02h
 mov ax,cs
 mov ds,ax
 mov si,offset setclockdata
 call sys_showstr
 call getstr 
 call settime
 mov dh,10
 mov dl,20
 mov cl,02h
 mov ax,cs
 mov ds,ax
 mov si,offset setsuccess
 call sys_showstr
 mov ah,0
 int 16h
 call cls
 jmp near ptr menu


;ds:si指向时间字符串
settime:
 jmp short seting
 settable db 9,8,7,4,2,0
seting:
 mov bx,0
 mov cx,6
settime_s:
 mov dh,ds:[si]
 inc si
 mov dl,ds:[si]
 add si,2
 mov al,30h
 sub dl,al
 sub dh,al
 shl dh,1
 shl dh,1
 shl dh,1
 shl dh,1
 or dl,dh
 mov al,settable[bx]
 out 70h,al
 mov al,dl
 out 71h,al
 inc bx
 loop settime_s
 ret

;子程序:接收字符串
getstr:
 push ax
getstrs:
 mov ah,0
 int 16h
 cmp al,20h
 jb nochar
 mov ah,0
 call charstack
 mov ah,2
 mov dh,8
 mov dl,25
 call charstack
 jmp getstrs
nochar:
 cmp ah,0eh
 je backspace
 cmp ah,1ch
 je enter
 jmp getstrs
backspace:
 mov ah,1
 call charstack
 mov ah,2
 call charstack
 jmp getstrs
enter:
 mov al,0
 mov ah,0
 call charstack
 mov ah,2
 call charstack
 pop ax
 ret


;子程序:字符串入栈,出栈和显示
;参数:(ah)=功能号,0入栈,1出栈,2显示
;  ds:si指向字符栈空间,对于0号功能,(al)表示入栈字符
;  1号功能,(al)返回的字符,对于2号功能,(dh)(dl)字符串在屏幕显示的行列位置
charstack:
 jmp short charstart
 table dw charpush,charpop,charshow
 top  dw 0
charstart:
 push bx
 push dx
 push di
 push es
 cmp ah,2
 ja sret
 mov bl,ah
 mov bh,0
 add bx,bx
 jmp word ptr table[bx]
charpush:
 mov bx,top
 mov [si][bx],al
 inc top
 jmp sret
charpop:
 cmp top,0
 je sret
 dec top
 mov bx,top
 mov al,[si][bx]
 jmp sret
charshow:
 mov bx,0b800h
 mov es,bx
 mov al,160
 mov ah,0
 mul dh
 mov di,ax
 add dl,dl
 mov dh,0
 add di,dx
 mov bx,0
charshows:
 cmp bx,top
 jne noempty
 mov byte ptr es:[di],' '
 mov byte ptr es:[di+1],02h
 jmp sret
noempty:
 mov al,[si][bx]
 mov es:[di],al
 mov byte ptr es:[di+2],' '
 mov byte ptr es:[di+1],02h
 inc bx
 add di,2
 jmp charshows
sret:
 pop es
 pop di
 pop dx
 pop bx
 ret


;显示0结尾的字符串
;参数:dh=行号,dl=列号,cl=颜色,ds:si指向字符串首地址
sys_showstr:
 push ax
 push cx
 push dx
 push si
 push bp
 push es
 mov ax,0b800h
 mov es,ax
 mov al,80*2 ;80*2*行号
 mul dh
 mov dh,0
 add dx,dx ;列号*2
 add ax,dx
 mov bp,ax
showstr_s:
 mov ch,ds:[si]
 cmp ch,0
 je showstr_return
 mov es:[bp],ch
 inc bp
 mov es:[bp],cl
 inc bp
 inc si
 jmp short showstr_s
showstr_return:
 pop es
 pop bp
 pop si
 pop dx
 pop cx
 pop ax
 ret


;清屏
cls:
 mov ax,0b800h
 mov ds,ax
 mov bx,0
 mov cx,24*80*2
cls_s:
 mov byte ptr ds:[bx],0
 add bx,2
 loop cls_s
 mov bx,1
resetcol:
 mov byte ptr ds:[bx],07h
 add bx,2
 loop resetcol
 ret


syssg ends


;安装过程的第一行指令
end setup

四、测试过程

1、测试工具

测试使用Sun VirtualBox虚拟机和仿真虚拟软驱(http://download.youkuaiyun.com/source/2209509

a)安装仿真虚拟软驱以后,我的电脑中会模拟出一个本地磁盘A,可以像真的软盘一样对其进行读写等
b)在windows命令行下对程序进行编译连接,执行后引导代码写入到软盘中

c)新建一个虚拟机,使用软盘A引导,启动虚拟机

阅读下面的材料 : 开机后, CPU 自动进入到 FFF0:0 单元处执行,此处有一条跳转指令。 CPU 执行该指令后,转去执行 BIOS 中的硬件系统检测和初始化程序。 初始化程序将建立 BIOS 所支持的中断向量,即将 BIOS 提供的中断历程的入口地址登记在中断向量表中。 硬件系统检测和初始化完成后,调用 INT 19H 进行操作系统的引导。 如果设为从软盘启动操作系统,则 INT 19H 将主要完成一下工作: ( 1 )控制 0 号软驱,读取软盘 0 道 0 面 1 扇区的内容到 0 : 7C 00 。 ( 2 )将 CS:IP 指向 0 : 7C 00 。 软盘的 0 道 0 面 1 扇区中装有操作系统引导程序。 INT 19H 将其装到 0 : 7C 00 处后,设置 CPU 从 0 : 7C 00 开始执行此处的引导程序,操作系统被激活,控制计算机。 如果在 0 号软驱中没有软盘,或发生软盘 I/O 错误,则 INT 19H 将主要完成以下工作 ; (1) 读取硬盘 C 的 0 道 0 面 1 扇区的内容到 0 : 7C 00 ; (2) 将 CS:IP 指向 0 : 7C 00 。 这次课程设计的任务是编写一个可以自行启动计算机,不需要在现有操作系统环境中运行的程序。 改程序的功能如下: ( 1 )列出功能选项,让用户通过键盘进行选择,界面如下: 1 ) reset pc ; 重新启动计算机 2 ) Start system ; 引导现有的操作系统 3 ) Clock ; 进入时钟程序 4 ) Srt clock ; 设置时间 ( 2 )用户输入“ 1 ”后重新启动计算机。(提示:考虑 FFFF:0 ) ( 3 )用户输入“ 2 ” 后引导现有的操作系统。(提示:考虑硬盘 C 的 0 道 0 面 1 扇区) ( 4 )用户输入“ 3 ”后,执行动态现实当前日期,时间的程序。 现实格式如下:年 / 月 / 日 时:分:秒 进入此项功能后,一直动态现实当前的时间,在屏幕上将出现时间按秒变化的效果。(提示:循环读取 CMOS ) 当按下 F1 键后,改变现实颜色;按下 ESC 键后,返回到主选单。(提示:利用键盘中断) ( 5 )用户输入“ 4 ”后可更改当前的日期,时间,更改后返回到主选单。(提示:输入字符串) 下面给出的几点建议: ( 1 )在 DOS 下编写安装程序,在按转程序中包含任务程序; ( 2 )运行安装程序,将任务程序写到软盘上; ( 3 )若要任务程序可以在开机后自行执行,要将它写到软盘的 0 道 0 面 1 扇区上。如果程序长度大于 512B ,则需要用多个扇区存放,这种情况下,处于软盘 0 道 0 面 1 扇区中的程序就必须负责将其他扇区中的内容读入内存。 这个程序较为复杂,它用到了我们所学到的所有技术,需要进行仔细地分析和耐心地调试。这个程序对于我们的整个学习过程是具有总结性的,希望读者能够尽力完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值