如下:
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
db 4 dup (0)
datasg ends
stacksg segment
dw 32 dup (0)
stacksg ends
codesg segment
start:;write to the floppy
mov ax,cs
mov es,ax
mov bx,offset floppy
mov dl,0
mov dh,0
mov cl,1
mov ch,0
mov al,4
mov ah,3
int 13h
mov ax,4c00h
int 21h
org 7c00h
floppy:jmp short beg
origin_int9 dw 0,0
dis_choice db 0
is_clock db 0
is_set_clock db 0
format2 db 'YE/MO/DA hh:mm:ss',0
example db 'please set the clock, the format is YE/MO/DA hh:mm:ss',0
hint db 'the clock has been set.',0
;mov ax,stacksg
;mov ss,ax
;mov sp,32*2
;mov ax,datasg
beg:;将第二个扇区读入内存
mov ax,0
mov es,ax
mov bx,7c00h+200h
mov dx,0
mov cx,2
mov ax,0203h
int 13h
mov dis_choice,1
call display
;替换9号中断
mov ax,0
mov es,ax
mov ax,es:[9*4]
mov origin_int9,ax
mov ax,es:[9*4+2]
mov origin_int9[2],ax
cli
mov word ptr es:[9*4],offset s9_beg
mov word ptr es:[9*4+2],cs
sti
s3:nop
jmp short s3
s9_beg:push bp
mov bp,sp
add bp,2
push ax
push ds
push bx
push si
push cx
push es
push di
in al,60h
mov bl,al
pushf
;mov si,offset origin_int9
call dword ptr origin_int9;here the book use 'cs' register
;这里修改一下,
;按4以后,清除第一个屏幕,显示屏幕样例提示,中断退出
;开始接受输入字符,输入完成后,在下一行显示已设置成功,按Esc返回到第一个屏幕
;进入setting cmod以后,按键不会触发其他的处理
;mov ah,0
;int 16h
cmp is_clock,1
jne s14
cmp bl,3Bh
jne s12
jmp near ptr c_f1
s12:cmp bl,1h
jne s10
jmp near ptr c_esc
s14:cmp is_set_clock,0
jne s11
cmp bl,2h
je reset
cmp bl,3h
je sys
cmp bl,4
je clock
cmp bl,5
jne s10
jmp near ptr set_c
s11:cmp bl,1h
jne s10
jmp near ptr set_esc
s10:jmp near ptr s4
reset:mov ax,ss
mov ds,ax
mov word ptr ds:[bp],0
mov word ptr ds:[bp+2],0ffffh
jmp near ptr s4
sys:;
;恢复int 9
mov ax,0
mov es,ax
mov ax,origin_int9
mov es:[9*4],ax
mov ax,origin_int9[2]
mov es:[9*4+2],ax
;删除键盘缓冲区
mov ah,0
int 16h
;int 13h 读硬盘
mov dx,0080h
mov cx,0001h
mov bx,7c00h
;es的值已设置过
mov ax,0201h
;模拟int 13h指令
pushf
;pushf
;pop ax
;and ah,11111100b
;push ax
;popf
push es
push bx
mov dis_choice,0
call display
jmp dword ptr es:[13h*4]
clock:mov is_clock,1
mov ah,0
int 16h
mov ax,ss
mov ds,ax
mov word ptr ds:[bp],offset clock_dis
mov ax,cs
mov word ptr ds:[bp+2],ax
mov dis_choice,0
call display
jmp near ptr s4
c_f1:mov ah,0
int 16h
mov ax,0b800h
mov es,ax
mov di,160*12+62+1
mov si,0
cf1_s1:cmp byte ptr format2[si],0
jne s13
jmp near ptr s4
s13:add byte ptr es:[di],1
inc si
add di,2
jmp short cf1_s1
c_esc:mov ah,0
int 16h
mov is_clock,0
;清除屏幕先
mov ax,0b800h
mov es,ax
mov di,160*12+62
mov si,0
cesc_s1:cmp byte ptr format2[si],0
je cesc_s3
mov es:[di],0720h
inc si
add di,2
jmp short cesc_s1
cesc_s3:mov dis_choice,1
call display
mov ax,ss
mov ds,ax
mov word ptr ds:[bp],offset s3
mov ax,cs
mov word ptr ds:[bp+2],ax
jmp near ptr s4
set_c:mov is_set_clock,1
mov ah,0
int 16h
mov dis_choice,0
call display
;显示时间格式提示
mov ax,0b800h
mov es,ax
mov di,160*12+80
mov si,0
setc_s1:cmp byte ptr example[si],0
je setc_s2
mov al,example[si]
mov es:[di],al
inc si
add di,2
jmp short setc_s1
setc_s2:call clock_set
;设置完成提示
mov ax,0b800h
mov es,ax
mov di,160*14+80
mov si,0
setc_s3:cmp byte ptr hint[si],0
je setc_s4
mov al,hint[si]
mov es:[di],al
inc si
add di,2
jmp short setc_s3
setc_s4:mov ax,ss
mov ds,ax
mov word ptr ds:[bp],offset s3
mov ax,cs
mov word ptr ds:[bp+2],ax
jmp short s4
set_esc:mov ah,0
int 16h
mov is_set_clock,0
;清除example提示
mov ax,0b800h
mov es,ax
mov di,160*12+80
mov si,0
sesc_s1:cmp byte ptr example[si],0
je sesc_s2
mov byte ptr es:[di],' '
inc si
add di,2
jmp short sesc_s1
;清除输入时间提示
sesc_s2:mov di,160*13+80
mov si,0
sesc_s3:cmp byte ptr format2[si],0
je sesc_s4
mov byte ptr es:[di],' '
inc si
add di,2
jmp short sesc_s3
;清除输入完成提示
sesc_s4:mov di,160*14+80
mov si,0
sesc_s5:cmp byte ptr hint[si],0
je sesc_s6
mov byte ptr es:[di],' '
inc si
add di,2
jmp short sesc_s5
sesc_s6:mov dis_choice,1
call display
mov ax,ss
mov ds,ax
mov word ptr ds:[bp],offset s3
mov ax,cs
mov word ptr ds:[bp+2],ax
jmp short s4
s4:pop di
pop es
pop cx
pop si
pop bx
pop ds
pop ax
pop bp
iret
s9_se:nop
;dis_choice为参数:1为显示,0为清屏
display:jmp short dis_beg
ad dw f1,f2,f3,f4
f1 db '1) reset pc',0
f2 db '2) start system',0
f3 db '3) clock',0
f4 db '4) set clock',0
dis_beg:push ax
push es
push di
push cx
push si
push bx
push dx
mov ax,0b800h
mov es,ax
mov cx,0 ;行数计数器
mov si,0 ;每行地址的指针
next:mov di,10*160+32*2
mov ax,160
mul cx
add di,ax
mov bx,ad[si]
add si,2
s0:mov al,cs:[bx]
cmp al,0 ;一行是否结束
je s1
add bx,1
;display功能选择
cmp dis_choice,1
je s2
mov byte ptr es:[di],' '
jmp short s5
s2:mov es:[di],al
s5:add di,2
jmp short s0
s1:add cx,1
cmp cx,4
je dis_end
jmp short next
dis_end:pop dx
pop bx
pop si
pop cx
pop di
pop es
pop ax
ret
clock_dis:jmp short s7
format db 'YE/MO/DA hh:mm:ss',0
position db 9,8,7,4,2,0
s7:mov bx,0
mov si,0
mov cx,6
s9:mov al,position[bx]
out 70h,al
in al,71h
mov ah,al
push cx
mov cl,4
shr ah,cl
pop cx
and al,00001111b
add ah,30h
add al,30h
mov format[si],ah
mov format[si+1],al
add si,3
inc bx
loop s9
mov ax,0b800h
mov es,ax
mov di,160*12+62
mov si,0
s8:cmp byte ptr format[si],0
je s7
mov al,format[si]
mov es:[di],al
inc si
add di,2
jmp short s8
;输入字符,保存到input_string
data db 256 dup(0)
charstack:jmp short charstart
table dw charpush,charpop,charshow,chardel
top dw 0
input_string db 'YE/MO/DA hh:mm:ss' ;课程设计2需要
charstart:push bx
push dx
push si
push es
cmp ah,3
ja s4_0
mov bl,ah
mov bh,0
add bx,bx
jmp word ptr table[bx]
charpush:mov bx,top ;注意标号的用法
mov data[si+bx],al
inc top
s4_0:jmp sret
charpop:cmp top,0
je sret
dec top
mov bx,top
mov al,data[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,data[si+bx]
mov es:[di],al
mov byte ptr es:[di+2],' '
inc bx
add di,2
jmp charshows
chardel: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,top
add bx,bx
add di,bx
mov byte ptr es:[di],' '
jmp sret
sret:pop es
pop di
pop dx
pop bx
ret
getstr:push ax
;课程设计2需要增加
push di
push dx
push si
push cx
getstrs:mov ah,0
int 16h
cmp al,20h
jb nochar
mov ah,0
call charstack
mov ah,2
call charstack
jmp getstrs
nochar:cmp ah,0eh
je backspace
cmp ah,1ch
je enter
jmp getstrs
backspace:mov ah,1
call charstack
mov ah,3
call charstack
jmp getstrs
enter:mov al,0
mov ah,0
call charstack
;mov ah,2
;call charstack
;下面为课程设计2需要新增加的功能
mov top,0
mov ax,0b800h
mov es,ax
;下面计算di
mov al,160
mov ah,0
mul dh
mov di,ax
add dl,dl
mov dh,0
add di,dx
mov si,0
mov cx,17
s4_2:mov al,es:[di]
mov input_string[si],al
add di,2
add si,1
loop s4_2
pop cx
pop si
pop dx
pop di
;功能增加完毕
pop ax
ret
clock_set:push si
push dx
mov si,0
mov dh,13
mov dl,40
call getstr
pop dx
pop si
push si
push di
push cx
push ax
push bx
jmp short s4_3
;将input_string变为BCD码,存到string
string db 6 dup(0)
s4_3:mov si,0
mov di,0
mov cx,6
s4_4:mov al,input_string[si]
sub al,30h
push cx
mov cl,4
shl al,cl
pop cx
add si,1
mov ah,input_string[si]
sub ah,30h
add al,ah
mov string[di],al
cmp cx,1
je s4_5
add si,2
inc di
s4_5:loop s4_4
;用string中的字节设置CMOS时间
mov bx,0
mov cx,6
s4_6:mov al,position[bx]
out 70h,al
mov al,string[bx]
out 71h,al
inc bx
loop s4_6
pop bx
pop ax
pop cx
pop di
pop si
ret
codesg ends
end start