assume cs:code
code segment
begin:
mov ax,cs
mov es,ax
mov bx,offset start
;---------------------------------------------从BX开始写入磁盘----------------------------------
mov dl,0
mov dh,0
mov ch,0
mov cl,1
mov al,19
mov ah,3
int 13h
;---------------------------------------------从BX开始写入磁盘结束----------------------------------
mov ax,4c00h
int 21h
;----------------------------------------------程序结束----------------------------------------------
;----------------------------------------------启动时从扇区中读取数据到内存--------------------------
start:
mov ax,0
mov es,ax
mov bx,7c00h
add bx,512
mov dl,0
mov dh,0
mov ch,0
mov cl,2
mov al,18
mov ah,2
int 13h
jmp start1
db 500 dup(?)
start1:
jmp menu
;menu-------------------------------------
menu: ;名称:菜单程序
;功能:显示一个菜单
;参数:无
;返回值:无
jmp short menustart
mn: db "1) reset pc",0 ;重启计算机
db "2) start system",0 ;引导现有操作系统
db "3) clock",0 ;进入时钟程序
db "4) set clock",0 ;设置时间
mt1: dw offset resetpc-offset start,offset startsys-offset start
dw offset clock-offset start,offset resetclock-offset start
menustart:
menus0:
mov ax,0b800h ;指向显示位置
mov es,ax
mov di,0
mov ax,cs ;指向数据位置
mov ds,ax
mov si,offset mn-offset start
add si,7c00h
mov cx,0
menus: ;循环显示以‘0’结尾的字符串
mov al,ds:[si]
cmp al,0
jz menuso
mov es:[di],al
inc si
add di,2
jmp menus
menuso:
inc cx
cmp cx,4
jz menuin
inc si
mov ax,160
mul cx
mov di,ax
jmp menus
;---------------------------------------menu显示完毕-----------------------------------------
menuin: ;1-9的扫描码为02-0A或者也可以比较ASCII码
mov ah,0
int 16h
cmp al,35h
jae menuin
cmp al,30h
jbe menuin
;---------------------------------------检测输入是否符合条件------------------------------
mov ah,al
sub ah,30h
menus2: nop
mjmp: mov bx,offset mt1-offset start ;调用相应的子程序
add bx,7c00h
dec ah ;扫描码比真实的大1
mov al,ah
add al,al
mov ah,0
add bx,ax
mov ax,ds:[bx]
add ax,7c00h ;找到真实的程序的地址
call ax
call cls
jmp menus0 ;返回显示菜单
menuover:
nop
;menu-------------------------------------
;resetpc------------------------------------------
resetpc: ;名称:resetpc
;功能:重启计算机
;参数:无
;返回值:无
push ax
push ds
push si
jmp short rpstart
rpstack:dw 0,0ffffh
rpstart:
mov ax,cs
mov ds,ax
mov si,offset rpstack-offset start
add si,7c00h
call dword ptr ds:[si]
pop si
pop ds
pop ax
ret
;resetpcend---------------------------------------
;==================================================================================
;startsys------------------------------------------------------
startsys: ;名称:STARTSYS
;功能:引导现有的操作系统
;参数:无
;返回值:无
call cls
push ax
push bx
push cx
push dx
push es
push si
jmp short startsys2
startsys1:
dw 7c00h,0
startsys2:
mov ax,0
mov es,ax
mov bx,7c00h
mov dl,80h ;现有的操作系统。
mov dh,0
mov ch,0
mov cl,1
mov al,1
mov ah,2
int 13h
mov si,offset startsys1-offset start
add si,7c00h
call dword ptr cs:[si] ;代码已经从硬盘上复制到7c00h处,指向该处,该处存放着0:7c00h
pop si
pop es
pop dx
pop cx
pop bx
pop ax
ret
data1 db 16 dup(0)
data2 db 9,8,7,4,2,0,' '
data3 db '/','/',' ',':',':',' '
;startsysend---------------------------------------------------
;=========================================================================================================
;clock-----------------------------------------
clock:
push ax
push di
push si
push dx
push cx
push es
;-----------------------------------------------------
push cs
pop ds
mov ax,0
mov es,ax
mov si,offset int9 -offset start + 7c00h
mov di,207h
mov cx,offset int9end-offset int9
cld
rep movsb
push es:[9*4]
pop es:[200h]
push es:[9*4+2]
pop es:[202h]
cli ;在改变int9中断的代码的地址时发生可屏蔽中断,所以先将F1置0
mov word ptr es:[9*4],207h
mov word ptr es:[9*4+2],0
sti
;------------------------------------------------------------
mov ax,0b800H
mov es,ax
clockok:
mov al,cs:[204]
mov byte ptr cs:[204],0
cmp al,01h
je okend
mov si,0
mov di,160*12+20*2
s1:
mov al,cs:[offset data2 - offset start + 7c00h+si]
out 70h,al
in al,71h
mov ah,al
mov cl,4
shr ah,cl
and al,00001111b ;将内存中的数据转换成两位数的字符
add ah,30h
add al,30h
mov byte ptr es:[10*160+4*2],ah
mov byte ptr es:[10*160+5*2],al
mov byte ptr es:[di],ah
mov byte ptr es:[di+2],al
mov al,cs:[offset data2 -offset start +7c00h +si+7]
mov byte ptr es:[di+4],al
mov al,cs:[offset data2 -offset start + 7c00h +si]
cmp al,0
je clockok
inc si
add di,6
jmp short s1
;------------------------------------------
int9:
push ax
push bx
push cx
push es
in al,60h
pushf
call dword ptr cs:[200h]
mov cs:[204],al
cmp al,3bh
jne int9ret
mov ax,0b800h
mov es,ax
mov bx,1
mov cx,80*25
mov al,0 ;颜色取时钟的秒钟,每发生一次int9,就会改变一次颜色,即每摁下一次F1就会改变一次颜色
out 70h,al
in al,71h
s2:
and byte ptr es:[bx],11111000b
and al,00000111b
or es:[bx],al
inc bx
inc bx
loop s2
int9ret:
pop es
pop cx
pop bx
pop ax
iret
int9end:nop
okend: pop es
pop cx
pop dx
pop si
pop di
pop ax
ret
;-----------------------------------------------------
cls: push ax
push di
push cx
mov cx,80*25
mov di,0
mov ax,0b800h
mov es,ax
s: mov es,ax
mov byte ptr es:[di],' '
inc di
inc di
loop s
pop cx
pop di
pop ax
ret
;=========================================================================================================
;resetclock------------------------------------------------
resetclock: ;名称:resetclock
;功能:修改CMOS中的时间
;参数:(输入,两位阿拉伯数字)
;返回值:无
push ax
push bx
push cx
push si
push di
push es
mov word ptr cs:[205],0
mov si,0
getstr: push ax
getstrs: mov ah,0
int 16h
cmp al,20h ;读取输入的ASCII码
jb nochar
mov ah,0 ;输入的是字符,则调用,ah传递的是功能号,即一个字符入栈
call charstack
mov ah,2 ;调用功能打印字符串
call charstack
jmp getstrs ;始终循环检测
nochar: cmp ah,0eh
je backspace
cmp ah,1ch
je enter
jmp getstrs
resetclockok:
pop es
pop di
pop si
pop cx
pop bx
pop ax
ret
backspace: mov ah,1
call charstack
call cls
mov ah,2
call charstack
jmp getstrs
enter: mov al,0
mov ah,0
call charstack
mov ah,2
call charstack
call changetime
pop ax
jmp resetclockok
charstack: jmp short charstart
table dw offset charpush - offset start +7c00h,offset charpop -offset start + 7c00h ,offset charshow -offset start +7c00h
;top dw 0
charstart: push bx
push dx
push di
push es
cmp ah,2 ;ah为传递过来的功能号参数
ja sret
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr cs:[offset table -offset start + 7c00h+bx]
charpush: mov bx,word ptr cs:[205]
mov cs:[offset data1 -offset start + 7c00h + si+bx],al
inc word ptr cs:[205]
jmp sret
charpop: cmp word ptr cs:[205],0
je sret
dec word ptr cs:[205]
mov bx,word ptr cs:[205]
mov al,cs:[offset data1 -offset start + 7c00h +si+bx]
jmp sret
charshow: mov bx,0b800h
mov es,bx
mov dh,12 ;初始化行列
mov dl,20
mov al,160
mov ah,0
mul dh ;dh,dl的输入问题
mov di,ax
add dl,dl
mov dh,0
add di,dx
mov bx,0
charshows: cmp bx,word ptr cs:[205]
jne noempty
mov byte ptr es:[si],' '
jmp sret
noempty: mov al,cs:[offset data1 - offset start + 7c00h +si+bx]
mov es:[di],al
inc bx
add di,2
jmp charshows
sret: pop es
pop di
pop dx
pop bx
ret
changetime:
push bx
push dx
push di
push es
; cmp bp,18 ;如果长度不等于18就退出,不改CMOS
; jne endenter
changclock:
mov si,0 ;指向开始的数据
; mov bp,0 ;指向开始的端口号
; mov bx,16
mov di,0
mov cx,6 ;年月日时分秒,共6次
changloop:
mov dx,70h
mov al,cs:[offset data2 -offset start +7c00h+di]
out dx,al ; 向70h写入了要访问的单元
mov dx,71h ;将端口71h预存到dx中,待会将向该端口写数据
mov ah,byte ptr cs:[offset data1 -offset start + 7c00h +si] ;得到年在al
mov al,byte ptr cs:[offset data1 -offset start + 7c00h +si+1]
sub ah,30h
sub al,30h
push cx ;保护cx
mov cl,4
shl ah,cl ;把年的十位移到高4位
pop cx
and al,00001111b ;把年的个位高4位清0
or al,ah ;把一个完整的年分合并到al一个字节中
out dx,al ;把年写入CMOS
inc si
inc si ;指向下一个时间单位
inc di ;指向下一个端口号
loop changloop
endenter: pop es
pop di
pop dx
pop bx
ret
;-----更改时间结束-----------------------------
;charstackend-----------------------------------------------
;==========================================================================================================
code ends
end begin