第六节 x86 vs. ARM 汇编对比
(第1章 安卓逆向概论)
学习目标
学完本节,希望你能够:理解 x86 和 ARM(ARM32、ARM64)在架构、寄存器、指令集、寻址模式上的区别;会对比三种架构的指令写法;能在不同架构上编汇编、调试、反编译;知道 x86 与 ARM 在逆向、安全、漏洞利用里的差异。
一、x86 和 ARM(ARM32、ARM64)架构有啥不同?
| 特性 | x86(CISC) | ARM32(RISC) | ARM64(RISC) |
|---|---|---|---|
| 指令集 | CISC(复杂指令集计算机) | RISC(精简指令集计算机) | RISC(精简指令集计算机) |
| 指令长度 | 可变长(1-15 字节) | 固定 4 字节 | 固定 4 字节 |
| 寻址模式 | 复杂,支持多种寻址方式 | 简单,偏向寄存器操作 | 简化,偏向寄存器操作 |
| 寄存器数量 | 少(x86-32: 8 个通用寄存器) | 16 个通用寄存器(R0-R15) | 31 个通用寄存器(X0-X30) |
| 操作模式 | 实模式、保护模式、长模式(64 位) | AArch32(32 位) | AArch64(64 位) |
| 能效 | 高功耗,适用于 PC 和服务器 | 低功耗,适用于移动设备 | 更高效,适用于移动设备和服务器 |
总结:
- x86 采用 CISC 架构,指令灵活但解码复杂。
- ARM32(ARMv7)采用 RISC 架构,指令固定,适用于 32 位移动设备。
- ARM64(ARMv8)优化了 RISC 架构,引入更多寄存器,提高计算能力,支持 64 位操作系统。
二、x86、ARM32、ARM64 指令咋对比?
x86 32/64 位寄存器
| 寄存器 | x86-32(IA-32) | x86-64(x86-64) | 用途 |
|---|---|---|---|
| EAX | RAX | 通用寄存器(累加器) | |
| EBX | RBX | 通用寄存器(基址寄存器) | |
| ECX | RCX | 计数寄存器(循环) | |
| EDX | RDX | 数据寄存器 | |
| ESI | RSI | 源索引寄存器 | |
| EDI | RDI | 目标索引寄存器 | |
| EBP | RBP | 栈基址指针 | |
| ESP | RSP | 栈指针 |
ARM32 和 ARM64 寄存器
| 寄存器 | ARM32(ARMv7) | ARM64(ARMv8) | 用途 |
|---|---|---|---|
| 通用寄存器 | R0 - R12 | X0 - X30 | 传递参数,计算存储 |
| 栈指针 | R13 (SP) | SP | 指向栈顶 |
| 链接寄存器 | R14 (LR) | X30 (LR) | 存储函数返回地址 |
| 程序计数器 | R15 (PC) | PC | 存储当前指令地址 |
三种架构指令对照
| 操作 | x86 指令(CISC) | ARM32 指令(RISC) | ARM64 指令(RISC) |
|---|---|---|---|
| 赋值 | mov eax, 5 |
MOV R0, #5 |
MOV X0, #5 |
| 加法 | add eax, 10 |
ADD R0, R0, #10 |
ADD X0, X0, #10 |
| 读取内存 | mov eax, [ebx] |
LDR R0, [R1] |
LDR X0, [X1] |
| 存储到内存 | mov [ebx], eax |
STR R0, [R1] |
STR X0, [X1] |
| 函数调用 | call my_function |
BL my_function |
BL my_function |
| 逻辑运算 | and eax, ebx |
AND R0, R0, R1 |
AND X0, X0, X1 |
| 条件跳转 | cmp eax, ebx je label |
CMP R0, R1 BEQ label |
CMP X0, X1 B.EQ label |
三、x86、ARM32、ARM64 代码示例
x86 汇编示例
assembly
section .text
global _start
_start:
mov eax, 5 ; 赋值 5 给 EAX
add eax, 10 ; EAX = EAX + 10
mov ebx, eax ; 复制 EAX 到 EBX
int 0x80 ; 调用 Linux 系统 API
ARM32 汇编示例
assembly
.global _start
_start:
MOV R0, #5 ; 赋值 5 给 R0
ADD R0, R0, #10 ; R0 = R0 + 10
LDR R1, [R2] ; 读取 R2 指向的内存到 R1
STR R1, [R3] ; 存储 R1 到 R3 指向的内存
B _start ; 无限循环
ARM64 汇编示例
assembly
.global _start
_start:
MOV X0, #5 ; 赋值 5 给 X0
ADD X0, X0, #10 ; X0 = X0 + 10
LDR X1, [X2] ; 读取 X2 指向的内存到 X1
STR X1, [X3] ; 存储 X1 到 X3 指向的内存
B _start ; 无限循环
动手练一练
- 运行 x86 汇编
bash
nasm -f elf64 test.asm
ld -o test test.o
./test
- 运行 ARM32 汇编
bash
as -o arm32.o arm32.s
ld -o arm32 arm32.o
./arm32
- 运行 ARM64 汇编
bash
as -o arm64.o arm64.s
ld -o arm64 arm64.o
./arm64
本节小结
你只要记住这几条就行:x86 是 CISC、指令可变长,ARM 是 RISC、指令固定 4 字节;参数/返回值 x86 用 EAX/RAX 等、ARM32 用 R0~R3、ARM64 用 X0~X7;赋值/加减/访存/调用在三种架构下写法不同,但逻辑对应,反汇编时能对上即可。
本节思考与练习
- 概念:CISC 和 RISC 在指令长度、寻址方式上有啥区别?
- 对比:同一段「赋值+加法+读内存」在 x86、ARM32、ARM64 下各怎么写?
- 动手:在 x86 和 ARM 环境各编一小段汇编并运行(或用模拟器)。
下一节预告 :下一节讲 ARM 汇编指令解析(第七节),把 MOV、LDR、STR、BL、B 等常用指令讲清楚。