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

ELF64中.data与.bss段内存顺序及汇编语法问询

Great questions—ELF section ordering and assembly-time size calculations are easy to take for granted, but it's smart to verify when your code depends on specific memory layouts. Let's break this down clearly.

1. Are .bss addresses always after .data in ELF64?

The ELF64 specification does not formally mandate a fixed order for .data and .bss sections. However, every mainstream linker (like GNU ld, the default for most Linux systems) follows a standard, efficient layout where:

  • .data (initialized read-write data) is placed first in the process's data segment
  • .bss (uninitialized zero-filled read-write data) follows immediately after .data

This default comes from standard linker scripts, which group these sections into a single contiguous memory region. The OS can optimize .bss by mapping zero-filled pages without loading data from disk, so placing it after .data keeps related read-write memory together.

For your specific code:

section .data
malloc_pointer: dq start_of_my_malloc
start_of_data:
; ... more data content ...
section .bss
start_of_my_malloc: resb 1 << 30 ; Pre-allocate 1GB

Under default linking, start_of_my_malloc will definitely be at a higher address than start_of_data, so [malloc_pointer] - start_of_data will be positive.

Caveat: If you use a custom linker script, you could reorder sections. If you need absolute certainty, check your linker script or explicitly enforce the order by placing .data and .bss in the same output section.

2. Can you use start_of_data to calculate resb size?

Your original attempt resb (1 << 30) - start_of_data fails because:

  • resb is an assembler (e.g., NASM) pseudo-instruction that calculates sizes at assembly time, not link time.
  • start_of_data is a label in the .data section—at assembly time, the assembler doesn't know the final memory offset between .data and .bss (that's determined by the linker later).

Here's how to fix this using linker-provided symbols, which resolve at link time:

Solution for NASM + GNU ld

  1. Declare the linker-provided symbol for the end of .data as external in your assembly:
    EXTERN __data_end__ ; GNU ld defines this as the address right after .data ends
    
  2. Calculate the reserved size using this symbol (the assembler generates a relocation for the linker to resolve):
    section .bss
    start_of_my_malloc: resb (1 << 30) - (__data_end__ - start_of_data)
    

This works because __data_end__ - start_of_data is the total size of your .data section, which the linker can compute once it knows the final memory layout. Note: Some toolchains use alternative symbols like _edata—adjust if needed.

Alternative: Custom Linker Script

For full control, define a symbol for the size of .data in your linker script:

SECTIONS {
  /* ... other section definitions ... */
  .data : {
    start_of_data = .;
    *(.data)
    data_size = SIZEOF(.data);
  }
  .bss : {
    *(.bss)
  }
}

Then reference this symbol in your assembly:

EXTERN data_size
start_of_my_malloc: resb (1 << 30) - data_size

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:18:42