我在汇编中编写游戏,今天我注意到奇怪的问题,在0x13
图形模式下屏幕底部显示的文字有时不会刷新。经过一段时间的搜索,我设法在一个更短的程序中重现问题,这只是连续不断
打印彩色数字。
我的代码:
[org 0x7c00]
[bits 16]
;Stack setup
mov bp, 0xffff
mov sp, bp
;Switch into mode 13h
mov ah, 0x00
mov al, 0x13
int 0x10
drawloop:
;Set cursor position
mov ah, 2
mov bh, 0
mov dh, 24
mov dl, 1
int 0x10
;Load counter into al
;Change color to cnt value
;Print at page 0
mov al, [cnt]
mov bl, al
mov bh, 0
;Print hex value of cnt (low byte)
call puthexb
;Wait 1/18.2 s
mov ax, 0
int 0x1a
mov bx, dx
delay:
int 0x1a
cmp bx, dx
je delay
;Increment counter
inc word [cnt]
;Issue doesn't happen if screen isn't cleared
call gfxcls
jmp drawloop
jmp $
cnt: dw 0
;Clear screen
gfxcls:
pushf
pusha
push es
mov ax, 0xA000 ;Make es point video memory
mov es, ax ;
mov cx, 32000 ;We will write 32000 times (word each time)
mov di, 0 ;Start at the beginning of the vmem
mov ax, 0 ;Fill it with 0s
cld ;Clear direction flag
rep stosw ;Kinda memset
pop es
popa
popf
ret
;Print contents of al register on screen (as hex number)
;al - value
puthexb:
pushf
pusha
push ax
and ax, 0x00f0 ;Fetch older 4 bits
shr ax, 4 ;Shift them into lower position
mov si, puthexb_assoc ;
add si, ax ;Add offset to assoc table address
mov al, [si] ;Print character
mov ah, 0xe ;
int 0x10 ;
pop ax ;Restore initial value to display
and ax, 0x000f ;Get 4 younger bits
mov si, puthexb_assoc ;
add si, ax ;Add offset to assoc table address
mov al, [si] ;Print character
mov ah, 0xe ;
int 0x10 ;
popa
popf
ret
puthexb_assoc: db '0123456789abcdef'
times 510 - ( $ - $$ ) db 0
dw 0xaa55
我用这个命令组装并运行代码:
nasm -f bin vgack.asm -o vgack.bin && qemu-system-i386 -boot a -fda vgack.bin
运行一段时间后,文本停止更改,但程序继续执行(您可以通过在每次循环迭代的屏幕上的某处绘制颜色像素来轻松检查) - 这很奇怪。
在后续绘制之间,当每次在同一个地方中绘制文本并且修改了屏幕的主要部分(此处 - 在我的游戏中已清除 - 填充了第二个视频缓冲区内容)时出现问题
此外,在真正的PC上还没有发生错误 - 程序现在在笔记本电脑上运行了大约一个小时。该问题仅存在于qemu中(我的版本为1:2.5+dfsg-5ubuntu10.14
- 它看起来很旧,但apt
表示它是最新版本)。那么,是否有可能,我发现了一个错误?
<小时/>