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

Linux下NASM小型x86 ELF二进制可修改预留内存问题排查

解决NASM极简ELF中.bss段写入段错误的问题

核心原因

你用的极简ELF(类似teensy的小二进制)默认程序头可能没正确处理.bss段:要么加载器没为.bss分配可写内存,要么内存权限被设为只读,导致写入操作触发段错误。

具体修复步骤

  1. 修正ELF程序头的内存大小与权限
    极简ELF通常只有一个PT_LOAD程序头,必须确保:

    • p_flags包含PF_W(可写)权限,一般设为7(PF_R | PF_W | PF_X)
    • p_memsz要包含.bss段的大小,因为.bss在二进制中是0长度,加载器需要知道要额外分配多少内存并清零。
      示例程序头修改:
    phdr:
      dd 1          ; PT_LOAD
      dd 0          ; 文件偏移
      dd $$         ; 虚拟地址
      dd $$         ; 物理地址
      dd filesize   ; 文件大小(.text+.data的总长度)
      dd filesize + 342  ; 内存大小 = 文件大小 + .bss的19*18字节
      dd 7          ; 权限:读+写+执行
      dd 0x1000     ; 对齐
    
  2. 正确声明.bss段
    单独声明.bss段,不要和.text/.data混放:

    section .text
    ; 你的代码、预定义字符串等放在这里
    ...
    
    section .bss
    printable: resb 19*18  ; 预留342字节的可写内存
    
  3. 确保地址访问正确
    如果是静态链接的绝对地址,直接用printable符号即可;如果是位置无关代码,需要通过基址计算(比如用ebx获取程序基址后偏移)。示例写入代码:

    ; 把printable缓冲区填满字符'X'
    mov edi, printable
    mov ecx, 19*18
    mov al, 'X'
    rep stosb
    
    ; 打印缓冲区内容
    mov eax, 4
    mov ebx, 1
    mov ecx, printable
    mov edx, 19*18
    int 0x80
    

关键说明

  • 原错误中操作string1也段错误,大概率是因为string1放在了只读的.text段里,.text段默认权限是执行+只读,写入自然会报错——只有.bss和.data段应该设为可写。
  • 极简ELF没有链接器帮你处理段属性,必须手动在程序头中指定内存权限和大小,加载器才会正确分配可写的.bss内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 12:03:39