You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

8086引导程序绘制矩形闪烁问题求助及相关教程推荐

Hey there! Let's fix that annoying pixel flickering when drawing rectangles in 320x200 256-color VGA mode. I’ve messed around with this classic issue before, so here’s a straightforward breakdown of why it happens and how to fix it step by step.

Why the Flickering Happens

In VGA Mode 13h (320x200 256-color), the display hardware constantly reads from the video memory at segment 0xA000 to refresh the screen. If your code modifies this memory while the screen is being refreshed, the hardware will catch a half-updated frame—causing that distracting flicker effect.

The most reliable fix is to use a double buffer: draw your entire rectangle in an off-screen memory area first, then copy the finished frame to video memory all at once. This way, the screen only ever shows complete, fully rendered frames.

1. Allocate an Off-Screen Buffer

First, set aside a continuous block of memory (at least 64KB, since 320×200 = 64,000 pixels) for your off-screen work. In real mode, you can use a memory segment that’s not used by the system or your code—0x1000 is a safe bet here:

[bits 16]
[org 0x7c00]
start:
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov sp, 0x09000
    mov bp, sp

    ; Save the off-screen buffer segment (0x1000 * 16 = 0x10000 in physical memory)
    mov word [offscreen_seg], 0x1000

    ; Enter VGA Mode 13h
    mov ax, 0x13
    int 0x10

2. Draw Your Rectangle to the Off-Screen Buffer

Instead of writing directly to 0xA000 (video memory), render your rectangle to the off-screen buffer. Here’s an example of drawing a solid rectangle:

; Draw a rectangle to the off-screen buffer
mov ax, [offscreen_seg]
mov es, ax          ; Point ES to the off-screen segment
mov di, 0x0000      ; Start at offset 0

; Rectangle parameters: (10,10) top-left, 100px wide, 50px tall, color 0xFF
mov cx, 50          ; Number of rows (height)
draw_row:
    push cx
    mov cx, 100     ; Number of pixels per row (width)
    mov al, 0xFF    ; Pixel color
    rep stosb       ; Fill the row with color
    add di, 320 - 100 ; Move to the start of the next row (320 pixels per screen row)
    pop cx
    loop draw_row

3. Wait for Vertical Sync (Optional but Critical for Smoothness)

To avoid "screen tearing" when copying the buffer, wait for the vertical blanking interval—this is the split second when the display finishes refreshing and starts over. Use the VGA status register at 0x3DA to detect this:

wait_vsync:
    in al, 0x3DA
    test al, 0x08
    jnz wait_vsync       ; Wait for the vertical sync to end
wait_vsync_end:
    in al, 0x3DA
    test al, 0x08
    jz wait_vsync_end    ; Wait for the vertical sync to start

4. Copy the Off-Screen Buffer to Video Memory

Now transfer the fully drawn rectangle to video memory in one go. Using rep movsw (copying words instead of bytes) makes this faster:

; Copy the 64KB off-screen buffer to video memory
mov ax, [offscreen_seg]
mov ds, ax
mov ax, 0xA000
mov es, ax
mov si, 0x0000
mov di, 0x0000
mov cx, 32000       ; 64,000 bytes = 32,000 words
rep movsw           ; Copy the entire buffer
Alternative Fix: Wait for Sync Before Drawing

If you don’t have enough memory for a double buffer, you can wait for vertical sync before drawing each row or pixel. This will slow down rendering but reduce flicker:

; Call this before drawing each row/pixel
wait_vsync:
    in al, 0x3DA
    test al, 0x08
    jnz wait_vsync
wait_vsync_end:
    in al, 0x3DA
    test al, 0x08
    jz wait_vsync_end
    ret
Quick Notes for Your Existing Code

Looking at your snippet (mov ebx,13h mov eax,4...), make sure you’re properly entering Mode 13h first. Then replace all direct writes to 0xA000 with writes to your off-screen buffer, and add the sync + copy steps at the end.


内容的提问来源于stack exchange,提问作者Dodo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:53:45