汇编语言是一种低级语言,与计算机的硬件架构密切相关,用于直接控制硬件。以下是汇编语言的基本语法及相关概念,基于 x86/x86-64 架构(适用于 NASM、MASM 等汇编器)。
一、汇编语言的基本结构
1.1 程序结构
汇编程序通常分为以下几部分:
- 数据段 (
data
): 定义全局变量和常量。
- 代码段 (
code
): 包含可执行指令。
- 堆栈段 (
stack
): 管理函数调用和本地变量。
示例:基本结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| section .data ; 数据段 message db "Hello, World!", 0
section .bss ; 未初始化数据段 buffer resb 64 ; 预留64字节的内存
section .text ; 代码段 global _start ; 声明程序入口点 _start: ; 程序开始位置 mov eax, 4 ; 系统调用:write mov ebx, 1 ; 文件描述符:stdout mov ecx, message ; 消息地址 mov edx, 13 ; 消息长度 int 0x80 ; 调用内核 mov eax, 1 ; 系统调用:exit xor ebx, ebx ; 返回码 0 int 0x80 ; 调用内核
|
二、基本语法
2.1 指令格式
汇编指令通常由以下部分组成:
- 标签: 可选,用于定义位置,类似标记。
- 指令: 汇编指令,如
mov
, add
, sub
。
- 操作数: 可以是寄存器、内存地址或立即数。
示例
1 2 3
| start: ; 标签 mov eax, 10 ; 将立即数 10 移动到 eax 寄存器 add eax, 5 ; eax = eax + 5
|
2.2 数据定义
- 在
.data
段中定义初始化的数据。
- 在
.bss
段中定义未初始化的数据。
伪指令 |
描述 |
示例 |
db |
定义字节(8位) |
var1 db 10 |
dw |
定义字(16位) |
var2 dw 1000 |
dd |
定义双字(32位) |
var3 dd 12345678h |
dq |
定义四字(64位) |
var4 dq 1234567890h |
resb |
分配字节(未初始化) |
buffer resb 64 |
resw |
分配字(未初始化) |
array resw 10 |
2.3 寄存器
通用寄存器
寄存器 |
说明 |
示例 |
eax |
累加器 |
mov eax, 5 |
ebx |
基址寄存器 |
mov ebx, eax |
ecx |
计数器寄存器 |
loop_start: ... |
edx |
数据寄存器 |
mov edx, 100 |
栈指针与基址指针
寄存器 |
说明 |
esp |
栈顶指针 |
ebp |
基址指针(函数调用中使用) |
2.4 指令类型
数据传输指令
用于在寄存器、内存和立即数之间传递数据。
指令 |
功能 |
示例 |
mov |
数据传输 |
mov eax, 10 |
lea |
加载地址 |
lea esi, [var1] |
xchg |
交换数据 |
xchg eax, ebx |
push |
压入栈 |
push eax |
pop |
弹出栈 |
pop eax |
算术指令
用于执行加减乘除等运算。
指令 |
功能 |
示例 |
add |
加法 |
add eax, 5 |
sub |
减法 |
sub eax, 3 |
imul |
有符号乘法 |
imul eax, ebx |
idiv |
有符号除法 |
idiv ecx |
inc |
自增 |
inc eax |
dec |
自减 |
dec ebx |
逻辑指令
用于位操作和逻辑判断。
指令 |
功能 |
示例 |
and |
按位与 |
and eax, 0xF0 |
or |
按位或 |
or eax, 0x01 |
xor |
按位异或 |
xor eax, eax |
not |
按位取反 |
not eax |
shl |
左移 |
shl eax, 2 |
shr |
右移 |
shr eax, 1 |
跳转指令
用于流程控制。
指令 |
功能 |
示例 |
jmp |
无条件跳转 |
jmp label |
je /jne |
等于跳转/不等跳转 |
je equal_label |
jg /jl |
大于跳转/小于跳转 |
jg greater_label |
loop |
循环跳转 |
loop loop_start |
2.5 栈操作
栈是一种后进先出的数据结构,用于函数调用或数据存储。
压栈和弹栈
1 2
| push eax ; 将 eax 压入栈 pop ebx ; 将栈顶值弹出到 ebx
|
函数调用
1 2
| call myFunction ; 调用函数 ret ; 返回调用点
|
2.6 条件判断
结合跳转指令和比较指令实现条件判断。
1 2
| cmp eax, ebx ; 比较 eax 和 ebx je equal_label ; 如果相等则跳转到 equal_label
|
三、示例代码
3.1 Hello World
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| section .data msg db "Hello, World!", 0
section .text global _start
_start: mov eax, 4 ; 系统调用号:write mov ebx, 1 ; 文件描述符:stdout mov ecx, msg ; 消息地址 mov edx, 13 ; 消息长度 int 0x80 ; 调用内核 mov eax, 1 ; 系统调用号:exit xor ebx, ebx ; 返回值 0 int 0x80 ; 调用内核
|
3.2 加法运算
1 2 3 4 5 6 7 8 9 10 11 12
| section .data result db 0 ; 存储结果
section .text global _start
_start: mov al, 5 ; 加数1 add al, 10 ; 加数2 mov [result], al ; 将结果存入 result mov eax, 1 ; 系统调用号:exit int 0x80 ; 调用内核退出
|
3.3 条件跳转
section .text
global _start
_start:
mov eax, 5
mov ebx, 10
cmp eax, ebx ; 比较 eax 和 ebx
jl less_label ; 如果 eax < ebx,跳转
jmp end_label
less_label:
; eax 小于 ebx 的逻辑