Assembly Language Sectors

Robert Crowther Jul 2026

Disclaimer: I don’t know much about this. This is a twisted subject. I approach on a superficial level, ‘What should I do when I code?’. This article may be revised, depending on information. At least I ask the questions.

NASM tutorials

See any NASM tutorial and you’ll be shown to structure the file like the following. You’ll also be told what the sections are ‘for’, which I’ve briefly added as comments,

; preamble declarations, such as,
BITS 64

SECTION .data
  ; For initialized data such as,
  db   'hello',13,10        ; a string

SECTION .rodata
  ; For read-only data such as,
  db    0x55                ; one byte 0x55

SECTION .bss
  ; For uninitialised storage space
  buffer: resb  64          ; reserve 64 bytes

SECTION .text
;  For code

  global main
main:
; entry point for code such as,
  push  rbp
  ; ...
  pop   rbp
  mov   rax,0
  ret

Seems clear? Declare variables, then program code. Go look at some Pascal and you’ll find Pascal declares storage and data in a syntactical section. So why would anyone have questions?

These are global variables

Let’s not kid ourselves—data declared in sections can be accessed from anywhere in code blocks. Some will say, well, this is Assembly code, so it’s fine‐grained and simple. I accept that but, before long, you will learn about stack frames and ‘call conventions’ so that Assembly code has a basic notion of scope and that scope is quite important, even if mostly implicit and related to freeing or reusing memory locations.

So what is the use of a ‘global variable’? In most code, it is only for a few ’global’ constants, like π (PI). Easy as it is, it’s better not to keep data globally—especially variables which should be within the smallest scope possible.

ELF format

Linux and a few other operating systems, use an format called ELF. The other operating systems, far as most would care, are systems with some Unix features—PlayStation and Android.

The point is, these ‘sections’ in the Code don’t represent some programming abstraction or syntax. They represent the physical layout in an ELF file.

So is this Unux only?

In wide, no. Microsoft’s Portable Executable format has regions/sections that get mapped to memory. Far as I’ve checked, Microsoft’s Dynamic libraries are much the same as Portable Executables, but minus the executable framework.

Why have sections?

Again, far as I know… Several comments repeat something like this, from Wikipedia on the Windows PE format,

An executable image consists of several different regions, each requiring different memory protection attributes… For instance, the .text section, which contains program code, is typically mapped as an execute/read‐only. Conversely, the .data section, which holds global variables, is mapped as no‐execute/read write.

That’s it, is it? It’s about read/write/executable permissions? And why would that be of interest for code that must be executable and must be writable in places for variable data? Perhaps because it is protection against attacks? And given sectors can only handle in the crudest terms—global variables—is it of use? Before that, here’s something,

Section definition

ELF format is flexible. You can declare your own sections. Which can be defined through NASM. Sections can have what attributes you like. Here are the default attributes given to those sections often written of,

  1. section .text progbits alloc exec nowrite align=16

  2. section .data progbits alloc noexec write align=4

  3. section .bss nobits alloc noexec write align=4

  4. section other progbits alloc noexec nowrite align=1

I will not write of why you might be interested in your own sections. Partly, too much. Partly, I don’t know.

What GCC thinks

You think the above questions, to which I’ve found no simple answer for on the web, are irrelevant? Lets look output from GCC, which ought to represent some kind of wisdom, Here’s a C program to knock ‘hello world’ aside,

int main()
{
    int x = 999;
    return 0;
}

GCC turn the value into an immediate then, with no purpose specified, pokes it on the stack (essential code rewritten somewhat NASM‐like),

mov	DWORD [rbp - 4], 999

Let’s push out the boat,

    static int x = 999;
    return x;

GCC generates a label. Then it uses a position‐independent code leap to visit the label (in GAS output, a RIP offset), loads it this time to a register. More NASM‐like translation,

    mov	eax, label1
    ret

label1:
    999

Let’s try a ‘hello world’ program. This will have two strings (one for a format string also),

#include <stdio.h>

int main()
{
  char x[] = "hello";
  printf("%s", x);
  return 0;
}

NASM‐like representation of what GCC is generating as Assembly,

label1:
  db "%s"

; probs 'hello' as an integer
mov	[rbp + 4], 1819043176
mov	rsi, [rbp + 4]
mov rdi, label1
call [printf wrt ..got]

If I make the string longer, GCC writes integers of string chunks to the stack. Then passes a pointer to the integers into the ‘fprint’ function.

It doesn’t really matter if my description or code is good or not. What it shows is GCC doesn’t use sections.

Why doesn’t GCC use sections?

Ah well, guesswork. For me. But I think the first reason is this. GCC is a compiler to make machine code from C language. It’s clearly got code to make strings into integers, then move the integers wholesale to the stack—maybe not ‘push’ them, but keep track of stack offsets and move the integers into the stack area. Effect is, this handles ‘local’ variables. Then, if GCC gets something that looks like a constant or ‘static’, it uses the label trick to reserve some memory in the ‘text’ sector. And that covers the two needs of ‘local’ variables and a few constants or enduring variables. It seems, in this environment, GCC feels no need to move global variables to sectors. Extra code for no purpose.

Yet the one reason I’ve dug up for sectors having importance is that the different permissions of different sections may be protection for programs. Why does GCC not care about this? Well, this is guesswork again but… protecting a few global variables is not much protection nowadays? People seem to worry much more about stack overflow attacks. And GCC goes to effort here. It warns about executable stacks. It outputs by default as position‐independent code—a big modern initiative against overflow attacks. So it’s not that GCC doesn’t care—it’s possibly that in an x64 environment, this is not the concern.

What does this mean for coding?

As far as I know… there’s no harm using sectors. If you have some massive data, such as big tables, then use of sectors may help the program loader by allowing an executable to be loaded into different places (‘segments’). But for everyday code, it seems there is, in an x64 position‐independent environment, no need for them. All that repeated tutorial information is unnecessary detail about a very small programming case.

Some practical help

Make like GCC. ‘local’ data can be put on stack, where stack framing will automatically remove it. Small data of wider use can be placed using the label trick. Or you could for large volumes and/or more internal organisation malloc space. Heap space, malloc, is less protected and expensive to allocate but much more flexible and universal than sector allocations.

And by the by, this kind of approach works in NASM,

extern printf
...

SECTION .text
formatStr:
  db "%s"
strToPrint:
  db "hello", 10, 0

  global main
main:
  mov rdi, formatStr
  mov	rsi, strToPrint
  call [printf wrt ..got]

Yep, for the labelled data NASM can build data using Dx pseudo‐instructions in the ‘.text’ section. No, these instructions are not locked to sectors. Also, labels are taken as addresses, which printf wants.

References

GAS manual,

https://ftp.gnu.org/old-gnu/Manuals/gas-2.9.1/html_chapter/as_toc.html

ELF intro, by one of the guys who made it,

https://www.linuxjournal.com/article/1060

Difference between sectors and segments,

(https://linuxvox.com/blog/what-s-the-difference-of-section-and-segment-in-elf-file-format/

ELF structure for sections,

https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html