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

如何在汇编语言中更快绘制矩形?现有int 10h实现性能优化需求

优化int 10h逐像素绘制矩形的速度问题

你当前用int 10h/ah=0Ch逐像素调用BIOS中断绘制矩形,代码如下:

proc drawRect  ;this function gets the coords of the upper left point of the rect and the height and width, as well as the color of it, and draw
mov cx, [n1]    ;n1=x, n2=y, n3=width, n4=height, al=color
mov dx, [n2]
add [n3], cx
add [n4], dx
row:
    mov dx, [n2]
    column:
        mov ah, 0Ch     ;draws a pixel on the given color and coords, due to the loops.
        mov bh, 0
        int 10h

        inc dx
        cmp dx, [n4]
        jbe column
    inc cx
    cmp cx, [n3]
    jbe row
ret
endp drawRect

这种方式速度慢的核心原因是每绘制一个像素就触发一次BIOS中断,中断本身需要保存/恢复CPU上下文,500×500的矩形要触发25万次中断,开销极大。以下是两种更高效的优化方案:

一、直接写入显存(最快方案)

绕过BIOS中断,直接往视频显存地址写入像素值,是x86实模式下最快的图形绘制方式。不同视频模式的显存地址和每行字节数不同,以常用的VGA 13h(320×200 256色)为例,显存段地址为0A000h,每行占320字节。

优化后的代码示例:

proc drawRectFast
    ; 输入参数:n1=x, n2=y, n3=width, n4=height, al=color
    push bx cx dx es di  ; 保存寄存器

    mov ax, 0A000h       ; 显存段地址(VGA 13h模式)
    mov es, ax

    mov cx, [n3]         ; CX = 矩形宽度(每次填充的字节数)
    mov dl, 320          ; DL = 屏幕每行字节数(VGA 13h固定为320)
    mov ax, [n2]         ; AX = 起始y坐标
    mul dl               ; AX = y * 320(计算行起始偏移)
    add ax, [n1]         ; AX = y*320 + x(矩形左上角显存偏移)
    mov di, ax

    mov ah, al           ; AH暂存颜色值(避免循环中重复读取内存)
    mov dx, [n4]         ; DX = 矩形高度(需要绘制的行数)
drawRow:
    mov al, ah
    rep stosb            ; 一次性填充整行CX个像素
    add di, 320 - [n3]   ; 跳转到下一行的矩形起始位置
    dec dx
    jnz drawRow

    pop di es dx cx bx   ; 恢复寄存器
    ret
endp drawRectFast

关键优化点:

  • 用rep stosb指令一次性填充整行像素,把25万次操作缩减为500次循环
  • 直接操作显存,完全避免BIOS中断的上下文切换开销
  • 提前计算显存偏移,减少循环内的计算量

如果使用其他视频模式,需要调整显存段地址和每行字节数:

  • 文本模式(80×25):显存段地址0B800h,每行160字节(每个字符占2字节)
  • VGA 16色模式(640×480):显存段地址0A000h,每行80字节(每像素占4位,2像素1字节)

二、优化原有中断调用方案(小幅提速)

如果必须依赖BIOS中断,可通过减少重复的寄存器赋值来小幅提升速度:把mov ah,0Ch和mov bh,0移到循环外部,避免每次绘制像素都重复设置这些寄存器:

proc drawRectOptimized
mov cx, [n1]    ;n1=x, n2=y, n3=width, n4=height, al=color
mov dx, [n2]
add [n3], cx
add [n4], dx
mov ah, 0Ch     ; 提前设置中断功能号
mov bh, 0       ; 提前设置显示页
row:
    mov dx, [n2]
    column:
        int 10h         ; 仅调用中断
        inc dx
        cmp dx, [n4]
        jbe column
    inc cx
    cmp cx, [n3]
    jbe row
ret
endp drawRectOptimized

这种修改能节省部分循环内的指令执行时间,但本质还是逐像素中断,速度提升远不如直接写入显存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 21:37:49