主体程序的基本样式,3、4功能可以运行显示相应结果
1、2功能并不是最终形式,不要运行,以免出现意外的情况
程序较为复杂,篇幅较长,源码请耐心阅读仔细分析
初步源程序
;autoact安装程序
;autoact程序可以自行启动计算机
;功能:(1)列出功能选项,让用户通过键盘进行选择,界面如下。
; 1) reset pc
; 2) start system
; 3) clock
; 4) set clock
;(2)用户输入“1”后重新启动计算机
;(3)用户输入“2”后引导现有的操作系统
;(4)用户输入“3”后,执行动态显示当前日期、时间的程序
; 显示格式:年/月/日 时:分:秒
; 一直动态显示当前的时间,在屏幕上将出现时间按秒变化的效果
; 当按下F1键后,改变显示颜色;按下Esc键后,返回到主菜单
;(5)用户输入“4”后可更改当前的日期、时间,更改后返回到主菜单
;
;
assume cs:code
code segment
;
;目标程序
;名称:autoact
;
autoact:jmp autostart
table dd 0ffff0000h,7c00h
subtab dw sub1,sub2,sub3,sub4 ;功能程序入口地址
str db '1) reset pc',0,'2) start system',0,'3) clock',0,'4) set clock',0
mastack dw 32 dup (0) ;定义栈空间
;
;界面
autostart: mov ax,cs
mov ss,ax ;设置栈空间
mov sp,offset mastack + 64
;
mov ax,0b800h
mov ds,ax
call clrscr
;
mov cx,4
mov bx,0
mov si,0
interface:push cx
mov di,0
mov ch,0
;
row:mov cl,str[si] ;显示行
inc si
jcxz rowend
mov [bx + di],cl
add di,2
jmp row
;
rowend:add bx,160
pop cx
loop interface
;
input: mov ah,0
int 16h
cmp al,'1'
jb input
cmp al,'4'
ja input ;输入不在1~4的范围返回重新输入
;
mov ah,0
sub ax,'1'
mov bx,ax
shl bx,1 ;根据用户输入计算功能程序入口地址在subtab表中的偏移
call word ptr subtab[bx]
jmp autostart ;返回初始化界面
;
;清屏
;参数:需要初始化(ds)=b800h
clrscr: push cx
push di
mov di,0
mov cx,2000
clears:mov byte ptr [di],' ' ;清空屏幕
mov byte ptr [di + 1],07h ;还原颜色属性
add di,2
loop clears
pop di
pop cx
ret
;
;重启计算机
sub1:
call clrscr ;清屏
call dword ptr table[0]
;
;引导操作系统
sub2:
call clrscr ;清屏
mov ax,0
mov es,ax
mov bx,7c00h ;设置es:bx指向接收从扇区读入数据的内存区
;
mov al,1
mov ch,0
mov cl,1
mov dl,80h ;硬盘C驱动器号
mov dh,0
mov ah,2
int 13h
call dword ptr table[4]
;
;动态显示当前日期、时间
sub3:
push ax
push bx
push cx
push dx
push si
push di
;
call clrscr ;清屏
;日期补全
mov byte ptr ds:[160*12+30*2],'2'
mov byte ptr ds:[160*12+31*2],'0'
;
mov si,32*2 ;设置显存
mov dl,9 ;初始访问单元
mov dh,'/' ;日期分隔符
mov bl,1 ;设置访问单元增量,日期部分为1,时间部分为2
call datetime
;
;时间部分的处理
mov byte ptr [160*12+si-2],' '
mov byte ptr [160*12+si],' ' ;日期和时间分隔
add si,2
mov bl,2
time: push si
mov dl,4
mov dh,':' ;时间分隔符
;
call datetime
mov byte ptr [160*12+si-2],' '
pop si
mov bh,al
;
update: mov ah,0ch
int 21h ;作用是清除键盘缓冲区
in al,60h
cmp al,3bh
je color ;按F1键改变显示颜色
cmp al,01h
je return3 ;按下Esc键返回主菜单
;
mov al,0
out 70h,al
in al,71h
and al,00001111b ;取秒的个位数
add al,30h
cmp al,bh
je update ;刷新时间
jmp time ;直接显示刷新时间
;
color:mov di,1
mov cx,2000
loopc:inc byte ptr [di]
add di,2
loop loopc
jmp update ;刷新时间
;
return3: pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
;
;日期时间处理子程序
;参数:(dl)=入口单元,(dh)=分隔符,(bl)=地址变量
;ds:si指向显示地址
;返回:(si)=处理后指向的位置,(al)=末位有效数字
;
datetime: push cx
push dx
mov cx,3
;
loopdt: push cx
mov al,dl
out 70h,al
in al,71h ;取访问单元中的数据
;
mov ah,al
mov cl,4
shr ah,cl ;ah为十位数码值
and al,00001111b ;al为个位数码值
add ah,30h
add al,30h ;得到ASCII码
;
mov byte ptr [160*12+si],ah
mov byte ptr [160*12+si+2],al
mov byte ptr [160*12+si+4],dh
;
add si,6
sub dl,bl
pop cx
loop loopdt
;
pop dx
pop cx
ret
;
;更改当前的日期、时间
sub4:
push ax
push dx
push es
push si
push bp
call clrscr ;清屏
mov byte ptr ds:[0],'2'
mov byte ptr ds:[2],'0' ;初始化日期、时间显示
;
jmp start4
stringsk db 18 dup (0) ;定义字符串存储空间——字符栈
dw 0 ;预留空间
start4: mov dx,2h ;显示位置为0行2列
mov ax,cs
mov es,ax
mov si,offset stringsk ;设置es:si指向字符栈
mov bp,0 ;设置栈顶
call getstr
;
;修改日期、时间
mov bp,0
mov dl,9
mov bl,1
call writedt
;
mov dl,4
mov bl,2
call writedt
;
pop bp
pop si
pop es
pop dx
pop ax
ret
;
;修改CMOS单元的子程序
;参数:(dl)=入口单元,(bl)=地址变量
;es:bp指向写入的字符串
;返回:(bp)=末尾位置
writedt: push ax
push cx
;
mov cx,3
loopwdt: push cx
mov ah,es:[si][bp]
sub ah,30h
mov cl,4
shl ah,cl
sub byte ptr es:[si][bp + 1],30h
or ah,es:[si][bp + 1]
;
mov al,dl
out 70h,al
mov al,ah
out 71h,al
add bp,3
sub dl,bl
pop cx
loop loopwdt
;
pop cx
pop ax
ret
;
;完整的接收字符串输入的子程序
getstr: push ax
;
getstrs:mov ah,0
int 16h
;
cmp al,30h
jb nonumber ;判断的是ASCII码小于30h,说明不是数字
cmp al,39h
ja nonumber ;判断的是ASCII码大于39h,说明不是数字
mov ah,0
call charstack ;字符入栈
mov ah,2
call charstack ;显示栈中的字符
jmp getstrs
;
;
nonumber: cmp ah,0eh ;退格键的扫描码
je backspace
cmp ah,1ch ;回车键的扫描码
je enter
jmp getstrs
;
;
backspace: ;退格
mov ah,1
call charstack ;字符出栈
mov ah,2
call charstack ;显示栈中的字符
jmp getstrs
;
enter: ;回车
mov al,' '
mov ah,0
call charstack ;0入栈
mov ah,2
call charstack ;显示栈中的字符
;
pop ax
ret ;getstr ends
;
;
;字符串功能子程序实现
charstack:jmp short charstart
;
strtable dw charpush,charpop,charshow
;
charstart: push cx
push bx
push dx
push di
;
cmp ah,2
ja overflow
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr strtable[bx]
;
overflow: jmp sret ;值超出返回
charpush:cmp bp,18
je overflow ;栈满不再入栈
mov es:[si][bp],al
inc bp
;
mov cl,'/'
;字符栈2、5单元判断
cmp bp,2
je sform
cmp bp,5
je sform
;
mov cl,' '
;字符栈8、17单元判断
cmp bp,8
je sform
cmp bp,17
je sform
;
mov cl,':'
;字符栈11、14单元判断
cmp bp,11
je sform
cmp bp,14
je sform
;直接返回
jmp sret
;
;格式符显示
sform: mov ah,2
call charstack ;显示字符
mov es:[si][bp],cl
inc bp
jmp sret
;
charpop:cmp bp,0
je sret
dec bp
;
cmp bp,2
je cform
cmp bp,5
je cform
cmp bp,8
je cform
cmp bp,11
je cform
cmp bp,14
je cform
;
rcform: mov al,es:[si][bp]
jmp sret
;
;格式符清除
cform: mov ah,2
call charstack ;显示字符
dec bp
jmp rcform ;返回
;
charshow: 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,bp
jne noempty
mov byte ptr [di],' '
jmp sret
;
noempty:mov al,es:[si][bx]
mov [di],al
mov byte ptr [di+2],' '
inc bx
add di,2
jmp charshows
;
sret: pop di
pop dx
pop bx
pop cx
ret
;
autoactend:nop
mov ax,4c00h
int 21h
code ends
end autoact
运行结果
3号功能
4号功能