[1我正在DosBox 0.74上用TASM 3.0编写,而我试图用Mode x编写(已调整13h,unchained mode 13),我遇到了一个问题,如何在图像中看到每一行会被打印,但是在每一行中,每四个像素组仅打印第一个像素的颜色,这是在将图像打印在VRAM中不同空间中以进行双缓冲之后,因此所有四个平面都具有第一架飞机。
这是应该打印图像的方式(这是不带双缓冲区的直接打印,是的,计时器有问题,但是没关系)
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS9YV0pYVC5wbmcifQ==” alt =“在此处输入图像描述”>
这是使用双缓冲打印图像的方式
我确实相信问题在于,在模式x下,数据与VGA端口中的读写数据不同,这是选择VGA平面的代码
proc VGAPlaneSelect
push ax
push dx
push cx
mov al, 02h
mov dx, 03C4h
out dx, al
VGAPlaneSelect_start:
mov ax, 1
mov cl, [VGAPlane]
shl ax, cl
cmp [VGAPlane], 4
jne VGAPlaneSelect_end
mov [VGAPlane], 0
jmp VGAPlaneSelect_start
VGAPlaneSelect_end:
mov dx, 03C5h
out dx, al
pop cx
pop dx
pop ax
ret
endp VGAPlaneSelect
如果输出不是问题,这里是内存传输的代码:
proc DoubleBuffer
mov ax, 0A000h
mov es, ax
mov [VGAPlane], 0
call VGAPlaneSelect
cli
mov cx, 4
DoubleBuffer_loop:
xor di, di
xor si, si
push cx
mov cx, 16000
DoubleBuffer_loop_plane:
push di
push si
shr di, 2
shr si, 2
add si, NON_VISABLE_PLANE_OFFSET
mov al, [es:si]
stosb
pop si
pop di
add di, 4
add si, 4
loop DoubleBuffer_loop_plane
inc [VGAPlane]
call VGAPlaneSelect
pop cx
loop DoubleBuffer_loop
sti
ret
endp pageFlipping
您使用的03C4h:02h寄存器称为ColorPlane
Write Enable。答案已经是它的名字了!它允许同时写入一个或多个平面。对于阅读,请使用03CEh:04h ReadPlaneSelect。
proc DoubleBuffer
...
endp pageFlipping
哪个?
PageFlipping不需要复制此过程中的大块内存。DoubleBuffering的想法是使用“普通” RAM来构建图片并将其全部或部分复制到视频内存中。您的程序使用视频内存来保存双缓冲区,因此读取速度非常慢!
DoubleBuffer_loop太复杂了?
xor di, di
mov si, NON_VISABLE_PLANE_OFFSET
mov cx, 16000
DoubleBuffer_loop_plane:
mov al, [es:si]
stosb
inc si
dec cx
jnz DoubleBuffer_loop_plane
可以进一步简化为:
xor di, di
mov si, NON_VISABLE_PLANE_OFFSET
mov cx, 16000
cld
rep movs byte [di], [es:si]
rep movs
的语法取决于您使用的汇编程序。在NASM中,您必须在REP MOVSB
指令之前加上句段覆盖,因此ES REP MOVSB