assume cs:code
code segment
;===============================================================
;功能:将代码写入0面0道1扇区
;入口参数:
; (ah)=int 13h的功能号(2表示读扇区,3表示写扇区)
; (al)=写入的扇区数
; (ch)=磁道号
; (cl)=扇区号
; (dh)=磁头号(面号)
; (dl)=驱动器号 软区从0开始,0:软驱A,1:软驱B
; 硬盘从80h开始,80h:硬盘C,81h:硬盘D
; es:bx指向将写入磁盘的数据或指向接收从扇区读入数据的内存区
;返回参数:
; 操作成功:(ah)=0,(al)=写入的扇区数
; 操作失败:(ah)=出错代码
;===============================================================
start:
mov ax,floppyend-floppy
mov dx,0
mov bx,512
div bx ;商ax为所需的扇区数
inc al ;写入的扇区数(为余数加扇区)
push cs
pop es
mov bx,offset floppy ;es:bx指向要被写入的内存单元
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov dl,0 ;驱动器号,软盘A
mov dh,0 ;磁头号(面号)
mov ah,3 ;int 13h的功能号(3表示写扇区)
int 13h ;将代码写入0面0道1扇区
mov ax,4c00h
int 21h
floppy:
jmp read
;===============================================================
;直接定址表
;===============================================================
table dw function1-floppy,function2-floppy
dw function3-floppy,function4-floppy
menu db '***main Menu***',0
db '1) reset pc ',0
db '2) start system',0
db '3) clock ',0
db '4) set clock ',0
db 'Please Choose: ',0
time db 'YY/MM/DD hh:mm:ss',0
cmos db 9,8,7,4,2,0
hint db 'press F1 to change the color, press Esc to return',0
hint1 db 'Please input: YY/MM/DD hh:mm:ss',0
char db ' / / : : ',0
;===============================================================
;功能:将0面0道2扇区的内容写入0:7e00h
;入口参数:
; (ah)=int 13h的功能号(2表示读扇区)
; (al)=写入的扇区数
; (ch)=磁道号
; (cl)=扇区号
; (dh)=磁头号(面号)
; (dl)=驱动器号 软区从0开始,0:软驱A,1:软区B
; 硬盘从80h开始,80h:硬盘C,81h:硬盘D
; es:bx指向将写入磁盘的数据
;返回参数:
; 操作成功:(ah)=0,(al)=写入的扇区数
; 操作失败:(ah)=出错代码
;===============================================================
read:
mov ax,floppyend-floppy
mov dx,0
mov bx,512
div bx ;商ax为所需的扇区数
inc al
mov bx,0
mov es,bx
mov bx,7e00h ;es:bx指向要读入的内存单元
mov ch,0 ;磁道号
mov cl,2 ;扇区号
mov dl,0 ;驱动器号
mov dh,0 ;磁头号(面号)
mov ah,2 ;int 13h的功能号(2表示读扇区)
int 13h ;读取0面0道2扇区的内容到0:7e00h处
;(第二扇区从512/200h开始)
mov ax,7c0h
push ax ;push cs
mov ax,showmenu-floppy
push ax ;push ip
retf ;jmp showmenu
;***************************************************************
;显示主菜单,调用show_str、clean子程序
;***************************************************************
showmenu:
call clean ;清屏
push cs
pop ds
mov si,menu-floppy
mov dh,8
mov dl,30
mov cx,6
showmenu0:
push cx
mov cl,2
call show_str
add si,16
inc dh
pop cx
loop showmenu0
;===============================================================
;接收键盘输入,跳转相应功能程序段
;调用BIOS用来提供读取键盘缓冲区功能的中断例程int 16h,
;将读取的扫描码送入ah,ASCII码送入al
;===============================================================
go: mov ax,0
int 16h
cmp al,'1'
jb showmenu
cmp al,'4'
ja showmenu
sub al,31h
mov bl,al
mov bh,0
add bx,bx
add bx,3 ;计算相应子程序在table中的位移
call word ptr cs:[bx]
jmp showmenu
;***************************************************************
;功能1:重新启动计算机
;***************************************************************
function1:
mov ax,0ffffh
push ax
mov ax,0
push ax
retf ;jmp ffff:0
;***************************************************************
;功能3:进入时钟程序
;***************************************************************
function3:
push ax
push bx
push cx
push dx
push si
push ds
push es
call clean ;清屏
mov dh,0 ;行号
mov dl,0 ;列号
mov cl,2
mov si,offset hint-floppy
call show_str ;显示提示信息
;===============================================================
;名称:clock
;功能:动态显示当前日期、时间
;===============================================================
mov cx,2 ;显示颜色
clock: mov bx,offset cmos-floppy
mov si,offset time-floppy
push cx
mov cx,6
clock0: push cx
mov al,[bx]
out 70h,al ;将al送入地址端口70h
in al,71h ;从数据端口71h处读出单元内容
mov ah,al
mov cl,4
shr al,cl ;右移4位
and ah,0fh ;al分成两个表示BCD码值的数据
add ax,3030h ;BCD码+30h=10进制数对应的ASCII码
mov [si],ax ;ASCII码写入time段
inc bx
add si,3
pop cx
loop clock0
;---------------------------------------------------------------
;按下F1键后,改变显示颜色
;按下Esc键后,返回主菜单,其他键照常处理
;---------------------------------------------------------------
mov al,0
in al,60h
pop cx ;显示颜色
cmp al,3bh ;和F1的扫描码3bh比较
je colour
cmp al,1 ;和esc的扫描码01h比较
je clockend
jmp show_clock
col_1: mov cx,1 ;cl∈[1,7],0为黑色
jmp show_clock
colour: cmp cx,7
je col_1
inc cx
show_clock:
mov dh,12 ;行号
mov dl,30 ;列号
mov si,offset time-floppy
call show_str
jmp clock ;循环显示CMOS
clockend:
pop es
pop ds
pop si
pop dx
pop cx
pop bx
pop ax
ret
;***************************************************************
;功能4:设置时间
;***************************************************************
function4:
push ax
push bx
push cx
push dx
push si
call clean
mov dh,8 ;行号
mov dl,30 ;列号
mov cl,2
mov si,offset hint1-floppy
call show_str ;显示提示信息
add dh,1 ;行号
add dl,14 ;列号
mov si,offset char-floppy ;ds:si指向字符栈空间
call show_str ;显示输入格式
mov di,0
call getstrs
call witein
call cleanchar
pop si
pop dx
pop cx
pop bx
pop ax
ret
;===============================================================
;清除char内输入数据,还原环境
;===============================================================
cleanchar:
push cx
cleanchar1:
mov cx,di
jcxz cleanchar2
call charpop
jmp cleanchar1
cleanchar2:
pop cx
ret
;===============================================================
;ASCII=>BCD,写入CMOS
;===============================================================
witein:
push si
mov cx,6
mov bx,offset cmos-floppy
wite: push cx
mov al,[bx]
out 70h,al ;将al送入地址端口70h
mov ax,[si]
sub ah,30h ;10进制数对应的ASCII码-30h=BCD码
sub al,30h
mov cl,4
shl al,cl ;左移4位
add al,ah ;al为8位BCD码
out 71h,al ;从数据端口71h处写入单元内容
add si,3
inc bx
pop cx
loop wite
pop si
ret
;===============================================================
;子程序:接收数字输入
;参数说明:di=char栈顶(字符地址、个数记录器)
;===============================================================
getstrs:
push ax
push bx
getstr: mov ax,0
int 16h
cmp ah,0eh ;退格键的扫描码
je backspace
cmp ah,1ch ;Enter键的扫描码
je enter1
cmp al,'0'
jb getstr
cmp al,'9'
ja getstr
cmp di,16 ;限制输入个数
ja enter1
call charpush ;字符入栈
call show_str ;显示栈中字符
jmp getstr
backspace:
call charpop ;字符出栈
call show_str ;显示栈中字符
jmp getstr
enter1: call show_str ;显示栈中字符
pop bx
pop ax
ret
;===============================================================
;子程序:数字的入栈。
;参数说明:ds:si指向char栈空间;(al)=入栈字符;
;===============================================================
charpush:
mov bx,di
mov [si][bx],al
inc di
cmp di,2
je adds
cmp di,5
je adds
cmp di,8
je adds
cmp di,11
je adds
cmp di,14
je adds
ret
adds: inc di
ret
;===============================================================
;子程序:数字的出栈。
;参数说明:ds:si指向char栈空间;(al)=入栈字符;
;===============================================================
charpop:cmp di,0
je sret ;栈顶为0(无字符),结束
cmp di,3
je subs
cmp di,6
je subs
cmp di,9
je subs
cmp di,12
je subs
cmp di,15
je subs
dec di
mov bx,di
mov al,' '
mov [si][bx],al
ret
subs: sub di,2
mov bx,di
mov al,' '
mov [si][bx],al
ret
sret: ret
;===============================================================
;名称:show_str子程序
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0~24);
; (dl)=列号(取值范围0~79);
; (cl)=颜色;
; ds:si指向字符串的首地址。
;返回:无。
;===============================================================
show_str:
push ax
push bx
push cx
push dx
push si
push es
mov ax,0b800h
mov es,ax
mov ax,160
mul dh
mov bx,ax ;bx=160*dh
mov ax,2
mul dl ;ax=dl*2
add bx,ax ;mov bx,(160*dh+dl*2)设置es:bx指向显存首地址
mov al,cl ;把颜色cl赋值al
mov cl,0
show0: mov ch,[si]
jcxz show1 ;(ds:si)=0时,转到show1执行
mov es:[bx],ch
mov es:[bx].1,al
inc si ;ds:si指向下一个字符地址
add bx,2 ;es:bx指向下一个显存地址
jmp show0
show1: pop es
pop si
pop dx
pop cx
pop bx
pop ax
ret
;===============================================================
;名称:clean子程序
;功能:清屏
;===============================================================
clean: push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
clean0: mov byte ptr es:[bx],' '
add bx,2
loop clean0
pop bx
pop cx
pop es
ret
;***************************************************************
;功能2:引导现有的操作系统
;***************************************************************
;===============================================================
;功能2实现引导现有的操作系统,代码需要将硬盘的0面0道1扇区读入0:7c00,
;会覆盖从软盘读到0:7c00的第一个扇区,所以功能2代码不能写在第一个扇区
;===============================================================
function2:
call clean
mov ax,0
mov es,ax
mov bx,7c00h
mov al,1 ;读取的扇区数
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov dl,80h ;驱动器号
mov dh,0 ;磁头号(面号)
mov ah,2 ;int 13h的功能号(2表示读扇区)
int 13h ;读取0面0道1扇区的内容到0:7c00h处
mov ax,0
push ax ;push cs
mov ax,7c00h
push ax ;push ip
retf ;jmp 0:7c00h
floppyend:nop
code ends
end start