第五节 汇编语言基础
(第1章 安卓逆向概论)
学习目标
学完本节,希望你能够:搞清汇编是啥、在计算机里干啥;会 x86、ARM、Smali 三种汇编的基础;掌握寄存器、指令、数据传输、运算、控制流;能对照 C 看汇编、跑简单汇编程序;知道汇编在逆向和漏洞利用里咋用。
一、汇编语言是啥?
汇编语言(Assembly Language) 说白了就是:用助记符代替二进制指令的「低级语言」,方便人写、人读,和 CPU 指令一一对应。
| 语言层级 | 示例 |
|---|---|
| 高级语言(C、Python) | int a = 5; |
| 汇编语言(x86、ARM) | MOV R0, #5 |
| 机器码(16 进制指令) | B8 05 00 00 00 |
汇编语言与特定 CPU 指令集紧密相关,如:
- x86 汇编(Intel、AMD 处理器)
- ARM 汇编(移动设备、嵌入式设备)
- Smali 汇编(Android DEX 字节码)
二、x86 汇编基础
x86 处理器架构
x86 采用 CISC(复杂指令集计算机) ,支持 可变长指令 和 丰富的寻址模式。
x86 32 位(IA-32)寄存器
| 寄存器 | 用途 |
|---|---|
| EAX | 累加器(运算/返回值) |
| EBX | 基址寄存器 |
| ECX | 计数寄存器(循环) |
| EDX | 数据寄存器 |
| ESI | 源索引寄存器 |
| EDI | 目标索引寄存器 |
| EBP | 栈基址指针 |
| ESP | 栈指针 |
x86 指令示例
assembly
section .text
global _start
_start:
mov eax, 5 ; EAX = 5
add eax, 10 ; EAX = EAX + 10
sub eax, 2 ; EAX = EAX - 2
int 0x80 ; 系统调用
特点:
mov eax, 5:将 5 赋值给eax。add eax, 10:对eax进行加法运算。int 0x80:调用 Linux 系统 API。
三、ARM 汇编基础
ARM 处理器架构
ARM 采用 RISC(精简指令集计算机) ,指令长度固定,执行效率更高,广泛用于 移动设备和嵌入式系统。
ARMv7(ARM32)寄存器
| 寄存器 | 用途 |
|---|---|
| R0-R3 | 传递函数参数 |
| R4-R11 | 通用寄存器 |
| R12 | 过程调用寄存器 |
| R13 | 栈指针(SP) |
| R14 | 链接寄存器(LR) |
| R15 | 程序计数器(PC) |
ARMv8(ARM64)寄存器
| 寄存器 | 用途 |
|---|---|
| X0-X7 | 传递参数和返回值 |
| X8 | 系统调用 |
| X9-X15 | 临时变量 |
| X19-X30 | 通用寄存器 |
| X30 (LR) | 链接寄存器 |
ARM 指令示例
assembly
.global _start
_start:
MOV R0, #5 ; 赋值 5 给 R0
ADD R0, R0, #3 ; R0 = R0 + 3
LDR R1, [R2] ; 读取 R2 指向的内存到 R1
STR R1, [R3] ; 存储 R1 到 R3 指向的内存
B _start ; 无限循环
四、Smali(Android DEX 汇编)是啥?
Smali 说白了就是 Android DEX 的「汇编」,相当于 Java 字节码的人类可读版。
Smali 代码示例
smali
.method public static sum(II)I
.registers 3
add-int v0, p0, p1
return v0
.end method
Smali 破解示例
smali
.method public isVip()Z
.registers 2
const/4 v0, 0x1 # 让所有用户变成 VIP
return v0
.end method
注意:修改 Smali 代码可用于绕过 Android 应用的 VIP 限制(仅限授权环境)。
五、汇编和 C 咋配合?
C 调用 x86 汇编
c
#include <stdio.h>
int add(int a, int b) {
int result;
__asm__ (
"addl %%ebx, %%eax;"
: "=a" (result)
: "a" (a), "b" (b)
);
return result;
}
int main() {
printf("Result: %d\n", add(5, 10));
return 0;
}
C 调用 ARM 汇编
c
int add(int a, int b) {
int result;
__asm__ (
"ADD %0, %1, %2"
: "=r" (result)
: "r" (a), "r" (b)
);
return result;
}
动手练一练
- 编写并运行 x86 汇编
bash
nasm -f elf64 test.asm
ld -o test test.o
./test
- 运行 ARM 汇编
assembly
.global _start
_start:
MOV R0, #1
LDR R1, =message
MOV R2, #13
MOV R7, #4
SWI 0
MOV R7, #1
SWI 0
.section .data
message: .ascii "Hello, ARM!\n"
- 反编译 APK 并改 Smali
bash
apktool d app.apk -o output
vim output/smali/com/example/Main.smali
本节小结
你只要记住这几条就行:汇编是机器码的助记符,和 CPU 指令集一一对应;x86 是 CISC、ARM 是 RISC、Smali 是 DEX 的「汇编」;寄存器、MOV/ADD/LDR/STR/BL 等是逆向里最常见;汇编和 C 可互相调用,逆向时能对上逻辑就行。
本节思考与练习
- 概念:汇编和机器码啥关系?x86、ARM、Smali 各用在啥场景?
- 动手:写一段 x86 或 ARM 汇编,用 nasm/as+ld 编译运行。
- 动手:用 apktool 反编译一个 APK,打开一个 smali 方法,和 Java 源码对照看。
下一节预告 :下一节讲 x86 vs. ARM 汇编对比(第六节),把两种架构的寄存器、指令、调用约定对比清楚。