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:
| Directive | Data size | Meaning | Example |
|---|---|---|---|
| DB | 1 byte | Define Byte | flag db 1 |
| DW | 2 bytes | Define Word | count dw 1000 |
| DD | 4 bytes | Define Doubleword | price dd 9999 |
| DQ | 8 bytes | Define Quadword | big_val dq 0x1234567890ABCDEF |
| DT | 10 bytes | Define Ten Bytes | ext_val dt 3.14 |
Example
; 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):
| Directive | Reserved size | Example |
|---|---|---|
| RESB | byte | buffer resb 256 |
| RESW | word (2 bytes) | wbuf resw 100 |
| RESD | doubleword (4 bytes) | dbuf resd 50 |
| RESQ | quadword (8 bytes) | qbuf resq 25 |
Example
; 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
; 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
; 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 support
mov [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
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