王爽 著《汇编语言》(第3版):课程设计2

assume cs:code,ss:stack

stack segment
 db 128 dup (0)
stack ends

code segment
;----------------------------	安装程序	----------------------------------------
start: 
	mov ax,stack
	mov ss,ax
	mov sp,128
	
;将引导程序安装到磁盘0面0磁道1扇区
	mov bx,cs
	mov es,bx
	mov bx,offset setup
	
	mov ch,0
	mov cl,1
	mov dh,0
	mov dl,0
	mov ah,3
	mov al,1
	int 13h


;将任务程序安装到磁盘0面0磁道2扇区
	mov bx,cs
	mov es,bx
	mov bx,offset boot
	
	mov ch,0
	mov cl,2
	mov dh,0
	mov dl,0
	mov ah,3
	mov al,2
	int 13h


	mov ax,4c00h
	int 21h

;------------------------	引导程序	-------------------------------------------
setup:
	mov bx,0
	mov ss,bx
	mov sp,7C00H

	call installint9 	;将原int9地址保存到0:200H处
	call installboot	;将任务程序从磁盘0面0磁道2扇区安装到0:7C00H处

	mov bx,0
	push bx
	mov bx,7E00H
	push bx
	retf 				;引导安装完成后,从0:7E00H执行任务程序

;安装新的int9
installint9:
	push cs
	push es

	mov ax,cs
	mov ds,ax
	mov si,offset newint9 - offset setup + 7C00H
	mov ax,0
	mov es,ax
	mov di,206H
	mov cx,offset newint9end - offset newint9
	cld
	rep movsb

	pop es
	pop cx
	ret

;新int9中断
newint9:
	push ax
	push bx
	push cx
	push es

	in al,60H
	pushf
	call dword ptr cs:[200H]

	cmp al,3BH
	je int9_f1
	cmp al,1
	je int9_esc

	jmp short newint9ret

;响应F1的子程序
int9_f1:
	mov ax,0B800H
	mov es,ax
	mov bx,1
	mov cx,2000
int9_f1s:
	inc byte ptr es:[bx]
	add bx,2
	loop int9_f1s
	jmp short newint9ret

;响应ESC的子程序
int9_esc:
	mov ax,0
	mov es,ax
	cli
	push es:[200H]
	pop es:[9*4]
	push es:[202H]
	pop es:[9*4+2]
	sti
	mov word ptr es:[204],1		;设置用于中断显示时间循环的flag
	jmp short newint9ret

newint9ret:
	pop es
	pop cx
	pop bx
	pop ax
	iret

newint9end:
	nop

;安装任务程序
installboot:
	mov bx,0
	mov es,bx
	mov bx,7E00H

	mov ch,0
	mov cl,2
	mov dh,0
	mov dl,0
	mov ah,2
	mov al,2
	int 13h

	ret

	db 512 dup (0) 			;安装程序将引导程序安装到磁盘后,第一个扇区空闲位置用0补足

;----------------------------	任务程序	----------------------------------------
boot:
	jmp short menu
	s1	db '1) reset pc',0
	s2	db '2) start system',0
	s3	db '3) clock',0
	s4	db '4) set clock',0
	s5 db 'Enter index number:',0
	show	dw offset s1 - offset boot + 7E00H
				dw offset s2 - offset boot + 7E00H
				dw offset s3 - offset boot + 7E00H
				dw offset s4 - offset boot + 7E00H
				dw offset s5 - offset boot + 7E00H
time	db '00/00/00 00:00:00',0
cindex	db 9,8,7,4,2,0

;调用菜单
menu:
	mov bx,0B800H
	mov es,bx

	mov bx,0
	mov ds,bx
	
	call cls
	call line

	jmp short run

;清屏程序
cls:
	push es
	mov bx,0B800H
	mov es,bx

	mov bx,0
	mov cx,2000
clss:
	mov ax,0720H
	mov es:[bx],ax
	add bx,2
	loop clss
	pop es
	ret

;显示文字数据
line:
	mov bx,offset show - offset boot + 7E00H	;文字行地址
	mov cx,5
	mov di,160*8+30*2
lines:
	mov si,ds:[bx]								;ds:[bx]为文字行首字符地址,si为文字行第一个字符的地址
	call showline
	add di,160
	add bx,2
	loop lines
	ret

;显示一行字符串
showline:
	push di
showlines:
	mov al,ds:[si]
	cmp al,0
	je showlineok
	mov es:[di],al
	add di,2
	inc si
	jmp short showlines
showlineok:
	pop di
	ret

;响应菜单指令程序
run:
	call clearbuff
	
	mov ah,0
	int 16h

	cmp al,'1'
	je f1
	cmp al,'2'
	je f2
	cmp al,'3'
	je f3
	cmp al,'4'
	je f4

	jmp run

;清除输入缓存
clearbuff:
	mov ah,1						;读取键盘缓存字符,返回参数ZF=0时al=字符,ZF=1时缓存区为空
	int 16h
	jz clearbuffok 					;ZF=1时缓存区为空跳转
	mov ah,0						;ZF不为1时,循环读取字符并丢弃al
	int 16h
	jmp clearbuff
