将操作系统写入软盘,并以软盘启动的方式开启操作系统。实现重启计算机,引导现有操作系统,显示及设置时钟(即所谓的操作系统)。调试阶段在vmware+msdos下完成。
实验提示:
1、为了方便我们在虚拟机下进行实验,我选择vmware;
2、为了调试方便我们安装MS-DOS 7.10(自带DEBUG),下载地址:http://www.onlinedown.net/soft/2465.htm;
3、下载并安装masm6.11(包括masm及link),下载地址:http://ishare.iask.sina.com.cn/f/11460493.html?from=like;
4、向虚拟主机内的DOS传文件可以选择光盘和软盘两种。可以用UltraISO制作。下载地址:http://www.crsky.com/soft/1134.html;
5、为了选择软盘启动我们可以让虚拟机延时进入操作系统。打开MS-DOS.vmx,加入bios.bootDelay = "10000"
效果图:
以下是全部代码:
assume cs:code
code segment
;安装程序
start: mov ax,cs
mov es,ax
mov bx,offset sec1
mov ah,3
mov al,9
mov ch,0
mov cl,1
mov dl,0
mov dh,0
int 13h
mov ax,4c00h
int 21h
;第一扇区
;读第二扇区到0:7e00h
sec1: ;mov ax,0
;mov es,ax
;mov bx,7e00h
mov ax,1000h
mov es,ax
mov bx,7e00h
mov ah,2
mov al,9
mov ch,0
mov cl,2
mov dl,0
mov dh,0
int 13h
;跳转到0:7e00h
;mov ax,0
;push ax
;mov ax,7e00h
;push ax
;retf
mov ax,1000h
push ax
mov ax,7e00h
push ax
retf
db 512-($-sec1)-2 dup(0)
dw 0aa55h
;第二扇区
sec2: jmp sec2start
intro:
db '*****************************************************'
db '*** press 1 to restart system ***'
db '*** press 2 to start current system ***'
db '*** press 3 to start clock ***'
db '*** press 4 to setting clock ***'
db '*****************************************************'
err_not_support_op:
db 'not support operation!'
opt:
db 0 ;接收输入的变量
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;newline,showstr,get_str的使用方法请见: ;;
;;http://blog.csdn.net/xiaodao1986/article/details/6724050 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;换行(当前行的下一行)
newline:push ax
push bx
push cx
push dx
mov ah,03h
mov bh,0
int 10h
cmp dh,24
jb incrow
mov ah,06h
mov al,1
mov bh,07h
mov ch,0
mov cl,0
mov dh,24
mov dl,80
int 10h
jmp changerow
incrow: inc dh
changerow:
mov ah,2
mov bh,0
mov dl,0
int 10h
nrtn: pop dx
pop cx
pop bx
pop ax
ret
;在当前行显示字符串(80*25)
;@param ds:si - 变量地址
;@param cx - 变量长度
showstr:push ax
push bx
push cx
push dx
push es
push di
push si
push cx
mov ah,03h
mov bh,0
int 10h
pop cx
mov ax,0b800h
mov es,ax
mov al,160
mul dh
mov di,ax
mov bx,0
mov dl,0
s: mov al,ds:[si]
cmp al,0
jne _if
mov byte ptr es:[bx+di],' '
jmp short _endif
_if: mov byte ptr es:[bx+di],al
inc dl
_endif: inc si
add bx,2
loop s
mov ah,2
mov bh,0
int 10h
pop si
pop di
pop es
pop dx
pop cx
pop bx
pop ax
ret
;获取用户输入
;@param ds:si - 变量地址
;@param cx - 变量长度
get_str:push ax
push bx
push cx
push dx
push si
mov bx,si
mov dx,0
push cx
push si
s1: mov byte ptr ds:[si],0
inc si
loop s1
pop si
pop cx
get: mov ah,0
int 16h
cmp ah,1ch
je gtrn
cmp ah,0eh
je delchar
cmp dx,cx
jnb get
mov byte ptr ds:[si],al
inc si
inc dx
jmp gshowstr
delchar:cmp si,bx
jna get
dec si
dec dx
mov byte ptr ds:[si],0
jmp gshowstr
gshowstr:
push si
mov si,bx
call showstr
pop si
jmp get
gtrn: call newline
pop si
pop dx
pop cx
pop bx
pop ax
ret
;子程序一:重启计算机
resetpc:mov ax,0ffffh
push ax
mov ax,0
push ax
retf
;子程序二:引导现有系统
startsys:
mov ax,0
mov es,ax
mov bx,7c00h
mov ah,2
mov al,1
mov ch,0
mov cl,1
mov dh,0
mov dl,80h
int 13h
mov ax,0
push ax
mov ax,7c00h
push ax
retf
;子程序三:时钟程序
;时钟程序,按ESC退出
;@param cl - 行
;@param ch - 列
clock: jmp clockstart
table:
db 9,8,7,4,2,0
timestr:
db 0,0,'/',0,0,'/',0,0,' ',0,0,':',0,0,':',0,0
clockstart:
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
call {1}3
ofst: pop ax ;ip
mov bx,ofst - table
sub ax,bx
mov si,ax
mov ax,cs
mov ds,ax
mov di,si
add di,6
for_clock:
push si
push di
push cx
mov cl,4
mov ch,0
for_clock2:
mov al,ds:[si]
mov dx,70h
out dx,al
in al,71h
mov ah,al
shr ah,cl
add ah,30h
mov byte ptr ds:[di],ah
inc di
and al,00001111b
add al,30h
mov byte ptr ds:[di],al
add di,2
inc si
inc ch
cmp ch,6
je show_time
jmp for_clock2
show_time:
pop cx
pop di
pop si
push si
push di
push cx
mov ax,0b800h
mov es,ax
mov si,di
mov al,160
mul cl
mov di,ax
mov al,2
mul ch
add di,ax
mov cx,17
for_getchr:
mov al,ds:[si]
mov ah,07h
mov es:[di],ax
inc si
add di,2
loop for_getchr
pop cx
pop di
pop si
check: in al,60h
cmp al,01h
je clockrtn
jmp for_clock
clockrtn:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
;子程序四:设置时钟
setclock:
jmp scstart
var_sc_time:
db 17 dup(0)
sc_tip:
db 'set time with format $/$/$ $:$:$,eg.11/09/05 11:14:20'
sc_table:
db 9,8,7,4,2,0
scstart:push ax
push ds
push bx
push si
push di
push cx
push dx
;动态设置ds,si,di
call scofst
scofst: pop ax ;ip
mov bx,scofst - var_sc_time
sub ax,bx
mov si,ax
mov di,ax
mov ax,cs
mov ds,ax
;显示提示字符串
mov cx,sc_table - sc_tip
add si,sc_tip - var_sc_time
call showstr
call newline
;获取用户输入
mov si,di
mov cx,sc_tip - var_sc_time
call get_str
;处理用户输入
add si,sc_table - var_sc_time
mov cx,6
for_sc: mov word ptr dx,ds:[di]
mov al,ds:[si]
push cx
sub dl,30h
mov cl,4
shl dl,cl
sub dh,30h
or dh,dl
out 70h,al
mov al,dh
out 71h,al
pop cx
inc si
add di,3
loop for_sc
pop dx
pop cx
pop di
pop si
pop bx
pop ds
pop ax
ret
;主程序
sec2start:
;mov ax,0
mov ax,1000h
mov ds,ax
mov cx,53
mov si,7e00h + offset intro - offset sec2
mov bl,6
;显示操作说明
for_intro:
call showstr
call newline
add si,53
dec bl
cmp bl,0
je end_for_intro
jmp for_intro
end_for_intro:
;获取用户输入
mov si,7e00h + offset opt - offset sec2
mov cx,1
call get_str
;=1,重启计算机
cmp byte ptr ds:[si],31h
je resetpc
;=2,引导现有系统
cmp byte ptr ds:[si],32h
je startsys
;=3,进入时钟程序
cmp byte ptr ds:[si],33h
je call_clock
;=4,设置时钟
cmp byte ptr ds:[si],34h
je call_setclock
;不支持用户输入的操作,显示错误消息,并等待用户的下一个输入
mov si,7e00h + offset err_not_support_op - offset sec2
mov cx,22
call showstr
call newline
jmp end_for_intro
call_clock:
mov cl,8
mov ch,60
call clock
jmp end_for_intro
call_setclock:
call setclock
jmp end_for_intro
code ends
end start