assume cs:code, ds:data
stack segment
db 64 dup(0)
stack ends
data segment
buf db 1024 dup(0)
old_mbr db 512 dup(0)
data ends
code segment
start:
mov ax, data
mov ds, ax
mov es, ax
mov ax, stack
mov ss, ax
mov sp, 64
; 读取硬盘的逻辑扇区0到old_mbr
mov bx, offset old_mbr
mov dx, 0080h
mov cx, 0001h
mov ax, 0201h
int 13h
; 把old_mbr写到硬盘的逻辑扇区2
mov bx, offset old_mbr
mov dx, 0080h
mov cx, 0003h
mov ax, 0301h
int 13h
; 复制mbr段到buf
push ds
mov ax, mbr
mov ds, ax
mov si, offset mbr_start
mov di, offset buf
mov cx, mbr_end - mbr_start
cld
rep movsb
pop ds
; 备份被分区表和引导标志占用的内容
mov si, offset buf
mov di, offset buf
add si, 1beh
add di, offset swap_data
mov cx, 66
cld
rep movsb
; 复制分区表和引导标志
mov si, offset old_mbr
mov di, offset buf
add si, 1beh
add di, 1beh
mov cx, 66
cld
rep movsb
; 把buf写到硬盘的逻辑扇区0和逻辑扇区1
mov bx, offset buf
mov dx, 0080h
mov cx, 0001h
mov ax, 0302h
int 13h
; jmp far ptr 0f000h:0fff0h
db 0eah
dw 0fff0h
dw 0f000h
mov ax, 4c00h
int 21h
code ends
mbr segment
mbr_start:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 7c00h
mov si, 7c00h
mov di, 0600h
mov cx, 256
cld
rep movsw
; jmp far ptr 60h:migrate
db 0eah
dw migrate
dw 60h
migrate:
mov ax, cs
mov ds, ax
mov es, ax
sti ; 确保允许中断
; 读取硬盘的逻辑扇区1到当前代码后面
mov bx, 200h
mov dx, 0080h
mov cx, 0002h
mov ax, 0201h
int 13h
; 恢复被分区表和引导标志占用的内容
mov si, offset swap_data
mov di, 1beh
mov cx, 66
cld
rep movsb
main_loop:
call cls
call disp_menu
call getchar
cmp al, '1'
jne @f
call reset_pc
jmp end_switch
@@:
cmp al, '2'
jne @f
call start_system
jmp end_switch
@@:
cmp al, '3'
jne @f
call clock
jmp end_switch
@@:
cmp al, '4'
jne @f
call set_clock
jmp end_switch
@@:
cmp al, '5'
jne @f
call uninstall_this
jmp end_switch
@@:
end_switch:
jmp main_loop
disp_menu:
push ax
push bx
push cx
push dx
push bp
mov bp, menu
mov dx, 0a20h
mov cx, 11
mov bx, 0007h
mov ax, 1300h
int 10h
mov bp, menu + 11
mov dx, 0b20h
mov cx, 15
mov bx, 0007h
mov ax, 1300h
int 10h
mov bp, menu + 26
mov dx, 0c20h
mov cx, 8
mov bx, 0007h
mov ax, 1300h
int 10h
mov bp, menu + 34
mov dx, 0d20h
mov cx, 12
mov bx, 0007h
mov ax, 1300h
int 10h
mov bp, menu + 46
mov dx, 0e20h
mov cx, 17
mov bx, 0007h
mov ax, 1300h
int 10h
; 设置光标到下一行
mov ah, 02h
mov bh, 0
mov dx, 0f00h
int 10h
pop bp
pop dx
pop cx
pop bx
pop ax
ret
reset_pc:
; jmp far ptr 0f000h:0fff0h
db 0eah
dw 0fff0h
dw 0f000h
ret
start_system:
; 读取硬盘的逻辑扇区2到0000h:7c00h
xor ax, ax
mov es, ax
mov bx, 7c00h
mov dx, 0080h
mov cx, 0003h
mov ax, 0201h
int 13h
mov dl, 80h ; 从硬盘启动
; jmp far ptr 0000h:7c00h
db 0eah
dw 7c00h
dw 0000h
ret
clock:
push ax
push bx
push si
mov bx, offset color
call cls
clock_loop:
call read_time
call show_time
mov si, 19
call update_cursor
call kbhit
cmp ax, 0
jz clock_hlt
call getchar
cmp ah, 01h ; Esc
je clock_exit
cmp ah, 3bh ; F1
jne clock_hlt
inc byte ptr [bx]
clock_hlt:
hlt
jmp clock_loop
clock_exit:
mov byte ptr [bx], 07h
pop si
pop bx
pop ax
ret
set_clock:
push ax
push bx
push si
call cls
call read_time
call show_time
mov bx, offset time
xor si, si
call update_cursor
set_clock_loop:
call getchar
cmp ah, 01h ; Esc
je set_clock_exit
cmp ah, 1ch ; Enter
jne @f
call write_time
jmp set_clock_exit
@@:
cmp ah, 4bh ; 左箭头
jne @f
cmp si, 0
je set_clock_hlt
dec si
call update_cursor
jmp set_clock_hlt
@@:
cmp ah, 4dh ; 右箭头
jne @f
cmp si, 18
je set_clock_hlt
inc si
call update_cursor
jmp set_clock_hlt
@@:
cmp al, '0'
jb set_clock_hlt
cmp al, '9'
ja set_clock_hlt
mov byte ptr [bx + si], al
call show_time
set_clock_hlt:
hlt
jmp set_clock_loop
set_clock_exit:
pop si
pop bx
pop ax
ret
uninstall_this:
xor ax, ax
mov es, ax
; 读取硬盘的逻辑扇区2到0000h:7c00h
mov bx, 7c00h
mov dx, 0080h
mov cx, 0003h
mov ax, 0201h
int 13h
; 把0000h:7c00h写到硬盘的逻辑扇区0
mov bx, 7c00h
mov dx, 0080h
mov cx, 0001h
mov ax, 0301h
int 13h
call reset_pc
ret
cls:
push ax
push cx
push di
push es
mov ax, 0b800h
mov es, ax
mov ax, 0720h
xor di, di
mov cx, 2000
cld
rep stosw
pop es
pop di
pop cx
pop ax
ret
getchar:
mov ah, 0
int 16h
ret
kbhit:
mov ah, 1
int 16h
jnz @f
xor ax, ax
@@:
ret
read_time:
push ax
push bx
push cx
mov bx, offset time
mov cx, 4
; 读取秒
mov al, 0
out 70h, al
in al, 71h
mov ah, al
and al, 0fh
shr ah, cl
add al, '0'
add ah, '0'
mov [bx + 18], al
mov [bx + 17], ah
; 读取分
mov al, 2
out 70h, al
in al, 71h
mov ah, al
and al, 0fh
shr ah, cl
add al, '0'
add ah, '0'
mov [bx + 15], al
mov [bx + 14], ah
; 读取时
mov al, 4
out 70h, al
in al, 71h
mov ah, al
and al, 0fh
shr ah, cl
add al, '0'
add ah, '0'
mov [bx + 12], al
mov [bx + 11], ah
; 读取日
mov al, 7
out 70h, al
in al, 71h
mov ah, al
and al, 0fh
shr ah, cl
add al, '0'
add ah, '0'
mov [bx + 9], al
mov [bx + 8], ah
; 读取月
mov al, 8
out 70h, al
in al, 71h
mov ah, al
and al, 0fh
shr ah, cl
add al, '0'
add ah, '0'
mov [bx + 6], al
mov [bx + 5], ah
; 读取年
mov al, 9
out 70h, al
in al, 71h
mov ah, al
and al, 0fh
shr ah, cl
add al, '0'
add ah, '0'
mov [bx + 3], al
mov [bx + 2], ah
; 读取世纪
mov al, 32h
out 70h, al
in al, 71h
mov ah, al
and al, 0fh
shr ah, cl
add al, '0'
add ah, '0'
mov [bx + 1], al
mov [bx + 0], ah
pop cx
pop bx
pop ax
ret
write_time:
push ax
push bx
push cx
mov bx, offset time
mov cx, 4
; 写入秒
mov al, 0
out 70h, al
mov al, [bx + 18]
mov ah, [bx + 17]
sub al, '0'
sub ah, '0'
shl ah, cl
or al, ah
out 71h, al
; 写入分
mov al, 2
out 70h, al
mov al, [bx + 15]
mov ah, [bx + 14]
sub al, '0'
sub ah, '0'
shl ah, cl
or al, ah
out 71h, al
; 写入时
mov al, 4
out 70h, al
mov al, [bx + 12]
mov ah, [bx + 11]
sub al, '0'
sub ah, '0'
shl ah, cl
or al, ah
out 71h, al
; 写入日
mov al, 7
out 70h, al
mov al, [bx + 9]
mov ah, [bx + 8]
sub al, '0'
sub ah, '0'
shl ah, cl
or al, ah
out 71h, al
; 写入月
mov al, 8
out 70h, al
mov al, [bx + 6]
mov ah, [bx + 5]
sub al, '0'
sub ah, '0'
shl ah, cl
or al, ah
out 71h, al
; 写入年
mov al, 9
out 70h, al
mov al, [bx + 3]
mov ah, [bx + 2]
sub al, '0'
sub ah, '0'
shl ah, cl
or al, ah
out 71h, al
; 写入世纪
mov al, 32h
out 70h, al
mov al, [bx + 1]
mov ah, [bx + 0]
sub al, '0'
sub ah, '0'
shl ah, cl
or al, ah
out 71h, al
pop cx
pop bx
pop ax
ret
show_time:
push ax
push bx
push cx
push dx
push bp
mov bp, offset time
mov dx, 0c1fh
mov cx, 19
mov bx, offset color
mov bx, [bx]
mov ax, 1300h
int 10h
pop bp
pop dx
pop cx
pop bx
pop ax
ret
update_cursor:
push ax
push bx
push dx
mov ah, 02h
mov bh, 0
mov dx, 0c1fh
add dx, si
int 10h
pop dx
pop bx
pop ax
ret
menu:
db '1) reset pc'
db '2) start system'
db '3) clock'
db '4) set clock'
db '5) uninstall this'
time db '0000/00/00 00:00:00'
color dw 0007h
; 这里存放被分区表和引导标志占用的内容
swap_data:
db 66 dup(0)
mbr_end:
mbr ends
end start