一、先定基础环境 & 工具(必准备)
1. 编译+反汇编工具(二选一,推荐两套都玩)
方案1:PC端(x86/x64,最方便看完整汇编)
-
编译器:`GCC / G++`(MinGW、WSL、Linux 自带)、MSVC(VS)
-
查看汇编方式:
- 命令行直接输出汇编:
```bash
g++ -S main.cpp -o main.s # 生成纯汇编文件 .s
```
- 调试器单步看汇编:`gdb` / Visual Studio(调试→转到反汇编)
- 推荐:**G++ + 文本查看**,代码干净、无多余微软扩展。
方案2:嵌入式端(ARM汇编,贴合你STM32)
-
工具:`arm-none-eabi-g++` + STM32CubeIDE / Keil
-
用途:看 **C++ 在 Cortex-M 内核下的汇编**,和工控/嵌入式场景完全匹配。
2. 前置共识
- 关闭**优化**!`-O0` 无优化,汇编和C++代码一一对应;开优化 `-O1/O2` 会重排、删减代码,不适合初学。
```bash
g++ -S -O0 main.cpp -o main.s
```
-
先从 **C++ 基础语法** 入手,再到面向对象、重载、继承、多态、虚函数(C++ 灵魂)。
-
先看懂 **AT&T 汇编(GCC)** 或 **Intel 汇编(VS)** 一种即可,语法差异很小。
二、学习顺序(由浅入深,循序渐进)
按这个顺序研究,难度逐步提升,不会卡壳:
-
基础类型、变量、赋值、四则运算(对标C)
-
分支 `if/else`、循环 `for/while`、逻辑判断
-
函数、参数传递、返回值、栈帧
-
指针、引用(C++ 重点)
-
结构体、类、成员变量、普通成员函数
-
构造函数、析构函数、拷贝构造
-
函数重载、运算符重载
-
继承、成员访问权限(public/private)
-
**虚函数、多态、虚表(vtable)**(C++ 最核心、最值得深挖)
-
`const`、`static`、`this` 指针、`new/delete` 内存管理
-
模板、RAII、异常(进阶)
三、核心 C++ 特性 + 汇编实现解析(精选高频重点)
下面用 **x86-32 + GCC -O0** 举例,代码极简 + 逐段解释,你可以直接复制编译验证。
1. 普通变量、赋值、运算(打底)
C++ 代码
```cpp
int a = 1;
int b = 2;
int c = a + b;
```
对应汇编核心逻辑
-
局部变量分配在 **栈(Stack)** 上;
-
立即数 `1/2` 送入寄存器,运算后写回栈;
-
本质:内存 ↔ 寄存器 数据搬运 + 算术指令。
**学习点**:理解栈布局、通用寄存器作用、基础算术指令。
2. 分支 if / 条件判断
C++
```cpp
int test(int x)
{
if (x > 0)
return 1;
else
return 0;
}
```
汇编核心实现
-
比较指令 `cmp`:对比 `x` 和 0;
-
条件跳转指令 `jg/jl/je`:根据标志位跳转到不同代码块;
-
无分支则顺序执行。
**学习点**:CPU 状态标志位、条件跳转指令(汇编精髓之一)。
3. 函数调用、栈帧、参数、返回值(重中之重)
C/C++/C++ 函数全靠**栈帧**支撑。
C++
```cpp
int add(int x, int y)
{
return x + y;
}
```
汇编关键行为
-
调用方:把**参数压栈**;执行 `call` 指令跳转到函数;
-
函数内部:开辟栈帧 `ebp/esp`,保护现场;
-
运算结果放入 **eax 寄存器**(x86 默认返回值寄存器);
-
`ret` 弹栈返回调用处,平衡栈。
**学习点**:栈帧结构、调用约定(cdecl)、`call/ret`、寄存器传参规则。
4. 指针 vs 引用(C++ 经典考点,汇编看区别)
> 结论先行:**底层汇编,引用 ≈ 常指针**,编译器语法层面做了封装。
C++
```cpp
void func(int* p, int& r)
{
*p = 10;
r = 20;
}
```
汇编现象
-
指针:显式解引用 `*p` → 汇编出现 **内存间接寻址**;
-
引用:编译器内部依然按「地址」处理,**没有额外开销**,和指针汇编几乎一致。
**学习点**:寻址方式、理解「引用只是语法糖」。
5. 类、普通成员函数 + this 指针(C++ 面向对象入门)
C++
```cpp
class Demo
{
public:
int val;
void set(int v)
{
val = v;
}
};
int main()
{
Demo d;
d.set(100);
return 0;
}
```
汇编核心关键点
-
`d` 是栈上对象,成员变量 `val` 就是一块栈内存;
-
成员函数 `set` **本质是全局函数**,编译器悄悄多传一个参数:**`this` 指针**(对象首地址);
-
`val = v` → 靠 `this` 指针偏移访问成员内存。
**学习点**:
-
`this` 指针的传递规则;
-
类成员 = 「数据内存 + 全局函数」的语法封装。
6. 构造函数 / 析构函数
C++
```cpp
class A
{
public:
int x;
A() { x = 1; }
~A() {}
};
int main()
{
A a;
return 0;
}
```
汇编行为
-
对象创建时,**自动调用构造函数**(本质普通函数调用);
-
作用域结束,自动调用析构函数;
-
栈对象生命周期 = 构造/析构的自动触发时机。
**学习点**:编译器自动插入函数调用,理解 RAII 底层基础。
7. 静态成员 static(变量/函数)
核心汇编特征
-
`static` 成员变量:**不在栈/对象内**,放在 **全局数据段(.data)**,所有对象共享同一块内存;
-
`static` 成员函数:**没有 this 指针**,调用方式和普通全局函数完全一致。
一眼就能和普通成员区分开。
8. 函数重载、运算符重载
结论
-
函数重载:C++ 编译器做 **名字改编(name mangling)**,不同参数列表生成不同汇编函数名,CPU 看来就是两个独立函数;
-
运算符重载:`+ / - / ()` 等,底层全部翻译成**普通成员/全局函数调用**,无特殊硬件指令。
**学习点**:C++ 名字改编机制。
9. 【最难也最有价值】虚函数 & 多态 & 虚表 vtable(必研究)
这是 C++ 区别于 C 的**核心特性**,汇编能彻底看穿原理。
C++ 多态示例
```cpp
class Base
{
public:
virtual void func() {}
};
class Derive : public Base
{
public:
virtual void func() {}
};
int main()
{
Base* p = new Derive;
p->func(); // 多态,调用子类方法
delete p;
return 0;
}
```
汇编底层完整逻辑(三步看懂多态)
- **每个含虚函数的对象,头部暗藏一个 `vptr`(虚表指针)**
对象内存布局:`vptr + 普通成员变量`
- **全局存在一张 vtable(虚函数表)**
每个类对应一张表,里面存虚函数的**函数地址**。
- 执行 `p->func()` 时:
-
通过 `vptr` 找到虚表;
-
查表取出真实函数地址;
-
间接调用。
> 关键:**非虚函数 = 编译期直接定地址;虚函数 = 运行期查表跳转**,这就是「动态多态」。
**这块吃透 = C++ OOP 底层完全通关**。
10. new / delete 内存分配
-
`new`:底层调用 **堆内存分配函数**(类似 `malloc`),再自动调用构造;
-
`delete`:先调用析构,再释放堆内存;
-
汇编能清晰区分 **栈内存(自动回收)** 和 **堆内存(手动管理)**。
四、标准实操流程(你每一段代码都这么练)
固定流程,形成习惯:
-
写一小段 **单一功能 C++ 代码**(只测一个特性,别写复杂代码);
-
用 `g++ -S -O0 代码.cpp` 生成汇编;
-
对照 C++ 行 + 汇编行逐行翻译;
-
回答三个问题:
-
这段C++语法对应哪几条汇编指令?
-
数据存在栈/堆/全局区?用了哪些寄存器?
-
编译器做了哪些**语法糖封装/自动插入代码**?
- 尝试**手写对应汇编**,逆向还原。
五、两个进阶方向(结合你的背景)
1. 切换到 ARM 汇编(对接 STM32)
学会x86汇编逻辑后,把同样代码用 `arm-none-eabi-g++` 编译成 ARM 汇编:
-
对比:x86 复杂指令集 vs ARM 精简指令集;
-
观察:寄存器传参、栈使用、虚表实现 **逻辑完全一致,只是指令名不同**;
-
收益:同时吃透 PC + 嵌入式汇编。
2. 开启优化对比
同一代码,分别用 `-O0` / `-O1` / `-O2` 生成汇编:
观察编译器如何**指令重排、常量传播、函数内联、死码删除**,理解编译优化原理。
六、避坑提醒
-
不要一上来就啃模板、异常、STL,先把**基础语法 + 类 + 虚函数**搞定;
-
务必 `-O0` 无优化学习,优化后汇编会打乱对应关系;
-
不用背所有汇编指令,**看懂执行流、数据流向**优先;
-
重点抓:**栈、调用、this、虚表** 四大块,这是 C++ 底层命脉。
七、入门练习清单(直接照着逐个打卡)
-
变量、运算、赋值
-
if / for / while 分支循环
-
普通函数、参数、返回值
-
指针 & 引用 对比
-
结构体 → 类 对比
-
成员函数 + this 指针
-
构造 / 析构
-
static 静态成员
-
函数重载
-
单继承
-
**虚函数 + 多态(重点攻坚)**
-
new / delete