|
发表于 2011-12-12 09:50:08
|
显示全部楼层
- 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
复制代码
|
|