Logo
Articles Compilers Libraries Books MiniBooklets Assembly C++ Linux Others Videos
Advertisement

Article by Ayman Alheraki on January 11 2026 10:37 AM

#13 Mastering GAS A Complete Guide to the GNU Assembler

#13 Mastering GAS: A Complete Guide to the GNU Assembler

 

Series for explaining and teaching GNU GAS Assembler using AT&T syntax – all codes are reviewed and tested daily on

Fedora Linux 42

GNU Assembler version 2.44-6

----------------------------------

Memory Sections in GAS

.bss Section: Storing Uninitialized Data

In the context of low-level programming, particularly when using the GNU Assembler (GAS), the .bss section plays a pivotal role in memory management by handling uninitialized data. It is one of the most important sections in assembly programming and understanding how it works is crucial for efficient memory utilization and the creation of optimized, functional programs. In this section, we will explore the .bss section in great detail, covering its purpose, functionality, advantages, and how it fits within the overall memory layout of a program. Additionally, we will look into various directives used to manipulate the .bss section.

What Is the .bss Section?

The .bss section (Block Started by Symbol) is a segment of memory reserved for uninitialized global or static variables. These variables are declared but not given a predefined value in the source code. The primary advantage of the .bss section is that it allows programs to allocate space for these variables without actually including the initial values in the binary file. Instead, when the program is loaded into memory, the operating system initializes this space, typically setting the values to zero (or a platform-specific default).

In the binary file, the .bss section does not contribute any data. Its role is purely to indicate that a certain portion of memory needs to be reserved. The actual memory is allocated by the operating system when the program is loaded into the memory space. This differs from the .data section, where values are stored directly in the executable, contributing to the file's size.

Purpose and Benefits of the .bss Section

The .bss section provides several important benefits when managing uninitialized variables:

a. Memory Efficiency

One of the primary advantages of the .bss section is memory efficiency. Since the .bss section does not store any actual data in the executable file, it allows a program to reserve memory without increasing the size of the binary. When a program is compiled, the .bss section only defines the size of the space required, not the actual data to be stored. The operating system allocates the required space in memory when the program is loaded and initializes it to a default value (usually zero).

For example, when you declare a global variable in the .bss section like so:

This tells the assembler to reserve 4 bytes of memory for my_var without storing any specific value in the executable. The value is initialized at runtime, saving both space in the binary and avoiding the unnecessary storage of large amounts of uninitialized data.

b. Runtime Initialization

The .bss section is initialized at runtime. When the program is loaded into memory, the operating system ensures that all uninitialized data in the .bss section is zeroed out (or initialized to a default value). This is particularly useful for ensuring that variables do not contain garbage values when the program begins execution. For example, in C/C++ programming, global static variables that are declared but not initialized are typically placed in the .bss section.

c. Zero Initialization

One of the key features of the .bss section is that the operating system automatically initializes the reserved space to zero (or another default value, depending on the system). This means that any variable in the .bss section is guaranteed to start with a neutral value, which is often zero, simplifying the initialization process for variables.

Directives Used in the .bss Section

The .bss section can be manipulated using several directives within GAS. These directives provide the programmer with the tools to reserve memory for uninitialized variables.

a. .skip Directive

The .skip directive is used to reserve a specific number of bytes in the .bss section. It is the most common directive used to allocate memory without initializing it. For example:

Here, .skip 4 tells the assembler to reserve 4 bytes of memory for the variable my_var. This space will be zeroed out by the operating system when the program is loaded.

b. .space Directive

The .space directive, like the .skip directive, is used to reserve space in the .bss section, but it may be preferred for aligning purposes. The .space directive reserves a specific number of bytes and is used in scenarios where you need to explicitly define the size of the memory block:

In this example, the .space directive reserves 64 bytes of uninitialized memory for the buffer variable. As with the .skip directive, the operating system will initialize this space to zero at runtime.

c. .comm Directive

The .comm directive is used to define common symbols in the .bss section. These common symbols can be shared between multiple object files, which is useful in larger programs spread across several source files. The .comm directive allocates a block of space for the symbol and ensures that the space is shared across all object files that reference it.

This line reserves 256 bytes for my_array and ensures that the memory space is shared among all the files that reference this symbol. This is especially useful for large programs where memory for global variables needs to be allocated dynamically.

How the .bss Section Fits into the Memory Layout

The .bss section is part of the data segment of a program's memory layout. A typical memory layout consists of several segments that serve different purposes:

  • Text Segment: Contains the executable code (instructions).

  • Data Segment: Stores initialized variables and constants (the .data section).

  • BSS Segment: Allocates space for uninitialized global variables (the .bss section).

  • Heap: A region used for dynamic memory allocation (managed during runtime).

  • Stack: A region for local variables, function call frames, and storing return addresses.

The .bss section resides between the data segment and the heap. When a program is loaded, the operating system allocates space in the .bss section, initializing the memory to zero (or another default value). This makes it easier to manage uninitialized data by having the OS handle the initialization.

Accessing Data in the .bss Section

Once the memory for the .bss section has been allocated at runtime, it can be accessed and manipulated in the same way as variables in other sections like the .data or .text sections. The main difference is that, in the .bss section, the variables are not initialized with any values in the source code, so they are empty until explicitly assigned a value during execution.

For example, if a program defines a variable in the .bss section and wishes to store a value in it during execution, the following steps would occur:

  1. The .bss section reserves space for the variable.

  2. The program loads a value into a register (e.g., eax).

  3. The program stores the value from the register into the variable in the .bss section.

In this example:

  • The .bss section reserves 4 bytes of memory for the my_counter variable.

  • The program stores the value 100 into the my_counter variable during execution.

  • The program exits using a system call.

Comparing the .bss Section with the .data Section

A comparison between the .bss section and the .data section can help clarify their roles in a program:

  • .data Section: Stores initialized data, i.e., variables that have predefined values.

    • Example: A string with a predefined value, like msg: .asciz "Hello, World!".

    • Size: The size of the data contributes to the size of the executable binary.

  • .bss Section: Stores uninitialized data, i.e., variables that are declared but not initialized with values.

    • Example: A variable declared as counter: .skip 4.

    • Size: The size of the data does not contribute to the size of the binary file since it is only reserved in memory during runtime.

In essence, while both sections store variables, the .bss section is used for memory allocation without the need to include large amounts of zeroed or uninitialized data in the binary, whereas the .data section includes actual data values.

Example of a Program Using the .bss Section

Consider the following simple example of using the .bss section to store and manipulate uninitialized data:

Conclusion

The .bss section is essential for managing uninitialized global and static data in a program. It allows efficient memory allocation, reducing binary size and ensuring that variables are initialized to zero or another default value when the program starts. By understanding how the .bss section works and how to use directives such as .skip, .space, and .comm, developers can create highly optimized and efficient programs. Moreover, the .bss section plays a significant role in the overall memory layout of a program, sitting between the data segment and heap, and helping manage uninitialized variables that are crucial for a program’s execution.

 

Advertisements

Responsive Counter
General Counter
1000725
Daily Counter
2345