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

为VGA图形将movedata()替换为内联汇编时出现电脑锁死问题

解决Turbo C内联汇编替换movedata导致的系统锁死问题

你的核心问题大概率是内联汇编中未正确引用C语言变量,导致错误的内存地址被访问,进而引发系统崩溃。以下是具体的排查和修复方案:

1. 修正Turbo C内联汇编的变量引用规则

Turbo C中,内联汇编访问全局C变量时,需要在变量名前添加下划线_;如果是局部变量,建议先将变量值存入寄存器,再在汇编中使用,避免栈帧寻址的复杂性。

全局变量场景修正代码

假设SEG_buffer、OFF_buffer、SIZE2是全局变量:

asm {
    push ds          
    push si
    push di
    push cx
    push es

    mov ax, _SEG_buffer  // 全局变量需加下划线前缀
    mov ds, ax
    mov si, _OFF_buffer

    mov ax, _SEG_vga
    mov es, ax
    mov di, _OFF_vga

    mov cx, _SIZE2
    cld
    rep movsw

    pop es
    pop cx
    pop di
    pop si
    pop ds     
}

局部变量场景修正代码

如果是局部变量,先将地址值存入临时变量再传递给汇编:

void copy_vga_buffer() {
    unsigned int seg_buf = FP_SEG(buffer);
    unsigned int off_buf = FP_OFF(buffer);
    unsigned int seg_vga = 0xA000;  // VGA 320x200 256色模式标准段地址
    unsigned int off_vga = 0;
    unsigned int cnt = 32000;

    asm {
        push ds          
        push si
        push di
        push cx
        push es

        mov ax, seg_buf
        mov ds, ax
        mov si, off_buf

        mov ax, seg_vga
        mov es, ax
        mov di, off_vga

        mov cx, cnt
        cld
        rep movsw

        pop es
        pop cx
        pop di
        pop si
        pop ds     
    }
}

2. 验证关键地址的正确性

  • 确认VGA段地址SEG_vga为0xA000,偏移OFF_vga为0,这是320x200 256色图形模式下帧缓冲的标准起始地址。
  • 用FP_SEG(buffer)和FP_OFF(buffer)获取缓冲区的段/偏移,确保地址合法且缓冲区大小为64000字节,避免越界访问。

3. 排查其他潜在问题

  • 总线兼容性:NuXT2作为PC/XT克隆,CPU为8088(16位寄存器+8位数据总线),movsw会自动拆分为两次8位传输,和movedata行为一致,不存在兼容性问题。
  • 寄存器保护:你的入栈/出栈顺序正确(后进先出),已完整保护所有被修改的寄存器,不会因中断导致寄存器混乱。
  • 缓冲区完整性:检查每帧清空、绘制对象的逻辑,确保没有越界写入破坏缓冲区结构。

最小化测试代码

运行以下极简代码验证汇编复制逻辑是否正常:

#include <dos.h>
#include <graphics.h>
#include <string.h>

#define BUF_SIZE 64000
unsigned char buffer[BUF_SIZE];

void main() {
    int gdriver = VGA, gmode = VGAHI;
    initgraph(&gdriver, &gmode, "");

    // 填充缓冲区为红色(VGA调色板索引4对应红色)
    memset(buffer, 4, BUF_SIZE);

    unsigned int seg_buf = FP_SEG(buffer);
    unsigned int off_buf = FP_OFF(buffer);
    unsigned int cnt = BUF_SIZE / 2;

    asm {
        push ds          
        push si
        push di
        push cx
        push es

        mov ax, seg_buf
        mov ds, ax
        mov si, off_buf

        mov ax, 0xA000
        mov es, ax
        mov di, 0

        mov cx, cnt
        cld
        rep movsw

        pop es
        pop cx
        pop di
        pop si
        pop ds     
    }

    getch();
    closegraph();
}

如果能正常显示全屏红色,说明汇编复制逻辑没问题,问题出在原有代码的其他部分(比如缓冲区更新逻辑)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 10:23:15