引导系统的设计与实现
任务
编写一个基于软盘的引导系统,该系统放置在软盘中,可以不需要操作系统就可以运行,基本功能如下:
(1
(2(3) 用户输入2后引导磁盘上现有的操作系统,即读取磁盘的引导扇区并
执行;
(4) 用户输入3后,将显示实时时钟,格式为“年/月/日 时:分:秒”,同
时按下F1键改变时钟的颜色,按ESC键返回主菜单;
(5) 用户输入4后,可以修改时间,按回车键确定修改并返回主菜单。
总体设计思路
PC机开机后,CPU被设定为执行FFFF:0单元处的指令,此处有一条跳转指令。CPU执行该指令后,转去执行BIOS中的硬件系统测试和初始化程序。 初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。
硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。 如果设为从软盘启动操作系统,则int 19h将主要完成以下工作:
(1) 控制0号软驱,读取软盘0道0面1扇区的内容到 0:7C00 (2) 将CS:IP指向0:7C00
软盘的0道0面1扇区中装有操作系统引导程序。int 19h将其装入到内存0:7C00处后,设置CPU从0:7C00开始执行此处的引导程序,操作系统被激活,控制计算机。
如果在0号软驱中没有软盘,或发生软盘I/O错误,则int 19h将主要完成以下工作:
(1) 读取硬盘C的0道0面1扇区的内容到0:7C00
(2) 将CS:IP指向0:7C00
由以上描述可知,若我们想要控制引导过程,只需:
(1) 编写程序
(2) 将该程序代码写入软盘或硬盘C的0道0面1扇区。
因为以上工作会破坏软盘或硬盘原有数据,因此本次实验,我们选择软盘存放我们自己的启动程序。
实验结果
1、将虚拟机设置为优先从软驱启动,启动虚拟机,此时会进入界面,界面显示为 :
2、按下数字键 “1”重启机器: (与1中图相同)
3、按下数字键“2”,进入虚拟机的xp系统:
4、重启虚拟机观察时钟显示和设置等功能:
重启虚拟机后按下数字键“3”,显示时间:
按下“F1
”键,改变显示颜色:
按下“
Esc”键,返回初始界面:
按下数字键“4”
,进入设置时间界面设置时间:
返回初始界面后按“3”键查看更改后的时间:
总结
通过此次的课程设计我熟悉了虚拟机的环境配置,加深理解计算机中断的概念与中断服务程序的执行过程。对汇编语言及计算机硬件有了更多的了解。编写代码期间出现很多问题,例如由于子程序的内存地址没有安排合理导致代码覆盖。汇编语言在界面的显示及美化、与用户的有效互动、算法编写及可读性等方面与高级语言相比差距很大,当面对较多的变量时,如何有效使用有限的寄存器也是需要慎重考虑的问题。此外,寄存器的合理使用、编写中断程序时中断现场的保存与恢复及其在内存地址中的合理安排、数据在内存中的位置及其读取/写入、子程序在内存中地址的合理安排以防代码被覆盖、屏幕刷新、修改日期数据时对数据输入范围的判断、如何显示界面、与用户的互动等都是一些注意的细节。
附录
assumecs:setup
setup segment
assumecs:setup
start:
movax,init
moves,ax
mov bx,0
mov al,1
mov ch,0
mov cl,1
mov dl,0
mov dh,0
mov ah,3
int 13h
movax,code
moves,ax
mov al,15
mov cl,2
mov ah,3
int 13h
mov ax,4c00h
int 21h
setup ends
init segment
assumecs:init
start1:
call load
mov ax,0200h
push ax
mov ax,0
push ax
retf
load:
mov ax,0200h
mov bx,0
mov al,15
mov ch,0
mov cl,2
mov dl,0
mov dh,0
mov ah,2
int 13h
ret
init ends
code segment
assumecs:code
menu:
jmp near ptrmenushow
menudatadw offset md1,offset md2,offset md3,offset md4 md1db "1) reset pc",0
md2db "2) start system",0
md3db "3) clock",0
md4db "4) set clock",0
systabledwsys_restart,sys_disksys,sys_showclock,sys_setclock menushow:
mov dh,5
mov dl,30
mov bp,0
movax,cs
movds,ax
mov cx,4
menushow_s:
push cx
movsi,menudata[bp]
mov cl,02h
callsys_showstr
add bp,2
add dh,2
pop cx
loopmenushow_s
sys_input:
mov ah,0
int 16h
movbl,al
mov al,30h
subbl,al
sub bl,1
cmp bx,0
jb cycle
cmp bx,3
ja cycle
addbx,bx
call word ptrsystable[bx]
cycle:
jmp short sys_input
sys_restart:
mov ax,0ffffh push ax
mov ax,0h
push ax
retf
sys_disksys:
callcls
mov ax,0h
moves,ax
mov bx,7c00h
mov al,1
mov ch,0
mov cl,1
mov dl,80h
mov dh,0
mov ah,2
int 13h
mov ax,0h
push ax
mov ax,7c00h push ax
retf
sys_showclock:
callcls
jmp short clockread
clockdata:
clockstrdw offset cl1,offset cl2,offset cl3
clockcolordb 02h
cl1db '00/00/00 00:00:00',0
cl2db 'press ESC return menu!',0
cl3db 'press F1 change color!',0
cltabledb 9,8,7,4,2,0
clockread:
mov si,0
mov di,0
mov cx,6
clockread_s:
push cx
moval,cltable[di]
out 70h,al
inal,71h
movah,al
mov cl,4
shrah,cl
and al,00001111b
add ah,30h
add al,30h
mov byte ptr cl1[si],ah
mov byte ptr cl1[si+1],al
add si,3
inc di
pop cx
loopclockread_s
clockprint:
mov dh,6
mov dl,30
mov bp,0
movax,cs
movds,ax
mov cx,3
clockprint_s:
push cx
movsi,clockstr[bp]
movcl,clockcolor[0]
callsys_showstr
add dh,2
pop cx
loopclockprint_s
mov ah,1
int 16h
cmp al,1bh
jeclockreturn
cmp ah,3bh
jechangecolor
jmp short clockread
clockreturn:
callcls
mov ah,0
int 16h
jmp near ptr menu
changecolor:
incclockcolor
mov ah,0
int 16h
jmp near ptrclockread
sys_setclock:
jmp short setclock
setclockdatadb 'Please input time like "yy/mm/dd hh:mm:ss"',0 setsuccessdb 'Set clock successful! Press any key return...',0 setclock:
callcls
mov dh,6
mov dl,20
mov cl,02h
movax,cs
movds,ax
movsi,offsetsetclockdata
callsys_showstr
callgetstr
callsettime
mov dh,10
mov dl,20
mov cl,02h
movax,cs
movds,ax
movsi,offsetsetsuccess
callsys_showstr
int 16h
callcls
jmp near ptr menu
settime:
jmp short seting
settabledb 9,8,7,4,2,0
seting:
mov bx,0
mov cx,6
settime_s:
movdh,ds:[si]
incsi
movdl,ds:[si]
add si,2
mov al,30h
subdl,al
subdh,al
shl dh,1
shl dh,1
shl dh,1
shl dh,1
ordl,dh
moval,settable[bx]
out 70h,al
moval,dl
out 71h,al
incbx
loopsettime_s
ret
getstr:
push ax
getstrs:
mov ah,0
int 16h
cmp al,20h
jbnochar
mov ah,0
callcharstack
mov ah,2
mov dh,8
mov dl,25
jmpgetstrs
nochar:
cmp ah,0eh
je backspace
cmp ah,1ch
je enter0
jmpgetstrs
backspace:
mov ah,1
callcharstack
mov ah,2
callcharstack
jmpgetstrs
enter0:
mov al,0
mov ah,0
callcharstack
mov ah,2
callcharstack
pop ax
ret
charstack:
jmp short charstart
tabledwcharpush,charpop,charshow top dw 0
charstart:
pushbx
push dx
push di
pushes
cmp ah,2
jasret
movbl,ah
mov bh,0
addbx,bx
jmp word ptr table[bx]
charpush:
movbx,top
mov [si][bx],al
inc top
jmpsret
charpop:
jesret
dec top
movbx,top
mov al,[si][bx] jmpsret
charshow:
mov bx,0b800h moves,bx
mov al,160
mov ah,0
mul dh
movdi,ax
adddl,dl
mov dh,0
adddi,dx
mov bx,0
charshows:
cmpbx,top
jnenoempty
mov byte ptres:[di],' ' mov byte ptres:[di+1],02h jmpsret
noempty:
mov al,[si][bx] moves:[di],al
mov byte ptres:[di+2],' ' mov byte ptres:[di+1],02h incbx
add di,2
jmpcharshows sret:
popes
pop di
pop dx
popbx
ret
sys_showstr:
push ax
push cx
push dx
pushsi
pushbp
mov ax,0b800h moves,ax
mov al,80*2 mul dh
mov dh,0
adddx,dx
addax,dx
movbp,ax
showstr_s:
movch,ds:[si] cmp ch,0
jeshowstr_return moves:[bp],ch incbp
moves:[bp],cl incbp
incsi
jmp short showstr_s showstr_return: popes
popbp
popsi
pop dx
pop cx
pop ax
ret
cls:
mov ax,0b800h movds,ax
mov bx,0
mov cx,24*80*2 cls_s:
mov byte ptr ds:[bx],0 add bx,2
loopcls_s
mov bx,1
resetcol:
mov byte ptr ds:[bx],07h add bx,2
loopresetcol
ret
end start
引导系统的设计与实现
任务
编写一个基于软盘的引导系统,该系统放置在软盘中,可以不需要操作系统就可以运行,基本功能如下:
(1
(2(3) 用户输入2后引导磁盘上现有的操作系统,即读取磁盘的引导扇区并
执行;
(4) 用户输入3后,将显示实时时钟,格式为“年/月/日 时:分:秒”,同
时按下F1键改变时钟的颜色,按ESC键返回主菜单;
(5) 用户输入4后,可以修改时间,按回车键确定修改并返回主菜单。
总体设计思路
PC机开机后,CPU被设定为执行FFFF:0单元处的指令,此处有一条跳转指令。CPU执行该指令后,转去执行BIOS中的硬件系统测试和初始化程序。 初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。
硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。 如果设为从软盘启动操作系统,则int 19h将主要完成以下工作:
(1) 控制0号软驱,读取软盘0道0面1扇区的内容到 0:7C00 (2) 将CS:IP指向0:7C00
软盘的0道0面1扇区中装有操作系统引导程序。int 19h将其装入到内存0:7C00处后,设置CPU从0:7C00开始执行此处的引导程序,操作系统被激活,控制计算机。
如果在0号软驱中没有软盘,或发生软盘I/O错误,则int 19h将主要完成以下工作:
(1) 读取硬盘C的0道0面1扇区的内容到0:7C00
(2) 将CS:IP指向0:7C00
由以上描述可知,若我们想要控制引导过程,只需:
(1) 编写程序
(2) 将该程序代码写入软盘或硬盘C的0道0面1扇区。
因为以上工作会破坏软盘或硬盘原有数据,因此本次实验,我们选择软盘存放我们自己的启动程序。
实验结果
1、将虚拟机设置为优先从软驱启动,启动虚拟机,此时会进入界面,界面显示为 :
2、按下数字键 “1”重启机器: (与1中图相同)
3、按下数字键“2”,进入虚拟机的xp系统:
4、重启虚拟机观察时钟显示和设置等功能:
重启虚拟机后按下数字键“3”,显示时间:
按下“F1
”键,改变显示颜色:
按下“
Esc”键,返回初始界面:
按下数字键“4”
,进入设置时间界面设置时间:
返回初始界面后按“3”键查看更改后的时间:
总结
通过此次的课程设计我熟悉了虚拟机的环境配置,加深理解计算机中断的概念与中断服务程序的执行过程。对汇编语言及计算机硬件有了更多的了解。编写代码期间出现很多问题,例如由于子程序的内存地址没有安排合理导致代码覆盖。汇编语言在界面的显示及美化、与用户的有效互动、算法编写及可读性等方面与高级语言相比差距很大,当面对较多的变量时,如何有效使用有限的寄存器也是需要慎重考虑的问题。此外,寄存器的合理使用、编写中断程序时中断现场的保存与恢复及其在内存地址中的合理安排、数据在内存中的位置及其读取/写入、子程序在内存中地址的合理安排以防代码被覆盖、屏幕刷新、修改日期数据时对数据输入范围的判断、如何显示界面、与用户的互动等都是一些注意的细节。
附录
assumecs:setup
setup segment
assumecs:setup
start:
movax,init
moves,ax
mov bx,0
mov al,1
mov ch,0
mov cl,1
mov dl,0
mov dh,0
mov ah,3
int 13h
movax,code
moves,ax
mov al,15
mov cl,2
mov ah,3
int 13h
mov ax,4c00h
int 21h
setup ends
init segment
assumecs:init
start1:
call load
mov ax,0200h
push ax
mov ax,0
push ax
retf
load:
mov ax,0200h
mov bx,0
mov al,15
mov ch,0
mov cl,2
mov dl,0
mov dh,0
mov ah,2
int 13h
ret
init ends
code segment
assumecs:code
menu:
jmp near ptrmenushow
menudatadw offset md1,offset md2,offset md3,offset md4 md1db "1) reset pc",0
md2db "2) start system",0
md3db "3) clock",0
md4db "4) set clock",0
systabledwsys_restart,sys_disksys,sys_showclock,sys_setclock menushow:
mov dh,5
mov dl,30
mov bp,0
movax,cs
movds,ax
mov cx,4
menushow_s:
push cx
movsi,menudata[bp]
mov cl,02h
callsys_showstr
add bp,2
add dh,2
pop cx
loopmenushow_s
sys_input:
mov ah,0
int 16h
movbl,al
mov al,30h
subbl,al
sub bl,1
cmp bx,0
jb cycle
cmp bx,3
ja cycle
addbx,bx
call word ptrsystable[bx]
cycle:
jmp short sys_input
sys_restart:
mov ax,0ffffh push ax
mov ax,0h
push ax
retf
sys_disksys:
callcls
mov ax,0h
moves,ax
mov bx,7c00h
mov al,1
mov ch,0
mov cl,1
mov dl,80h
mov dh,0
mov ah,2
int 13h
mov ax,0h
push ax
mov ax,7c00h push ax
retf
sys_showclock:
callcls
jmp short clockread
clockdata:
clockstrdw offset cl1,offset cl2,offset cl3
clockcolordb 02h
cl1db '00/00/00 00:00:00',0
cl2db 'press ESC return menu!',0
cl3db 'press F1 change color!',0
cltabledb 9,8,7,4,2,0
clockread:
mov si,0
mov di,0
mov cx,6
clockread_s:
push cx
moval,cltable[di]
out 70h,al
inal,71h
movah,al
mov cl,4
shrah,cl
and al,00001111b
add ah,30h
add al,30h
mov byte ptr cl1[si],ah
mov byte ptr cl1[si+1],al
add si,3
inc di
pop cx
loopclockread_s
clockprint:
mov dh,6
mov dl,30
mov bp,0
movax,cs
movds,ax
mov cx,3
clockprint_s:
push cx
movsi,clockstr[bp]
movcl,clockcolor[0]
callsys_showstr
add dh,2
pop cx
loopclockprint_s
mov ah,1
int 16h
cmp al,1bh
jeclockreturn
cmp ah,3bh
jechangecolor
jmp short clockread
clockreturn:
callcls
mov ah,0
int 16h
jmp near ptr menu
changecolor:
incclockcolor
mov ah,0
int 16h
jmp near ptrclockread
sys_setclock:
jmp short setclock
setclockdatadb 'Please input time like "yy/mm/dd hh:mm:ss"',0 setsuccessdb 'Set clock successful! Press any key return...',0 setclock:
callcls
mov dh,6
mov dl,20
mov cl,02h
movax,cs
movds,ax
movsi,offsetsetclockdata
callsys_showstr
callgetstr
callsettime
mov dh,10
mov dl,20
mov cl,02h
movax,cs
movds,ax
movsi,offsetsetsuccess
callsys_showstr
int 16h
callcls
jmp near ptr menu
settime:
jmp short seting
settabledb 9,8,7,4,2,0
seting:
mov bx,0
mov cx,6
settime_s:
movdh,ds:[si]
incsi
movdl,ds:[si]
add si,2
mov al,30h
subdl,al
subdh,al
shl dh,1
shl dh,1
shl dh,1
shl dh,1
ordl,dh
moval,settable[bx]
out 70h,al
moval,dl
out 71h,al
incbx
loopsettime_s
ret
getstr:
push ax
getstrs:
mov ah,0
int 16h
cmp al,20h
jbnochar
mov ah,0
callcharstack
mov ah,2
mov dh,8
mov dl,25
jmpgetstrs
nochar:
cmp ah,0eh
je backspace
cmp ah,1ch
je enter0
jmpgetstrs
backspace:
mov ah,1
callcharstack
mov ah,2
callcharstack
jmpgetstrs
enter0:
mov al,0
mov ah,0
callcharstack
mov ah,2
callcharstack
pop ax
ret
charstack:
jmp short charstart
tabledwcharpush,charpop,charshow top dw 0
charstart:
pushbx
push dx
push di
pushes
cmp ah,2
jasret
movbl,ah
mov bh,0
addbx,bx
jmp word ptr table[bx]
charpush:
movbx,top
mov [si][bx],al
inc top
jmpsret
charpop:
jesret
dec top
movbx,top
mov al,[si][bx] jmpsret
charshow:
mov bx,0b800h moves,bx
mov al,160
mov ah,0
mul dh
movdi,ax
adddl,dl
mov dh,0
adddi,dx
mov bx,0
charshows:
cmpbx,top
jnenoempty
mov byte ptres:[di],' ' mov byte ptres:[di+1],02h jmpsret
noempty:
mov al,[si][bx] moves:[di],al
mov byte ptres:[di+2],' ' mov byte ptres:[di+1],02h incbx
add di,2
jmpcharshows sret:
popes
pop di
pop dx
popbx
ret
sys_showstr:
push ax
push cx
push dx
pushsi
pushbp
mov ax,0b800h moves,ax
mov al,80*2 mul dh
mov dh,0
adddx,dx
addax,dx
movbp,ax
showstr_s:
movch,ds:[si] cmp ch,0
jeshowstr_return moves:[bp],ch incbp
moves:[bp],cl incbp
incsi
jmp short showstr_s showstr_return: popes
popbp
popsi
pop dx
pop cx
pop ax
ret
cls:
mov ax,0b800h movds,ax
mov bx,0
mov cx,24*80*2 cls_s:
mov byte ptr ds:[bx],0 add bx,2
loopcls_s
mov bx,1
resetcol:
mov byte ptr ds:[bx],07h add bx,2
loopresetcol
ret
end start