assembly - 双缓冲,汇编 x86

标签 assembly x86 drawing graphic doublebuffered

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

对于绘图,我正在使用子函数 0ch,这意味着我正在逐像素绘图。问题是屏幕清除速度非常快,会导致一些视觉故障。

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

编辑

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

最佳答案

您需要在 RAM 中有一个缓冲区(320*200 = 64000 字节)。这个缓冲区几乎填满了一个段,所以最好确保缓冲区的起始地址是“段: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)

如您所见,这个计算很困惑/很慢;而且您不想为每个像素都这样做。幸运的是,您几乎不需要绘制单个像素(通常是绘制线条或字符,或“ Sprite ”),通常您可以计算第一个像素的地址,然后向其添加一些内容以找到下一个像素的地址从头开始计算下一个像素的地址。例如,对于绘制垂直线,下一个像素的地址是前一个像素的地址 + 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

关于assembly - 双缓冲,汇编 x86,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13241594/

相关文章:

assembly - 确定数字的符号

c++ - 寄存器流水线计算

assembly - intel机器码转汇编代码的问题

Java绘制RadialGradientPaint圆切成矩形

javascript - 使用 RaphaelJS 同步两个动画的计时

c - 是否可以访问LR、PC等CPU寄存器

assembly - 子程序如何在不被调用的情况下执行?

visual-studio - 为什么寄存器 ax 中的内存整数之和是正确的,而寄存器 eax 中的内存整数之和却不是正确的?

ubuntu - assembly 模数

c - 使用 C 在 SVG 中绘制切线图