3

好吧,我正在 Assembly x86 ( 8086 ) 上制作 Space Invaders 游戏,到目前为止运行良好。我在图形模式下使用程序集13h,这意味着 320x200 像素和 256 色。

对于绘图,我使用 sub-function 0ch,这意味着我正在逐个像素地绘制。问题是屏幕被清除得很快,并导致一些视觉故障。

我以前编写过一些游戏,解决方案可能是双缓冲绘图。如何在 Assembly x86 中实现这一点?

编辑

我正在使用 Windows 8 X64 来测试和运行我的代码 DOSBox Portable、tasm 和 tlink。

4

2 回答 2

1

您需要 RAM 中的缓冲区(320*200 = 64000 字节)。这个缓冲区几乎填满了一个段,所以最好确保缓冲区的起始地址是“segment:0x0000”。您可以通过在 RAM 中的此缓冲区中设置像素/字节来绘制内容。例如,要将 (x,y) 处的像素设置为颜色 c,您可以执行以下操作:

mov ax,[y]
mov dx,320
mul dx               ;dx:ax = y * 320
mov di,[x]           ;di = x
add di,ax            ;di = y * 320 + x
mov bx,[bufferSeg]   ;bx = segment of video buffer
mov es,bx            ;es:di = address of pixel
mov al,[c]           ;al = colour
mov [es:di],al       ;Store colour in buffer at (x,y)

如您所见,此计算是混乱/缓慢的;而且您不想为每个像素都这样做。幸运的是,您几乎不需要绘制单个像素(通常您正在绘制线条或字符,或“精灵”),通常您可以计算第一个像素的地址,然后向其添加一些东西以找到下一个像素的地址从头开始计算下一个像素的地址。例如,对于绘制一条垂直线,下一个像素的地址是前一个像素的地址 + 320。

对于图形模式 0x13;显示内存位于物理地址 0x000A0000(或 0xA000:0x0000)。绘制完所有内容后,您会将所有内容从缓冲区复制到显示内存。例如:

mov ds,ax              ;ds = segment for buffer
xor si,si              ;si:si = address for buffer
mov ax,0xA000          ;ax = segment for display memory
mov di,ax              ;di = segment for display memory
mov es,ax              ;es:di = address for display memory
mov cx,320*200/2       ;cx = number of words to copy
cld                    ;Make sure direction flag is clear
rep movsw              ;Copy 320*200/2 words from buffer to display memory
于 2012-11-06T01:51:06.813 回答
0

mov es,[bufferSeg] 有效。在进行段/内存和内存/段移动时,您不需要使用额外的寄存器。

于 2013-03-20T13:13:52.640 回答