Assembly Language - Variables

Variables are the basic units for storing data in a program. Defining and using variables in assembly language is closer to the underlying hardware than in high-level languages; you need to directly control the size, type, and memory layout of variables.


Variable Concept in Assembly

In assembly language,a variableis essentially a named storage location in memory.

Unlike high-level languages, assembly variables have no automatic type checking—a label is just an alias for a memory address, and you can read or write it using any size.

NASM provides three sections to store different types of variables:.data(initialized),.bss(uninitialized), and.rodata(read-only).


Defining initialized variables in the .data section

Use the DB, DW, DD, DQ, DT directives to define variables of different sizes:

DirectiveData sizeMeaningExample
DB1 byteDefine Byteflag db 1
DW2 bytesDefine Wordcount dw 1000
DD4 bytesDefine Doublewordprice dd 9999
DQ8 bytesDefine Quadwordbig_val dq 0x1234567890ABCDEF
DT10 bytesDefine Ten Bytesext_val dt 3.14

Example

; File path: variables_data.asm
; Demonstrate defining various variables in the .data section

section .data
    ; Byte variable
    status db 1                 ; 1 byte, value 1
    grade db 'A'                ; 1 byte, character 'A' = 0x41

    ; Word variable (2 bytes)
    year dw 2026                ; 2 bytes, value 2026

    ; Doubleword variable (4 bytes)
    salary dd 50000             ; 4 bytes, value 50000

    ; Multi-byte sequence
    msg db 'Hello, example!', 0  ; Zero-terminated string (C-style)
    hex_bytes db 0x55, 0xAA, 0x00, 0xFF   ; Hexadecimal byte sequence

    ; Repeated value
    stars db 10 dup('*')        ; 10 asterisk characters

    ; Multiple variables with names
    x dd 10
    y dd 20
    z dd 30

section .text
    global _start

_start:
    ; Read variable values into registers
    mov al, [status]            ; al = 1 (read 1 byte)
    mov ax, [year]              ; ax = 2026 (read 2 bytes)
    mov eax, [salary]           ; eax = 50000 (read 4 bytes)

    ; Modify variable values
    mov byte [status], 0        ; status = 0
    mov dword [x], 100          ; x = 100

    mov eax, 1
    mov ebx, 0
    int 0x80

Use[variable name]When accessing a variable, be sure to ensure that the number of bytes read/written matches the size defined for the variable. Usemov al, [status]to read 1 byte, usemov eax, [salary]to read 4 bytes. NASM checks that operand sizes match.


Reserving uninitialized space in the .bss section

Use directives such as RESB, RESW, RESD to reserve space (without initializing):

DirectiveReserved sizeExample
RESBbytebuffer resb 256
RESWword (2 bytes)wbuf resw 100
RESDdoubleword (4 bytes)dbuf resd 50
RESQquadword (8 bytes)qbuf resq 25

Example

; File path: variables_bss.asm
; Demonstrate reserving space in the .bss section

section .bss
    input_buf resb 128          ; Reserve a 128-byte input buffer
    numbers resd 100            ; Reserve 100 doublewords (400 bytes)
    temp resb 1                 ; Reserve a 1-byte temporary variable

section .data
    prompt db 'Enter a number: '
    prompt_len equ $ - prompt

section .text
    global _start

_start:
    ; Output prompt
    mov eax, 4
    mov ebx, 1
    mov ecx, prompt
    mov edx, prompt_len
    int 0x80

    ; Read input into the buffer in the .bss section
    mov eax, 3
    mov ebx, 0
    mov ecx, input_buf           ; Use the space reserved in the .bss section
    mov edx, 128
    int 0x80

    ; Fill data into the numbers array
    mov dword [numbers], 42      ; numbers[0] = 42
    mov dword [numbers + 4], 100 ; numbers[1] = 100

    mov eax, 1
    mov ebx, 0
    int 0x80

Memory layout of bytes, words, and doublewords

x86 useslittle-endian (Little Endian)—the low byte is stored at the low address.

For example, when definingvalue dd 0x12345678the memory layout is:

地址    :[value]  [value+1]  [value+2]  [value+3]
内容    :0x78     0x56       0x34       0x12

Example

; File path: endianness.asm
; Demonstrating little-endian storage

section .data
    value dd 0x12345678        ; Double word, 4 bytes

section .text
    global _start

_start:
    ; Reading the same variable at different sizes
    mov eax, [value]            ; Read 4 bytes: eax = 0x12345678
    mov ax, [value]             ; Read 2 bytes: ax = 0x5678 (low 2 bytes)
    mov al, [value]             ; Read 1 byte: al = 0x78 (lowest byte)

    ; Verify little-endian: lower addresses store lower-order bytes
    mov al, [value]             ; al = 0x78
    mov bl, [value + 1]         ; bl = 0x56
    mov cl, [value + 2]         ; cl = 0x34
    mov dl, [value + 3]         ; dl = 0x12

    mov eax, 1
    mov ebx, 0
    int 0x80

Initialization and access of variables

In assembly, variable operations follow the three-step pattern of "load-operate-store":

Example

; File path: var_operations.asm
; Demonstrating the three-step pattern of variable operations

section .data
    a dd 100
    b dd 200
    result dd 0

section .text
    global _start

_start:
    ; result = a + b
    ; Step 1: Load
    mov eax, [a]                ; Load a into eax
    ; Step 2: Operate
    add eax, [b]                ; eax = eax + b
    ; Step 3: Store
    mov [result], eax           ; Store the result to result

    ; result = a * 2 - b
    mov eax, [a]
    imul eax, 2                 ; eax = a * 2
    sub eax, [b]                ; eax = eax - b
    mov [result], eax

    mov eax, 1
    mov ebx, 0
    int 0x80

Assembly does not supportmov [result], [a] + [b]this high-level syntax. The x86 mov instruction cannot use two memory operands at the same time; it must go through a register as an intermediary.


Variable size operators

When the assembler cannot infer the operand size, it must be specified explicitly:

Example

; Use size operators to clarify data size

section .data
    var dd 0

section .text
    global _start

_start:
    ; Size operators: byte, word, dword, qword
    mov byte [var], 1           ; Write 1 byte
    mov word [var], 1000        ; Write 2 bytes
    mov dword [var], 999999     ; Write 4 bytes

    ; When the destination size is clear (determined by the register), it can be omitted
    mov al, [var]               ; al is 1 byte, automatically read as byte
    mov ax, [var]               ; ax is 2 bytes, automatically read as word
    mov eax, [var]              ; eax is 4 bytes, automatically read as dword

    ; But the following line will cause an error (size is ambiguous):
    ; mov [var], 1 ; Error! 1 could be byte/word/dword
    ; It must be written as:
    mov dword [var], 1          ; Explicitly specify 4 bytes

    mov eax, 1
    mov ebx, 0
    int 0x80
Other extensions