2023-11-05 13:56:43 +08:00
|
|
|
|
mov ax,0xb800
|
|
|
|
|
mov es,ax
|
|
|
|
|
; 清屏
|
|
|
|
|
mov cx,80*25
|
2023-11-11 15:00:12 +08:00
|
|
|
|
clean:
|
|
|
|
|
mov di,cx
|
|
|
|
|
add di,di
|
|
|
|
|
mov byte [es:di],''
|
|
|
|
|
add di,1
|
|
|
|
|
mov byte [es:di],0x0F
|
|
|
|
|
loop clean
|
2023-11-05 13:56:43 +08:00
|
|
|
|
; 显示上方白条
|
|
|
|
|
; 移除(0,0)的S字符
|
2023-11-11 15:00:12 +08:00
|
|
|
|
mov byte [es:0x00],''
|
2023-11-05 13:56:43 +08:00
|
|
|
|
mov cx,80*2-1
|
2023-11-11 15:00:12 +08:00
|
|
|
|
mov di,0
|
|
|
|
|
push cx
|
|
|
|
|
headtitle:
|
|
|
|
|
mov di,cx
|
|
|
|
|
mov byte [es:di],0xF0
|
|
|
|
|
; 写入空字符
|
|
|
|
|
add di,di
|
|
|
|
|
mov byte [es:di],''
|
|
|
|
|
;inc cx
|
|
|
|
|
;sub cx,1
|
|
|
|
|
loop headtitle
|
|
|
|
|
|
|
|
|
|
xor di,di
|
|
|
|
|
pop cx
|
2023-11-05 13:56:43 +08:00
|
|
|
|
; 显示下方白条
|
|
|
|
|
tailtitle:
|
|
|
|
|
mov di,cx
|
|
|
|
|
add di,80*2*24
|
|
|
|
|
mov byte [es:di],0xF0
|
|
|
|
|
; 写入空字符
|
|
|
|
|
mov di,cx
|
|
|
|
|
add di,di
|
|
|
|
|
add di,80*2*24
|
|
|
|
|
mov byte [es:di],''
|
|
|
|
|
loop tailtitle
|
2023-11-11 15:00:12 +08:00
|
|
|
|
; 在第一行写入文本
|
2023-11-05 13:56:43 +08:00
|
|
|
|
jmp near showHeadText
|
2023-11-11 15:00:12 +08:00
|
|
|
|
headText: db 'Wine Runner Webiste:http://gitee.com/gfdgd-xi/deep-wine-runner'
|
2023-11-05 13:56:43 +08:00
|
|
|
|
showHeadText:
|
|
|
|
|
; 虽然可以简单粗暴的用 movsw,但是会出现问题
|
|
|
|
|
mov cx,showHeadText-headText
|
|
|
|
|
mov ax,0x7c0
|
|
|
|
|
mov ds,ax ; 定位到汇编程序所在的内存地址
|
|
|
|
|
showHeadTextLoop:
|
|
|
|
|
mov dx,cx
|
|
|
|
|
mov di,cx
|
|
|
|
|
add di,di
|
|
|
|
|
mov si,headText
|
|
|
|
|
sub dx,1
|
|
|
|
|
add si,dx
|
|
|
|
|
; inc si
|
|
|
|
|
; mov al,1000
|
|
|
|
|
mov al,[ds:si]
|
|
|
|
|
mov byte [es:di],al
|
|
|
|
|
loop showHeadTextLoop
|
|
|
|
|
jmp near showTailText
|
|
|
|
|
tailText: db '2020~Now gfdgd xi'
|
|
|
|
|
showTailText:
|
|
|
|
|
mov cx,showTailText-tailText
|
|
|
|
|
mov ax,0x7c0
|
|
|
|
|
mov ds,ax
|
|
|
|
|
showTailTextLoop:
|
|
|
|
|
mov dx,cx
|
|
|
|
|
mov di,cx
|
|
|
|
|
add di,di
|
|
|
|
|
add di,80*2*24
|
|
|
|
|
mov si,tailText
|
|
|
|
|
sub dx,1
|
|
|
|
|
add si,dx
|
|
|
|
|
mov al,[ds:si]
|
|
|
|
|
mov byte [es:di],al
|
|
|
|
|
loop showTailTextLoop
|
2023-11-07 21:00:32 +08:00
|
|
|
|
|
|
|
|
|
; 显示中部提示文本
|
|
|
|
|
jmp near showCenterText
|
|
|
|
|
centerTextScreenSize:
|
|
|
|
|
; 第一位是行数
|
|
|
|
|
; 第二位是单行偏移量
|
|
|
|
|
db 1, -1
|
|
|
|
|
centerText:
|
2023-11-11 15:00:12 +08:00
|
|
|
|
db 'Mode: Real Mode Demo', 0x0A
|
|
|
|
|
db 'Bit: 16', 0x0A
|
|
|
|
|
db 'Virtual Machine: qemu-system-i386'
|
2023-11-07 21:00:32 +08:00
|
|
|
|
db 0x03 ; 结束符
|
|
|
|
|
showCenterText:
|
|
|
|
|
centerTextLong equ showCenterText-centerText
|
|
|
|
|
mov cx,centerTextLong
|
|
|
|
|
xor ax,ax
|
|
|
|
|
loopShowCenterText:
|
|
|
|
|
jmp near addScreenLineFinish
|
|
|
|
|
addScreenLine:
|
|
|
|
|
; 如果检测到换行符
|
|
|
|
|
mov dx, [centerTextScreenSize]
|
|
|
|
|
add dx,1
|
|
|
|
|
mov [centerTextScreenSize], dx
|
|
|
|
|
dec cx
|
|
|
|
|
mov al,-1
|
|
|
|
|
mov [centerTextScreenSize+1],al
|
|
|
|
|
; 行数+1,偏移量设为 -1(从头开始)
|
|
|
|
|
;ret
|
|
|
|
|
addScreenLineFinish:
|
|
|
|
|
; 偏移量 + 1
|
|
|
|
|
mov al,[centerTextScreenSize+1]
|
|
|
|
|
add al,1
|
|
|
|
|
mov [centerTextScreenSize+1],al
|
|
|
|
|
mov di,centerText
|
|
|
|
|
add di,centerTextLong
|
|
|
|
|
sub di,cx
|
|
|
|
|
mov bl,[di]
|
|
|
|
|
|
|
|
|
|
; 判断是不是结束符
|
|
|
|
|
cmp bl,0x03
|
|
|
|
|
je showCenterTextEnd
|
|
|
|
|
|
|
|
|
|
; 判断是不是换行符
|
|
|
|
|
cmp bl,0x0A
|
|
|
|
|
je addScreenLine ; 换行符检测
|
|
|
|
|
|
|
|
|
|
xor ah,ah ; 清空高位
|
|
|
|
|
add al,al
|
|
|
|
|
mov di,ax
|
|
|
|
|
|
|
|
|
|
; 计算显示位置
|
|
|
|
|
xor dx,dx
|
|
|
|
|
mov dl,[centerTextScreenSize]
|
|
|
|
|
mov ax,80
|
|
|
|
|
mul dx
|
|
|
|
|
mov dx,2
|
|
|
|
|
mul dx
|
|
|
|
|
add ax,2
|
|
|
|
|
add di,ax
|
|
|
|
|
|
|
|
|
|
; 显示
|
|
|
|
|
mov byte [es:di], bl
|
|
|
|
|
loop loopShowCenterText
|
|
|
|
|
|
|
|
|
|
showCenterTextEnd:
|
2023-11-07 18:47:21 +08:00
|
|
|
|
|
2023-11-11 15:00:12 +08:00
|
|
|
|
;mov ax,[cs:0x100]
|
|
|
|
|
;mov dx,[cs:0x102]
|
|
|
|
|
; mov bx,16
|
|
|
|
|
; div bx
|
|
|
|
|
; mov ds,ax
|
|
|
|
|
; mov es,ax
|
|
|
|
|
;xor di,di
|
|
|
|
|
;mov si,1
|
2023-11-11 10:04:00 +08:00
|
|
|
|
;xor ds,ds
|
|
|
|
|
;mov bx,512
|
2023-11-11 15:00:12 +08:00
|
|
|
|
;xor bx,bx
|
|
|
|
|
;call read_hard_disk_0
|
|
|
|
|
|
2023-11-11 10:04:00 +08:00
|
|
|
|
|
2023-11-07 18:47:21 +08:00
|
|
|
|
get_data:
|
|
|
|
|
mov di,80*2*25-2
|
|
|
|
|
|
|
|
|
|
; 读取秒
|
|
|
|
|
mov al,0x00
|
|
|
|
|
call read_time
|
|
|
|
|
mov byte [es:di-4],':'
|
|
|
|
|
mov byte [es:di-2],ah
|
|
|
|
|
mov byte [es:di],al
|
|
|
|
|
; 读取分钟
|
|
|
|
|
mov al,0x02
|
|
|
|
|
call read_time
|
|
|
|
|
mov byte [es:di-10],':'
|
|
|
|
|
mov byte [es:di-8],ah
|
|
|
|
|
mov byte [es:di-6],al
|
|
|
|
|
; 读取小时
|
|
|
|
|
mov al,0x04
|
|
|
|
|
call read_time
|
|
|
|
|
mov byte [es:di-14],ah
|
|
|
|
|
mov byte [es:di-12],al
|
|
|
|
|
; 读取日
|
|
|
|
|
mov al,0x07
|
|
|
|
|
call read_time
|
|
|
|
|
mov byte [es:di-22],'.'
|
|
|
|
|
mov byte [es:di-20],ah
|
|
|
|
|
mov byte [es:di-18],al
|
|
|
|
|
; 读取月
|
|
|
|
|
mov al,0x08
|
|
|
|
|
call read_time
|
|
|
|
|
mov byte [es:di-28],'.'
|
|
|
|
|
mov byte [es:di-26],ah
|
|
|
|
|
mov byte [es:di-24],al
|
|
|
|
|
; 读取年
|
|
|
|
|
mov al,0x09
|
|
|
|
|
call read_time
|
|
|
|
|
mov byte [es:di-32],ah
|
|
|
|
|
mov byte [es:di-30],al
|
2023-11-11 15:00:12 +08:00
|
|
|
|
|
2023-11-07 18:47:21 +08:00
|
|
|
|
|
|
|
|
|
hlt ; 使用停机指令降低 CPU 使用率
|
|
|
|
|
jmp near get_data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
read_time:
|
|
|
|
|
out 0x70,al
|
|
|
|
|
in al,0x71
|
|
|
|
|
call bcd_to_ascii
|
|
|
|
|
ret
|
|
|
|
|
|
|
|
|
|
; 用于编码转换:BCD=》ASCII
|
|
|
|
|
; 输入:AL=bcd码
|
|
|
|
|
; 输出:AX=ascii
|
|
|
|
|
bcd_to_ascii:
|
|
|
|
|
mov ah,al
|
|
|
|
|
and al,0x0f
|
|
|
|
|
add al,0x30
|
|
|
|
|
|
|
|
|
|
shr ah,4
|
|
|
|
|
and ah,0x0f
|
|
|
|
|
add ah,0x30
|
|
|
|
|
ret
|
|
|
|
|
|
2023-11-11 10:04:00 +08:00
|
|
|
|
;poweroff:
|
2023-11-05 13:56:43 +08:00
|
|
|
|
; 关机
|
2023-11-11 10:04:00 +08:00
|
|
|
|
; mov ax,5307H ; 高级电源管理功能,设置电源状态
|
|
|
|
|
; mov bx,0001H ; 设备ID,1:所有设备
|
|
|
|
|
; mov cx,0003H ; 状态,3:表示关机
|
|
|
|
|
; int 15h
|
|
|
|
|
|
2023-11-11 15:00:12 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end:
|
|
|
|
|
times 510-($-$$) db 0
|
|
|
|
|
db 0x55,0xaa
|
|
|
|
|
|
|
|
|
|
; 后面部分暂时废弃
|
|
|
|
|
|
|
|
|
|
|
2023-11-11 10:04:00 +08:00
|
|
|
|
read_hard_disk_0: ; 从硬盘读取一个逻辑扇区
|
|
|
|
|
; 输入:DI:SI=起始逻辑扇区号
|
|
|
|
|
; DS:BX=目标缓冲区地址
|
|
|
|
|
push ax
|
|
|
|
|
push bx
|
|
|
|
|
push cx
|
|
|
|
|
push dx
|
|
|
|
|
|
|
|
|
|
mov dx,0x1f2
|
|
|
|
|
mov al,1
|
|
|
|
|
out dx,al ; 读取的扇区数
|
|
|
|
|
|
|
|
|
|
inc dx ; 0x1f3
|
|
|
|
|
mov ax,si
|
|
|
|
|
out dx,al ; LBA地址7~0
|
|
|
|
|
|
|
|
|
|
inc dx ; 0x1f4
|
|
|
|
|
mov al,ah
|
|
|
|
|
out dx,al ; LBA地址15~8
|
|
|
|
|
|
|
|
|
|
inc dx ; 0x1f5
|
|
|
|
|
mov ax,di
|
|
|
|
|
out dx,al ; LBA地址23~16
|
|
|
|
|
|
|
|
|
|
inc dx ; 0x1f6
|
|
|
|
|
mov al,0xe0 ; LBA28模式,主盘
|
|
|
|
|
or al,ah ; LBA地址27~24
|
|
|
|
|
out dx,al
|
|
|
|
|
|
|
|
|
|
inc dx ; 0x1f7
|
|
|
|
|
mov al,0x20 ; 读命令
|
|
|
|
|
out dx,al
|
|
|
|
|
|
|
|
|
|
.waits:
|
|
|
|
|
in al,dx ; 此时 dx 为 0x1f7,此时为命令端口也是状态窗口
|
|
|
|
|
and al,0x88
|
|
|
|
|
cmp al,0x08
|
|
|
|
|
jnz .waits
|
|
|
|
|
; 内部操作期间,会将 0x1f7 端口第 7 位设置为“1”,准备就绪后会将此位清零,并将第 3 位设为 1
|
|
|
|
|
|
|
|
|
|
mov cx,256 ; 总计要读取的/字/数
|
|
|
|
|
mov dx,0x1f0
|
|
|
|
|
|
|
|
|
|
.readw:
|
|
|
|
|
in ax,dx
|
|
|
|
|
mov [bx],ax
|
|
|
|
|
add bx,2
|
|
|
|
|
loop .readw
|
|
|
|
|
|
|
|
|
|
pop dx
|
|
|
|
|
pop cx
|
|
|
|
|
pop bx
|
|
|
|
|
pop ax
|
|
|
|
|
|