deep-wine-runner/VM-source/test-kvm.asm

290 lines
4.8 KiB
NASM
Raw Normal View History

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
; 显示中部提示文本
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'
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-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
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
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 ; 设备ID1所有设备
; 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