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

GNU汇编中如何在偏移量中使用立即数?求助解决相关错误

问题分析与解决建议

错误原因拆解

第一个代码的编译错误

你写的movq $50, mem($3)是错误的AT&T语法:

  • x86_64 AT&T语法中,直接指定偏移量访问符号地址的正确格式是mem+3(或3+mem),而非mem($3)。
  • 另外,你要写入的是单个字节,用movq会一次性写入8字节,覆盖后续7个字节,应该用movb指令。

第二个代码的段错误

movq mem, %rbx是错误的:

  • AT&T语法中,不加$表示访问该地址的内容,而非取地址。mem在.bss段初始值为0,这条指令会把0加载到%rbx,后续访问3(%rbx)就是访问虚拟地址3,属于非法内存,触发段错误。
  • 正确取地址的写法是movq $mem, %rbx(加$表示立即数,即mem的地址)。
  • 同样,写入单个字节应该用movb而非movq。

正确实现方案

方案1:直接用符号+偏移量(无需寄存器,符合你的需求)

利用x86_64的PC相对寻址,直接通过符号+偏移访问内存,无需额外寄存器:

.bss
mem:
    .zero 30000  # 30KB空字节串
    .text
    .globl main
main:
    pushq %rbp
    movq %rsp, %rbp
    movb $50, mem+2  # 注:字节索引从0开始,第3个字节对应偏移2;若你是从1计数的第3个字节,此处用+2
    movzbl mem+2, %edi  # 读取该字节并零扩展到%edi(putchar需要int类型参数)
    call putchar
    leave
    ret  # main函数需返回,补充ret指令避免未定义行为

方案2:用寄存器保存地址(适合多次复用地址的场景)

如果需要多次访问mem,可以先把地址存入寄存器,注意正确的取地址写法和字节操作:

.bss
mem:
    .zero 30000
    .text
    .globl main
main:
    pushq %rbp
    movq %rsp, %rbp
    movq $mem, %rbx  # 把mem的地址加载到%rbx(加$表示立即数)
    movb $50, 2(%rbx)  # 写入第3个字节(偏移2)
    movzbl 2(%rbx), %edi
    call putchar
    leave
    ret

关键注意点

  • AT&T语法中,立即数必须加$,符号地址取地址时也要加$,否则是访问该地址的内容。
  • 操作单个字节用movb,操作双字用movl,四字用movq,避免不必要的内存覆盖。
  • main函数最后必须加ret指令返回,否则会导致未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 23:15:34