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

32位保护文本模式下如何使用汇编实现换行打印

32位保护模式VGA文本模式汇编换行打印实现

之前操作无效的原因

VGA默认80×25文本模式的显存起始地址为0xb8000,每个字符占2字节:低字节存ASCII码,高字节存显示属性。直接修改0xb8000处的值仅会修改屏幕左上角第一个字符的内容,既没有更新当前打印位置的偏移,也没有调整VGA光标状态,自然无法实现换行效果。

换行实现核心逻辑

换行本质是将后续打印的起始位置移动到下一行行首,若当前已经在屏幕最后一行,还需要执行滚屏操作,核心步骤如下:

  • 内存中维护两个全局状态值:cursor_row(当前行号,范围0-24)、cursor_col(当前列号,范围0-79),所有打印操作都基于这两个值计算显存偏移
  • 触发换行时,先将cursor_col置0(回到行首),再将cursor_row加1(移动到下一行)
  • 判断cursor_row是否等于25(超出最大行索引24):如果是则执行滚屏,将第124行的显存内容整体上移1行覆盖第023行,清空最后一行后将cursor_row重置为24
  • 计算新位置的显存偏移:显存偏移 = (cursor_row * 80 + cursor_col) * 2,后续字符从0xb8000 + 显存偏移位置开始写入
  • 若需要显示硬件光标,通过0x3D4、0x3D5端口更新VGA光标寄存器的值即可

32位汇编实现示例(NASM语法)

; 全局状态变量定义
cursor_row: db 0
cursor_col: db 0
vga_base:   equ 0xb8000
vga_attr:   equ 0x07    ; 默认黑底白字属性

; 换行功能函数
print_newline:
    mov byte [cursor_col], 0
    inc byte [cursor_row]
    cmp byte [cursor_row], 25
    jl .update_hw_cursor

; 滚屏逻辑
.scroll:
    cld
    mov esi, vga_base + 80*2  ; 源地址:第1行起始位置
    mov edi, vga_base         ; 目的地址:第0行起始位置
    mov ecx, 24*80            ; 共24行,每行80个字符单元,按4字节搬运
    rep movsd

    ; 清空最后一行
    mov ebx, vga_base + 24*80*2
    mov ecx, 80
.clr_last:
    mov word [ebx], vga_attr << 8 | ' '
    add ebx, 2
    loop .clr_last
    mov byte [cursor_row], 24

; 更新硬件光标
.update_hw_cursor:
    movzx ax, byte [cursor_row]
    mov bx, 80
    mul bx
    movzx bx, byte [cursor_col]
    add ax, bx    ; ax = 光标线性位置(行*80+列,非字节偏移)

    ; 写光标高8位
    mov dx, 0x3D4
    mov al, 0xE
    out dx, al
    mov dx, 0x3D5
    mov al, ah
    out dx, al

    ; 写光标低8位
    mov dx, 0x3D4
    mov al, 0xF
    out dx, al
    mov dx, 0x3D5
    mov al, al
    out dx, al

    ret

注意:如果不需要显示硬件闪烁光标,可以省略端口操作部分,但必须维护内存中的cursor_row和cursor_col变量,否则后续打印无法定位到正确位置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 10:15:29