【问题标题】:Double Buffering, Assembly x86双缓冲,汇编 x86
【发布时间】:2012-10-25 20:22:17
【问题描述】:

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

对于绘图,我使用子函数0ch,这意味着我正在逐个像素地绘制。问题是屏幕清理得很快,会导致一些视觉故障。

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

编辑

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

【问题讨论】:

  • 这不是汇编本身的问题,而是您的代码将在哪个硬件和软件环境中运行。您使用的是操作系统,如果是的话,是哪个?
  • 这在 25 年前是通过翻页来完成的。让约翰卡马克他的法拉利。好吧,1990 年的模型,直到他厌倦了它们并开始发射火箭。

标签: assembly x86 drawing graphic doublebuffered


【解决方案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

【讨论】:

  • 谢谢,这类似于清屏方法,现在确实有意义,谢谢!
【解决方案2】:

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

【讨论】:

  • 您能否充实一下这个答案并扩展主题?
猜你喜欢
  • 2017-04-01
  • 2021-04-20
  • 1970-01-01
  • 1970-01-01
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多