|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 没个正样 于 2012-2-28 10:51 编辑
;哎哟!费老大劲才完成《课程设计2》。
;题目:课程设计2
;阅读下面的材料:
;开机后,CPU自动进入到FFFF:0单元处执行,此处有一条跳转指令。CPU执行该指令后,转去执行BIOS中的硬件系统检测和初始化程序。
;初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中。
;硬件系统检测和初始化完成后,调用int 19h进行操作系统的引导。
;*****
;如果设为从软盘启动操作系统,则int 19h将主要完成以下工作。
;(1)控制0号软驱,读取软盘0道0面1扇区的内容到0:7c00;
;(2)将CS:IP指向0:7c00。
;*****
;软盘的0道0面1扇区中装有操作系统引导程序。int 19h将其装到0:7c00处后,设置CPU从0:7c00开始执行此处的引导程序,操作系统被激活,控制计算机。
;如果在0号软驱中没有软盘,或发生软盘I/O错误,则int 19h将主要完成以下工作。
;(1)读取硬盘C的0道0面1扇区的内容到0:7c00;
;(2)将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"后可更改当前的日期、时间,更改后返回到主选单(提示:输入字符串)。
;功能:将代码写入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)=出错代码
;一,第一部分。(将引导信息数据写入某驱动器)
assume cs:code
code segment
start:mov ax,offset ydxxend-offset ydxx
mov dx,0
mov bx,512
div bx ;商ax为所需的扇区数
cmp dx,0
je ok
inc al ;如果dx不等于0,那么证明有余数要加一个扇区。
ok: mov bx,cs
mov ds,bx
mov bx,offset ydxx ;es:bx指向要被开始读入的内存单元
mov ah,3 ;int 13h的功能号(3表示写扇区)
mov ch,0 ;磁道号
mov cl,1 ;扇区号(1处开始)
mov d,0 ;磁头号(面号)
mov dl,0 ;驱动器号,软盘A
int 13h
mov ax,4c00h
int 21h
;二,第二部分。
ydxx: mov ax,offset ydxxend-offset ks1
mov dx,0
mov bx,512
div bx ;商ax为所需的扇区数
cmp dx,0
je ok1
inc al ;如果dx不等于0,那么证明有余数要加一个扇区。
ok1: mov bx,0
mov es,bx
mov bx,7c00h+200h ;es:bx指向要被写入的内存单元
mov ah,2 ;int 13h的功能号(2表示读扇区,3表示写扇区)
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov dh,0 ;磁头号(面号)
mov dl,0 ;驱动器号,软盘A
int 13h
mov bx,7c0h
push bx
mov bx,offset ks1
push bx
retf
ks1: jmp d1
table dw cd1,cd2,cd3,cd4 ;直接定址表
cd db '1) reset pc ',0
db '2) start system',0
db '3) clock ',0
db '4) set clock ',0
db 'F1 / Esc ',0
time db 'ni/yu/re si:fe:ma',0
cmos db 9,8,7,4,2,0
zb db ' F1/Esc ',0
;显示主菜单,调用show_str、qp子程序
d1: call qp ;清屏
push cs
pop ds
mov si,offset cd
mov dh,8
mov dl,30
mov cx,5
d0: push cx
mov cl,7
call show_str
add si,16
add di,160
pop cx
loop d0
;接收键盘输入,跳转相应功能程序段
;调用BIOS用来提供读取键盘缓冲区功能的中断例程int 16h,
;将读取的扫描码送入ah,ASCII码送入al
d2: mov ax,0
int 16h
cmp al,'1'
jb d1
cmp al,'4'
ja d1
sub al,31h
mov bl,al
mov bh,0
add bx,bx ;计算相应子程序在table中的位移
call word ptr table[bx] ;调用对应的功能子程序
jmp d1
;功能1:重新启动计算机
cd1:
mov ax,0ffffh
push ax
mov ax,0
push ax
retf ;jmp ffff:0
;功能2:引导现有的操作系统
;功能2实现引导现有的操作系统,代码需要将硬盘的0面0道1扇区读入0:7c00,
;会覆盖从软盘读到0:7c00的第一个扇区,所以功能2代码不能写在第一个扇区
cd2:call qp
mov ax,0
mov es,ax
mov bx,7c00h
mov ah,2 ;int 13h的功能号(2表示读扇区)
mov al,1 ;读取的扇区数
mov ch,0 ;磁道号
mov cl,1 ;扇区号
mov dl,80h ;驱动器号
mov dh,0 ;磁头号(面号)
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
;功能3:进入时钟程序
cd3:
push ax
push bx
push cx
push dx
push si
push ds
push es
call qp ;清屏
mov dh,24 ;行号
mov dl,33 ;列号
mov cl,7
mov si,offset zb
mov di,0
call show_str ;显示提示信息
;名称:dtsj
;功能:动态显示当前日期、时间
mov cx,7 ;显示颜色
dtsj: push cx
mov si,offset time
mov bx,offset cmos
mov cx,6
s0: 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,00001111b ;al分成两个表示BCD码值的数据
add ah,30h
add al,30h ;BCD码+30h=10进制数对应的ASCII码
mov [si],ax ;ASCII码写入ds:[si]
inc bx
add si,3
pop cx
loop s0
;按下F1键后,改变显示颜色
;按下Esc键后,返回主菜单,其他键照常处
mov al,0
in al,60h
pop cx ;显示颜色
cmp al,3bh ;和F1的扫描码3bh比较
je hdbz
cmp al,1 ;和Esc的扫描码01h比较
je dtsjend
jmp zjxs
bs: mov cx,0
jmp zjxs
hdbz:cmp cx,127
je bs
inc cx
zjxs:mov dh,12 ;行号
mov dl,33 ;列号
mov si,offset time
mov di,0
call show_str
jmp dtsj ;循环显示CMOS
dtsjend:
pop es
pop ds
pop si
pop dx
pop cx
pop bx
pop ax
ret
;功能4:设置时间
cd4: call qp
dtsj1: mov si,offset time
mov bx,offset cmos
mov cx,6
s1: 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,00001111b ;al分成两个表示BCD码值的数据
add ah,30h
add al,30h ;BCD码+30h=10进制数对应的ASCII码
mov [si],ax ;ASCII码写入ds:[si]
inc bx
add si,3
pop cx
loop s1
mov dh,12 ;行号
mov dl,33 ;列号
mov cl,7
mov si,offset time
mov di,0
call show_str
mov si,offset time
call getstr
jmp near ptr ydxx
;完整的接收字符串输入的子程序
getstr: push ax
getstrs:
mov ah,0
int 16h
cmp al,20h
jb nochar ;判断的是ASCII码小于0,说明不是字符
mov ah,0
call charstack ;字符入栈
mov ah,2
call charstack ;显示栈中的字符
jmp getstrs
nochar:
cmp ah,0eh ;退格键的扫描码
je backspace
cmp ah,1ch ;回车键的扫描码
je denter
jmp getstrs
backspace: ;退格
mov ah,1
call charstack ;字符出栈
mov ah,2
call charstack ;显示栈中的字符
jmp getstrs
denter: ;回车
mov al,0
mov ah,0
call charstack ;0入栈
mov ah,2
call charstack ;显示栈中的字符
pop ax
ret
;功能子程序实现
charstack:
jmp short charstart
tableb dw charpush,charpop,charshow
top dw 0 ;栈顶
charstart:
push bx
push dx
push di
push es
cmp ah,2
ja sret
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr tableb[bx]
charpush:
mov bx,top
mov [si][bx],al
inc top
jmp sret
charpop:
cmp top,0
je sret
dec top
mov bx,top
mov al,[si][bx]
jmp sret
charshow:
mov bx,0b800h
mov es,bx
mov al,160
mov ah,0
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx
mov bx,0
charshows:
cmp bx,top
jne noempty
mov byte ptr es:[di],' '
jmp sret
noempty:
mov al,[si][bx]
mov es:[di],al
mov byte ptr es:[di+2],' '
inc bx
add di,2
jmp charshows
sret:
pop es
pop di
pop dx
pop bx
ret
;名称:qp子程序
;功能:清屏
qp:
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0
mov cx,2000
qp0: mov byte ptr es:[bx],' '
add bx,2
loop qp0
pop bx
pop cx
pop es
ret
;名称:show_str子程序
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0~24);
; (dl)=列号(取值范围0~79);
; (cl)=颜色;
; ds:si指向字符串的首地址。
;返回:无。
show_str: ;显示字符串的子程序(定义开始)。
push ax
push bx
push cx
push dx
push es
push si
push di
mov al,0a0h ;每行有160个字节,转换成16进制为A0。
mul dh ;相当于从第(n-1)*0A0H个Byte单元开始......
mov bx,ax ;定位好的位置偏移地址存放在bx里(行)
mov al,2 ;每个字符占两个字节
mul dl ;定位列,结果ax存放的是定位好的列的位置
add bx,ax ;此时bx中存放的是行与列号的偏移地址
mov ax,0B800h ;显存开始的地址
mov es,ax ;es中存放的是显存的第0页(共0--7页)的起始的段地址
mov al,cl ;cl是存放颜色的参数,这时候al存放颜色了,因为cl下边要用来临时存放要处理的字符
mov ch,0 ;下边cx存放的是每次准备处理的字符
s: mov cl,ds:[si] ;ds:[si]指向“ ”,0
jcxz ok3 ;当cl的值为0时候,cx == 0, 则发生跳转,到OK处结束处理!
mov es:[bx+di],cl ;偶地址存放字符
mov es:[bx+di+1],al ;奇地址存放字符的颜色属性
inc si
add di,2 ;指向了下个字符
jmp short s ;无条件跳转,jcxz是离开的关键跳!
ok3:pop di
pop si
pop es
pop dx
pop cx
pop bx
pop ax
ret ;显示字符串的子程序[定义结束]
ydxxend:nop
code ends
end start
|
|