为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
相关产品推荐
相关产品推荐