clearbuffok:
	ret

;响应指令1
f1:
	call showi
	call reboot
	;mov word ptr ds:[0],0FFFFH
	;mov word ptr ds:[2],0
	;call dword ptr ds:[0]
	jmp run

;响应指令2
f2:
	call showi
	call system

;响应指令3
f3:
	call showi
	call gettime
	jmp menu

;响应命令4
f4:
	call showi
	call settime
	jmp menu

;显示输入的命令序号
showi:
	mov byte ptr es:[160*12+30*2+19*2],al
	ret

;重启
reboot:
	mov bx,0FFFFH
	push bx
	mov bx,0
	push bx
	retf

;加载c盘系统并执行
system:
	mov bx,0
	mov es,bx
	mov bx,7C00H

	mov ch,0
	mov cl,1
	mov dl,80h
	mov dh,0
	mov ah,2
	mov al,1
	int 13h

	call cls

	mov bx,0
	push bx
	mov bx,7C00H
	push bx
	retf

;设定cmos时间程序
settime:
	call resettimedata
	call showtimedata
	call getstr
	call updatetime
	ret

;更新cmos时间程序
updatetime:
	mov bx,offset cindex - offset boot + 7E00H
	mov si,offset time - offset boot +7E00H
	mov cx,6
updatetimes:
	push cx
	mov dx,ds:[si]
	sub dx,3030H
	mov cl,4
	shl dl,cl
	or dl,dh
	mov al,ds:[bx]
	out 70h,al
	mov al,dl
	out 71h,al
	add si,3
	inc bx
	pop cx
	loop updatetimes
	ret

;将输入内容存储到时间字符串缓存
getstr:
	mov si,offset time - offset boot + 7E00H 		;字符栈缓存位置
	mov bx,0 										;字符栈当前位置
getstrs:
	call clearbuff
	mov ah,0
	int 16h
	cmp al,'0'
	jb notnumber
	cmp al,'9'
	ja notnumber
	call charpush
	call showtimedata
	jmp getstrs

;非数字时,判断是否为backspaces或enter
notnumber:
	cmp ah,0eh
	je backspace
	cmp ah,1ch
	je enter
	jmp getstrs

;退格键执行
backspace:
	call charpop
	call showtimedata
	jmp getstrs

;回车键执行(结束输入)
enter:
	ret

;字符栈出栈
charpop:
	cmp bx,0
	je charpopret
	cmp bx,3
	je charreset
	cmp bx,6
	je charreset
	cmp bx,9
	je charreset
	cmp bx,12
	je charreset
	cmp bx,15
	je charreset

	cmp bx,1
	je chargo
	cmp bx,2
	je chargo
	cmp bx,4
	je chargo
	cmp bx,5
	je chargo
	cmp bx,7
	je chargo
	cmp bx,8
	je chargo
	cmp bx,10
	je chargo
	cmp bx,11
	je chargo
	cmp bx,13
	je chargo
	cmp bx,14
	je chargo
	cmp bx,16
	je chargo
	cmp bx,17
	je chargo
charreset:
	dec bx

chargo:
	dec bx
	mov byte ptr ds:[si+bx],'0'
	cmp bx,3
	je charpopset
	cmp bx,6
	je charpopset
	cmp bx,9
	je charpopset
	cmp bx,12
	je charpopset
	cmp bx,15
	je charpopset
	jmp short charpopret
charpopset
	dec bx
charpopret:
	ret

;字符栈入栈
charpush:
	cmp bx,16
	ja charpushret
	mov ds:[si+bx],al
	inc bx
	cmp bx,2
	je charpushset
	cmp bx,5
	je charpushset
	cmp bx,8
	je charpushset
	cmp bx,11
	je charpushset
	cmp bx,14
	je charpushset
	jmp short charpushret
charpushset:
	inc bx
charpushret:
	ret

;显示时间字符串缓存内容
showtimedata:
	push si
	push di
	mov si,offset string_stack - offset boot + 7E00H
	mov di,160*14+30*2
	call showline
	pop di
	pop si
	ret

;重置时间字符串内容
resettimedata:
	push bx
	push cx
	push es
	push si
	push di

	mov si,offset time - offset boot + 7E00H
	mov dx,3030h
	mov cx,6
clearstringstack:
	mov ds:[si],dx
	add si,3
	loop clearstringstack

	pop di
	pop si
	pop es
	pop cx
	pop bx
	ret

;显示cmos时间程序
gettime:
	call setupnewint9
	call showtime
	ret

;安装新的int9程序
setupnewint9:
	push es
	mov ax,0
	mov es,ax

	push es:[9*4]
	pop es:[200H]
	push es:[9*4+2]
	pop es:[202H]

	cli
	mov word ptr es:[9*4],206H
	mov word ptr es:[9*4+2],0
	sti

	mov word ptr es:[204H],0			;初始化响应ESC的flag

	pop es
	ret

