Assembly Language - Basic Syntax
This chapter introduces the basic structure, syntax rules, and writing conventions of NASM assembly programs, helping you understand the skeleton of assembly code.
Basic structure of an assembly program
A complete NASM assembly program usually consists of the following parts:
Example
; Example of basic NASM program structure
section .data ; Data section: stores initialized data
; Define variables and constants here
msg db 'Hello, EXAMPLE!', 0xA
len equ $ - msg
section .bss ; BSS section: stores uninitialized data
; Reserve memory space here
buffer resb 64 ; Reserve a 64-byte buffer
section .text ; Code section: stores executable instructions
global _start
_start:
; Write program logic here
mov eax, 4
mov ebx, 1
mov ecx, msg
mov edx, len
int 0x80
mov eax, 1
mov ebx, 0
int 0x80
| Section | Purpose | Characteristics |
|---|---|---|
.data | Stores initialized global variables and constants | Size and content determined at compile time, stored in the executable file |
.bss | Stores uninitialized global variables | Space is allocated only at runtime, does not occupy executable file size |
.text | Stores executable machine instructions | Read-only, contains all the program's logic code |
At least
.textsections are required to form a valid assembly program. If there is no data, can omit the.dataand.bsssection.
Assembly statement format
The general format of each assembly statement is:
[标签:] 指令助记符 [操作数1 [, 操作数2 [, 操作数3]]] [; 注释]
Explanation of each part:
| Part | Required? | Description |
|---|---|---|
| Label | Optional | A symbolic name representing a memory address, ending with a colon |
| Instruction mnemonic | Required | Such as mov, add, sub, etc., tells the CPU what to do |
| Operand | Optional (some instructions have no operand) | The data object operated on by the instruction, can be a register, memory address, or immediate value |
| Comment | Optional | Starts with a semicolon and continues to the end of the line |
Example
; Instruction only, no operand
ret ; Return from subroutine
; Instruction + single operand
push eax ; Push the value of eax onto the stack
inc ecx ; Add 1 to ecx
; Instruction + two operands (most common)
mov eax, 42 ; Copy 42 into the eax register
add ebx, ecx ; ebx = ebx + ecx
; With a label
loop_start: ; Label: marks the start of the loop
dec ecx ; Subtract 1 from ecx
jnz loop_start ; If ecx is not 0, jump back to loop_start
Comment conventions
NASM usessemicolon (;)to denote comments; content from the semicolon to the end of the line is ignored by the assembler.
Example
; Calculate the sum of two numbers and output the result
mov eax, 10 ; Inline comment: put 10 into eax
add eax, 20 ; Inline comment: add 20 to eax, now eax = 30
Comments are extremely important in assembly code. Without comments, even the author may not understand the assembly code after a few weeks. Develop the habit of writing a comment for every instruction.
Identifier naming rules
Identifiers (labels, variable names, constant names, etc.) must follow the following rules:
| Rule | Description |
|---|---|
| Composition characters | Letters, digits, underscore _, dot ., question mark ?, @, $, #, etc. |
| Starting character | Must begin with a letter, underscore, dot, or question mark; cannot begin with a digit. |
| Case sensitivity | Case-sensitive by default (can be modified via compilation options) |
| Reserved words | Cannot have the same name as instruction mnemonics, register names, or NASM keywords. |
Example
my_variable: ; Starts with a letter + underscore
.loop_start: ; Starts with a dot (local label)
?error_handler: ; Starts with a question mark
counter2: ; Letter + digit
; Illegal identifiers (for reference only, do not use)
; 1st_value: ; Error: cannot start with a digit
; mov: ; Error: mov is a reserved word
; my-variable: ; Error: hyphen is not a legal character
Pseudo-instructions (Directives)
DirectivesAre commands to the assembler, not instructions to the CPU; they control the assembly process and define data structures.
| Directives | Purpose | Example |
|---|---|---|
db | Define byte (1 byte) | byte_val db 0x55 |
dw | Define word (2 bytes) | word_val dw 0x1234 |
dd | Define double word (4 bytes) | dword_val dd 0x12345678 |
equ | Define constant | MAX_SIZE equ 256 |
resb | Reserve byte space | buffer resb 128 |
resw | Reserve word space | wbuf resw 64 |
resd | Reserve double word space | dbuf resd 32 |
%define | Macro-defined constant | %define COUNT 10 |
Case conventions
NASM, by default, for labels and identifiersis case-sensitive.:
Example
section .data
msg db 'EXAMPLE', 0 ; Define variable msg
section .text
global _start
_start:
mov eax, MSG ; Error: MSG and msg are different (unless case-insensitive mode is enabled)
mov eax, msg ; Correct: msg exactly matches the definition
MOV EAX, 42 ; Syntactically correct: instruction mnemonics are case-insensitive
mov eax, 42 ; Recommended style: use lowercase for better readability
Instruction mnemonics and register names are case-insensitive (
MOV、Mov、movsame effect), but the recommended style is uniformly lowercase.
Numeric representation
NASM supports numeric representation in multiple bases:
Example
mov eax, 42 ; Decimal: write the number directly
mov eax, 0x2A ; Hexadecimal: 0x prefix (recommended style)
mov eax, 2Ah ; Hexadecimal: h suffix
mov eax, 0o52 ; Octal: 0o prefix
mov eax, 52o ; Octal: o suffix
mov eax, 101010b ; Binary: b suffix
mov eax, 0b101010 ; Binary: 0b prefix
Recommended:
0xuse prefix for hexadecimal (e.g.,0x2A), so it is less likely to be confused with labels.
A complete syntax example
The following program comprehensively uses the above syntax elements to calculate the sum of 1 to 10 and output it:
Example
; Calculate 1+2+...+10 and output the resulting character
section .data
result db 0 ; Store the calculation result (1 byte)
newline db 0xA ; Newline character
section .text
global _start
_start:
; Initialize registers and variables
mov ecx, 10 ; Loop counter: count down from 10
mov eax, 0 ; eax stores the accumulated sum, initially 0
sum_loop: ; Loop start label
add eax, ecx ; eax = eax + ecx
dec ecx ; ecx decremented by 1
jnz sum_loop ; If ecx != 0, continue the loop
; At this point eax = 55 (10+9+...+1)
add eax, '0' ; Convert number to ASCII character ('0'=48, 55+48=103='g', incorrect)
; Actual demonstration requires more complex conversion, see later chapters
; Here only output result (simplified demonstration)
mov [result], al ; Store the accumulated result into result
; Exit program
mov eax, 1
mov ebx, 0
int 0x80
Other extensionsNote: In the above example, adding '0' directly is only correct when the number is in the range 0-9. Converting numbers with two or more digits will be explained in detail in later chapters.