汇编语言基本语法(以 x86 为例)
1 汇编语言的基本组成结构
汇编语言是对机器码指令的助记符表示,不同于高级语言的抽象,它直接反映 CPU 的指令集架构。以 x86 汇编为例,程序由**若干段(section)**组成,每段有特定用途:
- 数据段(.data):用于存放已初始化的全局或静态数据
- 未初始化数据段(.bss):用于存放未初始化的全局或静态变量
- 代码段(.text):用于存放程序指令
- 只读数据段(.rodata):存放只读数据,通常是字符串常量
3.1.1 示例汇编文件结构
section .data
hello db 'Hello, world!', 0 ; 定义字符串,以0结束
section .bss
buffer resb 64 ; 申请64字节未初始化空间
section .text
global _start ; 程序入口点,全局可见
_start:
; 程序代码写这里
; ...
2 汇编指令分类与示例
汇编指令可根据功能分为几类:
类别 | 常用指令 | 功能描述 |
---|---|---|
数据传输 | mov, lea, xchg | 寄存器与内存间移动数据 |
算术运算 | add, sub, inc, dec, mul, div | 加减乘除及自增自减 |
逻辑运算 | and, or, xor, not | 位与、位或、异或、取反 |
比较与跳转 | cmp, test, jmp, je, jne, jg, jl | 比较与条件跳转 |
栈操作 | push, pop, call, ret | 栈入栈出栈,函数调用返回 |
控制转移 | jmp, call, ret, loop | 无条件跳转,调用函数,返回 |
其他 | nop, int, syscall | 无操作,中断,系统调用 |
常见指令举例
mov eax, 1 ; 将立即数1放入eax寄存器
add eax, ebx ; eax = eax + ebx
cmp eax, 10 ; 比较eax与10,设置标志位
je label_equal ; 如果相等,跳转到label_equal
jmp label_end ; 无条件跳转
label_equal:
; 执行等于时的代码
label_end:
; 继续执行
3 寄存器详解
x86 架构中寄存器是汇编编程的核心资源。64位模式下(x86-64)主要寄存器:
寄存器 | 说明 |
---|---|
RAX | 累加寄存器,算术运算默认结果寄存器 |
RBX | 基址寄存器,保存基址数据 |
RCX | 计数寄存器,循环控制 |
RDX | 数据寄存器,乘除法操作使用 |
RSI | 源索引寄存器 |
RDI | 目的索引寄存器 |
RBP | 基址指针,栈帧指针 |
RSP | 栈指针 |
R8-R15 | 额外通用寄存器 |
每个寄存器有 64位(RAX)和其低 32/16/8 位访问部分(EAX,AX,AH/AL):
RAX
(64位)EAX
(低32位)AX
(低16位)AH
(高8位)AL
(低8位)
4 操作数类型
汇编指令支持多种操作数类型:
- 立即数(Immediate):常量值,如
mov eax, 1
- 寄存器(Register):如
eax
,rbx
- 内存地址(Memory):间接寻址访问内存数据,格式多样:
mov eax, [rbp-4] ; 访问基址寄存器rbp偏移-4地址的数据
mov rax, [rax+rcx*4+8] ; 复杂寻址模式,基址+索引*比例+偏移
3.5 标签与跳转
标签(label)是代码中跳转的目标标识符,以冒号结尾。跳转指令可用于流程控制:
start:
cmp eax, ebx
je equal_label
jmp end_label
equal_label:
; 执行相等逻辑
jmp end_label
end_label:
; 结束
6 汇编中的伪指令(伪操作)
伪指令不是CPU指令,编译时指导汇编器如何处理数据或代码:
db
— 定义字节dw
— 定义字(2字节)dd
— 定义双字(4字节)dq
— 定义四字(8字节)resb
— 申请未初始化字节空间equ
— 定义常量
示例:
msg db 'Hello, World!', 0
num dw 0x1234
buffer resb 64
7 程序入口与调用规范
在 Linux 下,裸汇编程序一般以 _start
作为入口标签:
global _start
_start:
; 程序开始执行的代码
操作系统调用终止程序用 exit
系统调用(x86-64 Linux 用 syscall
指令):
mov rax, 60 ; exit syscall
xor rdi, rdi ; exit code 0
syscall
8 汇编示例:Hello World(Linux x86-64)
section .data
msg db 'Hello, World!', 10
len equ $ - msg
section .text
global _start
_start:
mov rax, 1 ; syscall: write
mov rdi, 1 ; fd stdout
mov rsi, msg ; msg address
mov rdx, len ; msg length
syscall
mov rax, 60 ; syscall: exit
xor rdi, rdi ; exit code 0
syscall
9 常用调试与汇编查看技巧
使用
nasm
进行汇编汇编:nasm -f elf64 hello.asm -o hello.o
使用
ld
链接生成可执行文件:ld hello.o -o hello
用
objdump
查看反汇编:objdump -d hello
用
gdb
断点调试汇编代码
10 总结
- 汇编语言由段和指令组成,分明的代码结构是清晰编程的基础。
- 掌握基础指令及寄存器用法是汇编编程核心。
- 汇编支持多种寻址方式,灵活操控内存和寄存器。
- 标签与跳转是控制流实现的关键。
- 伪指令帮助数据定义与空间管理。
- 通过示例掌握程序入口和系统调用能快速入门。
- 调试工具是理解汇编执行过程的必要利器。