;显示时间字符串
showtime:
	push ax
	push bx
	push cx
	push es
showtimestart:
	call clearibuff
	mov cx,6
	mov si,0
	mov di,0
showtimes:
	mov bx,offset cindex - offset install + 7E00H
	mov al,ds:[bx+si]
	call savetimedata					;将读取结果保存到时间字符串缓存中,用于显示。若为读取并马上显示,会发生闪烁现象
	add di,3
	inc si
	loop showtimes

	mov ah,al
	mov al,0
	out 70H,al
	in al,71H
	cmp al,ah
	je showtime
	mov bx,offset time - offset install + 7E00H
	call showdata

	mov ax,0
	mov es,ax
	mov ax,es:[204H]
	cmp ax,1
	je showtimeok						;每个循环中判断响应ESC的flag是否为1,为1则中断循环
	jmp short showtimestart
showtimeok:
	pop es
	pop cx
	pop bx
	pop ax
	ret

;把读取的cmos数据保存到时间字符串缓存
savetimedata:
	push cx
	out 70H,al
	in al,71H
	mov ah,al
	mov cl,4
	shr ah,cl
	and al,00001111B
	add ax,3030H
	mov bx,offset time - offset install + 7E00H
	mov ds:[bx+di],ah
	mov ds:[bx+di+1],al
	pop cx
	ret

;显示时间字符串
showdata:
	push ax
	push cx
	push es
	mov ax,0B800H
	mov es,ax
	mov di,160*16+30*2
	mov si,0
	mov cx,17
showdatas:
	mov al,ds:[bx+si]
	mov byte ptr es:[di],al
	inc si
	add di,2
	loop showdatas
	pop es
	pop cx
	pop ax
	ret


	db 512 dup (0)
code ends
end start
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
阅读下面的材料 : 开机后, CPU 自动进入到 FFF0:0 单元处执行,此处有一条跳转指令。 CPU 执行该指令后,转去执行 BIOS 中的硬件系统检测和初始化程序。 初始化程序将建立 BIOS 所支持的中断向量,即将 BIOS 提供的中断历程的入口地址登记在中断向量表中。 硬件系统检测和初始化完成后,调用 INT 19H 进行操作系统的引导。 如果设为从软盘启动操作系统,则 INT 19H 将主要完成一下工作: ( 1 )控制 0 号软驱,读取软盘 0 道 0 面 1 扇区的内容到 0 : 7C 00 。 ( 2 )将 CS:IP 指向 0 : 7C 00 。 软盘的 0 道 0 面 1 扇区中装有操作系统引导程序。 INT 19H 将其装到 0 : 7C 00 处后,设置 CPU 从 0 : 7C 00 开始执行此处的引导程序,操作系统被激活,控制计算机。 如果在 0 号软驱中没有软盘,或发生软盘 I/O 错误,则 INT 19H 将主要完成以下工作 ; (1) 读取硬盘 C 的 0 道 0 面 1 扇区的内容到 0 : 7C 00 ; (2) 将 CS:IP 指向 0 : 7C 00 。 这次课程设计的任务是编写一个可以自行启动计算机,不需要在现有操作系统环境中运行的程序。 改程序的功能如下: ( 1 )列出功能选项,让用户通过键盘进行选择,界面如下: 1 ) reset pc ; 重新启动计算机 2 ) Start system ; 引导现有的操作系统 3 ) Clock ; 进入时钟程序 4 ) Srt clock ; 设置时间 ( 2 )用户输入“ 1 ”后重新启动计算机。(提示:考虑 FFFF:0 ) ( 3 )用户输入“ 2 ” 后引导现有的操作系统。(提示:考虑硬盘 C 的 0 道 0 面 1 扇区) ( 4 )用户输入“ 3 ”后,执行动态现实当前日期,时间的程序。 现实格式如下:年 / 月 / 日 时:分:秒 进入此项功能后,一直动态现实当前的时间,在屏幕上将出现时间按秒变化的效果。(提示:循环读取 CMOS ) 当按下 F1 键后,改变现实颜色;按下 ESC 键后,返回到主选单。(提示:利用键盘中断) ( 5 )用户输入“ 4 ”后可更改当前的日期,时间,更改后返回到主选单。(提示:输入字符串) 下面给出的几点建议: ( 1 )在 DOS 下编写安装程序,在按转程序中包含任务程序; ( 2 )运行安装程序,将任务程序写到软盘上; ( 3 )若要任务程序可以在开机后自行执行,要将它写到软盘的 0 道 0 面 1 扇区上。如果程序长度大于 512B ,则需要用多个扇区存放,这种情况下,处于软盘 0 道 0 面 1 扇区中的程序就必须负责将其他扇区中的内容读入内存。 这个程序较为复杂,它用到了我们所学到的所有技术,需要进行仔细地分析和耐心地调试。这个程序对于我们的整个学习过程是具有总结性的,希望读者能够尽力完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值