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

C语言内联汇编MOV指令无法运行,x86_64编译报错32位环境段错误

问题原因拆解

1. x86_64环境编译报错的原因

x86_64架构的寻址模式不支持使用16位寄存器%bx作为基址指针,你写的汇编代码是16位/32位x86实模式兼容的写法,在64位编译链下直接被汇编器拒绝,属于架构语法限制。
使用gcc -m32指定编译为32位程序后,32位x86架构支持16位基址寻址,所以编译可以通过。

2. 32位程序运行触发段错误的原因

不管你用inline汇编还是直接操作指针,本质都是在Linux用户态进程的虚拟地址空间中直接访问固定地址0xf0f0:

  • Linux对用户态进程的地址空间有严格的保护机制,低于1MB的低地址区域默认是未映射的非法区域,只要访问就会触发内核发送SIGSEGV信号,也就是你遇到的段错误。
  • 这个行为和你自研OS的裸金属/自定义内存管理环境完全不同:Linux用户态有虚拟地址翻译、内存权限校验,而你自研OS如果是跑在实模式、自定义页表的环境下,地址是直接映射/你自己定义规则的,二者没有可比性。

解决方案

  • 如果只是要验证内存读写函数的逻辑正确性,不要写死固定地址,先申请一块合法的用户态内存再测试:
int main() {
    char *test_buf = malloc(1); // 申请合法可访问的内存空间
    char d;
    MemWrite((short)(unsigned long)test_buf, 'a');
    d = MemRead((short)(unsigned long)test_buf);
    printf("Hello World,%c",d);
    free(test_buf);
    return 0;
}
  • 如果要验证固定物理地址的读写逻辑,Linux用户态无法满足需求,你可以选择:
    • 编写Linux内核模块,在内核态申请ioremap映射目标地址后测试
    • 直接用QEMU等模拟器加载你的自研OS镜像,在目标运行环境下直接测试,这样和真实上线逻辑完全一致。
  • 额外注意:你当前用的是x86实模式的16位寻址写法,如果你的自研OS后续要切到保护模式,还要对应修改汇编代码的寄存器寻址逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:24:02