前言:本文涉及两种代码,未安装虚拟机的参照第一种代码实现三四功能即可,
阅读下面的材料
开机后,CPU自动进入到FFFF:0单元处执行,此处有一条跳转指令。CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。
初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。
硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。
如果设为从软盘启动操作系统,则int 19h将主要完成以下工作。
控制0号软驱,读取软盘0道0面1扇区的内容到0:7c00;
将CS:IP指向0:7c00。
软盘的0道0面1扇区中装有操作系统引导程序。int 19h将其装到0:7c00处后,设置CPU从0:7c00开始执行此处的引导程序,操作系统被激活,控制计算机。
如果在0号软驱中没有软盘,或发生软盘I/O错误,则int 19h将主要完成以下工作。
读取硬盘C的0道0面1扇区的内容到0:7c00;
将CS:IP指向0:7c00。
该程序的功能如下:
(1)列出功能选项,让用户通过键盘进行选择,界面如下:
1)reset pc ;重新启动计算机
2)start system ;引导现有的操作系统
3)clock ;进入始终程序
4)set clock ;设置时间
(2)用户输入“1”后重新启动计算机(提示:考虑ffff:0单元)
(3)用户输入“2”后引导现有的操作系统(提示:考虑硬盘C的0道0面1扇区)
(4)用户输入“3”后,执行动态显示当前日期,时间的程序
显示格式如下:年/月/日/ 时/分/秒
进入此项功能后,一直动态显示当前的时间,在屏幕上将出现时间按秒变化的效果(提示:循环读取CMOS)。
当按下F1键后,改变显示颜色:按下ESC键后,返回到主选单(提示:利用键盘中断)。
(5)用户输入“4”后可更改当前的日期,时间,更改后返回到主选单(提示:输入字符串)
以下内容进实现 3 4号功能
assume cs:code,ds:data,ss:stack
data segment
BEGIN db 512 dup(0) ;因为一个扇区字节大小为512
BEGIN_BOOT db 512 dup(0) ;2号扇区 ds:[si]->es:[di]
db 512 dup(0) ;3
db 512 dup(0) ;4
data ends
stack segment
db 128 dup(0)
stack ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,128(0)
; mov bx,OFFSET Boot_end - OFFSET Boot
; call cpy_boot_toDiskA ;把上述代码复制到软盘中
call cpy_Boot
call sav_old_int9 ;因为要编写新的int9
mov bx,0
push bx
mov bx,7e00h
push bx
retf ;相当于执行 pop ip pop cs 返还到保存在0:7e00h中的 Boot代码
;ret 相当于 pop ip
mov ax,4c00h
int 21h
;int 19h 的内容: 将软盘0面0道1扇区(512)-》写入 0:7c00h cs:ip=0:7c00h
;将0面0到2扇区开始的 3个扇区中的内容 复制 到 0:7e00h cs:ip-07e00h
;先将 OFFSET Boot_end -OFFSET Boot 复制到 0面0道2扇区开始的3个扇区
;es:[bx]->复制到 1 2 3 4扇区
;==========================================================
Boot: jmp BOOT_START
;*******************************************************************
;*******************************************************************
;*******************************************************************
;数据区
OPTION_1 db '1) restart pc ',0 ;地址两个字节????
OPTION_2 db '2) start system ',0
OPTION_3 db '3) show clock ',0
OPTION_4 db '4) set clock ',0
ADDRESS_OPTION dw OFFSET OPTION_1 - OFFSET Boot + 7e00h ;ADDRESS_OPTION[0] 可以不加OFFSET的!!!
dw OFFSET OPTION_2 - OFFSET Boot + 7e00h
dw OFFSET OPTION_3 - OFFSET Boot + 7e00h
dw OFFSET OPTION_4 - OFFSET Boot + 7e00h
TIME_CMOS db 9,8,7,4,2,0 ;CMOS RAM中存储的时间信息 详情看实验16
TIME_STYLE db 'YY/MM/DD HH:MM:SS',0
STRING_STACK db 12 dup('0'),0 ;time_style 中12个字节型数据
;*******************************************************************
;*******************************************************************
;*******************************************************************
BOOT_START: call init_reg ;寄存器 对es ds赋值 es 0b800 ds 0
call clear_screen ;清屏
call show_option
jmp choose_option
mov ax,4c00h
int 21h
;==========================================================
choose_option: call clear_buff ;调用了int 16h 来处理键盘缓冲区中已经输入数据 详情看实验十七
mov ah,0 ;从数据缓存区中读取数据
int 16h ; ah 扫描码 al ASCII码
cmp al,'1'
je isChooseOne
cmp al,'2'
je isChooseTwo
cmp al,'3'
je isChooseThree
cmp al,'4'
je isChooseFour
jmp choose_option ;不用管ret
;==========================================================
isChooseOne: mov di,160*3
mov byte ptr es:[di],'1' ;es是0b800h 将写入的数据 显示到屏幕上
jmp choose_option
isChooseTwo: mov di,160*3
mov byte ptr es:[di],'2' ;es是0b800h
jmp choose_option
isChooseThree: mov di,160*3
mov byte ptr es:[di],'3' ;es是0b800h
call show_clock ;功能3:执行动态显示当前日期,时间的程序!!!
jmp BOOT_START
isChooseFour: mov di,160*3
mov byte ptr es:[di],'4' ;es是0b800h
call set_clock
jmp choose_option
;======================================================================
set_clock: call clear_string_stack
call show_string_stack
call get_string
call set_time ;修改cmos中的时间
ret
;=======================================================
set_time:
mov bx,OFFSET TIME_CMOS -Boot+7e00h
mov si,OFFSET STRING_STACK - OFFSET Boot + 7e00h
mov cx,6
setTime: mov dx,ds:[si] ;换位 bcd码
sub dh,30h ;ds:[si] ='12'
sub dl,30h ; dh ='2' dl= '1'
shl dl,1
shl dl,1
shl dl,1
shl dl,1
and dh,00001111b
or dl,dh
mov al,ds:[bx] ;传递给cmos
out 70h,al
mov al,dl
out 71h,al
add si,2
inc bx
loop setTime
ret
;=========================================================
get_string: mov si,OFFSET STRING_STACK -OFFSET Boot +7e00h
mov bx,0 ;当作栈顶
getString: call clear_buff
mov ah,0
int 1