Eri*_*fat 6 x86 assembly dos vga x86-16
1我在 DosBox 0.74 上用 TASM 3.0 写,我想用模式 x(调整 13h,非链接模式 13)写,我遇到了一个问题,你如何在图像中看到,每一行都被打印出来,但是在每行,每组四个像素只打印第一个像素的颜色,这是在VRAM中的不同空间打印图像进行双缓冲后,因此所有四个平面都有第一个平面的数据。
这是图像的打印方式(这是没有双缓冲区的直接打印,是的,计时器有问题,但没关系)

这是使用双缓冲打印图像的方式
我确实认为问题在于模式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
Run Code Online (Sandbox Code Playgroud)
如果输出不是问题,这里是内存传输的代码:
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
Run Code Online (Sandbox Code Playgroud)
在 VGA 的图形控制器中,有一个单独的寄存器来指定要读取的平面。
您可以通过在地址端口 03CEh 中写入 4,然后在数据端口 03CFh 中写入平面编号 (0-3) 来选择它。
您使用的 03C4h:02h 寄存器称为 ColorPlane Write Enable。答案已经在它的名字里了!它允许同时写入一个或多个平面。如需读取,请使用 03CEh:04h ReadPlaneSelect。
Run Code Online (Sandbox Code Playgroud)proc DoubleBuffer ... endp pageFlipping
PageFlipping 不需要像此过程那样复制大块内存。
DoubleBuffering 的想法是使用“普通”RAM 构建图片并将其全部或部分复制到视频内存。您的程序使用视频内存来保存双缓冲区,因此读取速度会非常慢!
您根本不需要这种转移和保存!
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
Run Code Online (Sandbox Code Playgroud)
这可以进一步简化为:
xor di, di
mov si, NON_VISABLE_PLANE_OFFSET
mov cx, 16000
cld
rep movs byte [di], [es:si]
Run Code Online (Sandbox Code Playgroud)
的语法rep movs取决于您使用的汇编器。在 NASM 中,您必须在REP MOVSB指令之前添加段覆盖,因此ES REP MOVSB