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

32位保护模式下用变量偏移文本显存地址的异常问题

问题分析

代码存在两个直接导致显存访问错误的问题:

  • 汇编语法错误:add edx, CURSORX执行时,加到edx上的是CURSORX变量的内存地址,而非变量中存储的光标坐标值。x86汇编中要读取内存变量的内容,必须用方括号包裹内存操作数,正确写法是取[CURSORX]的值。
  • 偏移计算逻辑错误:VGA文本模式下每个字符显示单元占2字节(1字节ASCII编码、1字节显示属性),水平偏移N个字符位置时,对应的字节偏移量是N * 2,直接加坐标值会导致地址错位,要么写到属性字节位置,要么跨单元覆盖显存数据。

如果CURSORX是单字节存储的坐标值(范围0-79),直接参与32位地址计算时还可能因为高位残留垃圾值导致地址完全越界,访问非显存区域触发CPU异常,这也是屏幕内容全部消失的核心原因——未注册异常处理的情况下,非法内存访问会直接导致CPU复位或跳转至不可预期位置,清空屏幕显示。

正确实现

32位保护模式版本(直接访问线性地址)

mov al, ' '
mov ah, 0xff
; 加载显存基址+第三行(从0开始计数)行偏移,每行80字符共占160字节
mov edx, 0xb8000 + 160*3
; 零扩展读取单字节存储的X坐标,避免高位脏数据影响地址
movzx ecx, byte [CURSORX]
; 坐标转字节偏移(乘2)后计算最终目标地址
lea edx, [edx + ecx*2]
; 写入显存完成光标位置绘制/擦除
mov word [edx], ax

如果CURSORX定义为32位双字类型,去掉movzx的零扩展逻辑,直接写mov ecx, [CURSORX]即可。

实模式版本(段:偏移寻址)

如果是在16位实模式下开发,不能直接使用32位线性地址,需要通过段寄存器映射显存段:

; 配置附加段寄存器指向文本显存段基址
mov ax, 0xb800
mov es, ax
mov al, ' '
mov ah, 0xff
; 计算行偏移
mov bx, 160*3
; 读取X坐标
movzx cx, byte [CURSORX]
; 计算X对应的字节偏移(乘2)
add bx, cx
add bx, cx
; 段寻址写入显存
mov [es:bx], ax
运行效果参考
  • 无偏移逻辑正常运行效果:
    无偏移正常运行截图
  • 地址计算错误时的异常效果:
    添加偏移后异常截图

内容的提问来源于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 05:15:40