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

GNU汇编.data段result值执行syscall后损坏,求排查原因

问题原因与解决方案

1. 错误的段布局:.lcomm指令不能放在.data段内

.lcomm是GNU汇编中用于在bss段分配本地未初始化存储的指令,它不应该被放在.data段(初始化数据段)中。强行将.lcomm混入.data段会导致汇编器错误地混合初始化与未初始化数据的内存布局,破坏预期的内存结构,进而引发意外的数据损坏。

正确的段划分方式应该是:

.data
result: .byte 1  # 初始化数据放在.data段

.bss
.lcomm input 1   # 未初始化数据放在.bss段
.lcomm cha 2

2. x86_64环境下误用32位系统调用接口(int $0x80)

你当前使用的是32位系统调用接口,但运行环境是x86_64架构的Debian。虽然Linux内核提供32位兼容接口,但在64位程序中使用它可能会引发寄存器处理、内存地址解析等兼容性问题,甚至意外改写内存数据。

对于x86_64程序,应当使用原生的64位系统调用接口(syscall指令),对应的调用号和寄存器约定完全不同:

  • 系统调用号存储在rax寄存器中
  • 参数依次存入rdi, rsi, rdx, r10, r8, r9寄存器
  • 返回值会被写入rax

修改后的read与exit系统调用代码示例:

.global _start
_start:
    # 64位read系统调用:读取1字节到input
    mov $0, %rax        # 64位read调用号为0
    mov $0, %rdi        # 文件描述符0:标准输入
    mov $input, %rsi    # 缓冲区地址
    mov $1, %rdx        # 读取字节数
    syscall             # 执行64位系统调用

    # 64位exit系统调用:退出程序,返回码0
    mov $60, %rax       # 64位exit调用号为60
    mov $0, %rdi        # 程序返回码
    syscall

为什么result会被意外改写?

当你错误地将.lcomm放在.data段时,input的内存位置紧邻result之后,再结合32位系统调用的寄存器处理漏洞(比如64位寄存器高32位未清零导致地址解析错误),内核在处理系统调用时可能意外将数据写入了result的地址。修复段布局并改用64位系统调用接口后,这个问题就能解决。

调试时可以用gdb查看内存状态,比如用x/b &result查看result的字节值,x/b &input查看input的字节值,确认内存布局是否符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:57:51