burpow
第04节-x86-64汇编入门

第04节-x86-64汇编入门

第 4 节:x86-64 汇编入门

所属课程:操作系统自学路线:面向网络安全、逆向工程与漏洞分析
所属周次:第 2 周
课程主题:C 语言、栈和汇编基础
本节目标:掌握 x86-64 汇编中最常见的寄存器、指令和调用约定,能初步读懂简单 C 程序对应的反汇编代码。


1. 本节课你要学会什么

学完这一节,你应该能回答下面几个问题:

  1. 汇编语言是什么?它和机器码、C 语言有什么关系?
  2. x86-64 中常见寄存器有哪些?
  3. raxrsprbprip 分别有什么作用?
  4. movaddsubcmpjmpcallret 大致是什么意思?
  5. 汇编中的 [] 表示什么?
  6. Linux x64 和 Windows x64 函数传参有什么区别?
  7. 如何用 objdump 和 GDB 看一个程序的反汇编?
  8. 为什么逆向工程和漏洞分析离不开汇编?

本节课的主线是:

1
C 代码 -> 编译 -> 机器指令 -> 汇编表示 -> 反汇编阅读 -> 理解程序行为

你不需要一节课就精通汇编,但要开始能看懂最常见的指令和寄存器。


2. 汇编语言是什么

CPU 真正执行的是机器码。

机器码是二进制数据,例如:

1
55 48 89 e5 48 83 ec 10

这些字节对人类来说很难直接阅读。

汇编语言是机器指令的文本表示。

例如上面的机器码可能对应:

1
2
3
push rbp
mov rbp, rsp
sub rsp, 0x10

所以可以这样理解:

1
2
3
机器码:CPU 执行的字节
汇编:机器码的人类可读形式
C 语言:更高级的人类可读程序语言

大致关系:

1
C 源代码 -> 编译器 -> 汇编/机器码 -> CPU 执行

逆向工程中的“反汇编”则是反过来:

1
机器码 -> 反汇编器 -> 汇编代码

常见反汇编工具:

  • objdump
  • GDB
  • IDA
  • Ghidra
  • x64dbg
  • WinDbg

3. 为什么网络安全要学汇编

如果你只写普通应用程序,可能很少直接写汇编。

但网络安全中,汇编非常重要。

3.1 逆向工程需要汇编

很多时候你拿不到源码,只能看到二进制程序。

工具能给你:

  • 反汇编
  • 反编译伪代码
  • 字符串
  • 调用关系

但最底层可靠的信息仍然是汇编。

如果反编译结果看不懂或不准确,就要回到汇编。


3.2 漏洞分析需要汇编

漏洞分析时你经常要看:

  • 崩溃地址
  • 当前执行到哪条指令
  • 哪个寄存器异常
  • 返回地址是否被覆盖
  • 栈上数据如何变化
  • 函数参数如何传入

这些都需要汇编基础。


3.3 恶意代码分析需要汇编

恶意代码经常会:

  • 动态解析 API
  • 加密字符串
  • 使用反调试技巧
  • 修改内存权限
  • 跳转到动态生成代码
  • 混淆控制流

这些行为经常需要看汇编才能确认。


4. x86、x64、x86-64 是什么

常见说法:

名称 含义
x86 通常指 32 位 Intel 架构
x64 通常指 64 位扩展架构
x86-64 64 位 x86 架构的正式说法之一
AMD64 x86-64 的另一种常见名称

本课程主要学习:

1
x86-64

也就是现代 PC 上最常见的 64 位架构之一。

Linux、Windows 下的 64 位程序大多都运行在这个架构上。


5. 寄存器是什么

寄存器是 CPU 内部非常小但非常快的存储位置。

可以先理解为:

CPU 自己随身携带的一组变量。

程序执行时,CPU 经常把数据放到寄存器里进行计算。

例如:

1
2
mov eax, 1
add eax, 2

意思大致是:

1
2
把 1 放到 eax
给 eax 加 2

此时 eax 里就是 3。

内存容量大但慢,寄存器容量小但快。

所以 CPU 会频繁在寄存器和内存之间移动数据。


6. x86-64 常见通用寄存器

x86-64 中常见通用寄存器包括:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
rax
rbx
rcx
rdx
rsi
rdi
rbp
rsp
r8
r9
r10
r11
r12
r13
r14
r15

它们都是 64 位寄存器。

其中最常见的几个:

寄存器 常见用途
rax 返回值、算术结果
rbx 通用寄存器,部分调用约定下需保持
rcx 通用寄存器,Windows x64 第 1 参数
rdx 通用寄存器,常用于参数
rsi Linux x64 第 2 参数,源地址相关操作
rdi Linux x64 第 1 参数,目标地址相关操作
rsp 栈顶指针
rbp 栈帧基址
rip 指令指针,表示下一条执行指令地址
r8/r9 额外参数寄存器

注意:

rip 通常不归类为通用寄存器,但它极其重要。


7. 64 位、32 位、16 位、8 位寄存器名

同一个物理寄存器可以用不同宽度访问。

rax 为例:

名称 大小
rax 64 位
eax 低 32 位
ax 低 16 位
al 低 8 位

例如:

1
mov rax, 0x1122334455667788

此时:

1
2
3
4
rax = 0x1122334455667788
eax = 0x55667788
ax = 0x7788
al = 0x88

其他寄存器也有类似命名:

64 位 32 位 16 位 8 位
rbx ebx bx bl
rcx ecx cx cl
rdx edx dx dl
rsi esi si sil
rdi edi di dil
rbp ebp bp bpl
rsp esp sp spl

一个重要细节:

在 x86-64 中,写入 32 位寄存器通常会把对应 64 位寄存器的高 32 位清零。

例如:

1
mov eax, 1

执行后:

1
rax = 0x0000000000000001

8. rip:指令指针

rip 是非常重要的寄存器。

它保存:

1
CPU 下一条要执行的指令地址

如果 rip 是:

1
0x401136

说明 CPU 当前要从地址 0x401136 处取指令执行。

程序的正常执行、跳转、函数调用、返回,本质上都在改变 rip

例如:

  • 顺序执行:rip 自动指向下一条指令
  • jmp:直接修改 rip
  • call:保存返回地址后修改 rip
  • ret:从栈中取返回地址放入 rip

漏洞分析中,如果你看到:

1
rip = 0x4141414141414141

通常说明程序控制流已经被异常数据影响。


9. rsprbp:栈相关寄存器

上一节讲过:

  • rsp 通常指向栈顶
  • rbp 常作为栈帧基址

常见函数开头:

1
2
3
push rbp
mov rbp, rsp
sub rsp, 0x10

常见函数结尾:

1
2
leave
ret

在调试器里,你需要经常观察:

1
2
3
rsp
rbp
rip

这三个寄存器可以帮助你判断:

  • 当前执行到哪里
  • 当前栈顶在哪里
  • 当前栈帧在哪里
  • 函数返回时可能跳到哪里

10. 汇编语法:Intel 和 AT&T

x86 汇编常见两种语法风格:

1
2
Intel 语法
AT&T 语法

本课程主要使用 Intel 语法。

Intel 语法常见形式:

1
2
mov eax, 1
mov [rbp-4], eax

AT&T 语法常见形式:

1
2
movl $1, %eax
movl %eax, -4(%rbp)

两者区别之一是操作数顺序不同。

Intel:

1
目标在前,源在后

例如:

1
mov eax, 1

意思是:

1
把 1 放到 eax

如果你用 objdump,默认可能看到 AT&T 语法。

可以加参数显示 Intel 语法:

1
objdump -d -M intel program

11. mov:数据移动

mov 是最常见的指令之一。

它的作用是:

1
把数据从源位置复制到目标位置

Intel 语法:

1
mov 目标, 源

例子:

1
mov eax, 1

意思是:

1
eax = 1

例子:

1
mov eax, ebx

意思是:

1
eax = ebx

例子:

1
mov DWORD PTR [rbp-4], eax

意思是:

1
把 eax 的低 32 位写入 rbp-4 指向的内存位置

注意:

mov 不是“移动后源数据消失”,而是复制。


12. []:访问内存

在 Intel 汇编中,方括号 [] 表示访问内存。

例如:

1
mov eax, [rbp-4]

意思是:

1
从地址 rbp-4 处读取数据到 eax

而:

1
mov eax, rbp

意思是:

1
把 rbp 这个寄存器的值复制到 eax

区别很大:

指令 含义
mov eax, rbp 复制 rbp 的数值
mov eax, [rbp] 把 rbp 当地址,读取该地址处的内容
mov eax, [rbp-4] 读取 rbp-4 地址处的内容

这类似 C 语言中的:

1
2
p   // 指针变量的值,也就是地址
*p // 访问这个地址里的内容

所以:

1
[地址]

类似:

1
*地址

13. addsub:加减

add 表示加法。

1
add eax, 2

意思是:

1
eax = eax + 2

sub 表示减法。

1
sub rsp, 0x20

意思是:

1
rsp = rsp - 0x20

在函数开头经常看到:

1
sub rsp, 0x20

这通常表示:

1
在栈上预留 0x20 字节空间

因为 x86-64 中栈通常向低地址增长,所以 rsp 减小表示栈空间扩大。


14. pushpop:压栈和出栈

push 把数据压入栈。

1
push rbp

大致做:

1
2
rsp = rsp - 8
[rsp] = rbp

pop 从栈中取出数据。

1
pop rbp

大致做:

1
2
rbp = [rsp]
rsp = rsp + 8

64 位模式下一次 push / pop 通常处理 8 字节。

函数开头常见:

1
push rbp

用于保存调用者的 rbp

函数结尾常通过 leavepop rbp 恢复。


15. cmp 和条件跳转

cmp 用于比较。

例如:

1
cmp eax, 10

它大致比较:

1
eax 和 10

cmp 本身不保存结果到普通寄存器,而是影响 CPU 的标志位。

后面通常跟条件跳转。

常见条件跳转:

指令 含义
je equal,相等则跳转
jne not equal,不相等则跳转
jg greater,大于则跳转
jl less,小于则跳转
jge greater or equal,大于等于则跳转
jle less or equal,小于等于则跳转
ja unsigned above,无符号大于
jb unsigned below,无符号小于

例子:

1
2
cmp eax, 10
je equal_label

意思是:

1
如果 eax == 10,就跳转到 equal_label

16. jmp:无条件跳转

jmp 是无条件跳转。

例如:

1
jmp 0x401200

意思是:

1
直接跳到 0x401200 执行

C 语言中的 ifforwhileswitch 编译后,通常都会变成比较和跳转。

例如:

1
2
3
4
5
if (x == 10) {
puts("yes");
} else {
puts("no");
}

可能变成:

1
2
3
4
5
6
7
cmp DWORD PTR [rbp-4], 10
jne else_label
call puts_yes
jmp end_label
else_label:
call puts_no
end_label:

17. callret:函数调用和返回

上一节已经讲过。

call 大致做:

1
2
保存返回地址
跳转到目标函数

ret 大致做:

1
2
从栈顶取出返回地址
跳转回调用者

例如:

1
2
call puts
ret

逆向中看到 call 时,要问:

  • 调用了哪个函数?
  • 参数在哪里?
  • 返回值是否被使用?
  • 调用后程序如何继续?

漏洞分析中看到 ret 时,要问:

  • 栈顶的返回地址是什么?
  • 返回地址是否被覆盖?
  • rip 会跳到哪里?

18. lea:取有效地址

lea 是 Load Effective Address。

它经常让初学者困惑。

例如:

1
lea rax, [rbp-0x10]

意思不是读取 [rbp-0x10] 里面的内容。

而是计算地址:

1
rax = rbp - 0x10

也就是说,lea 取的是地址本身。

它类似 C 语言中的:

1
&变量

例子:

1
2
lea rdi, [rip+0xe9b]
call puts

常见于把字符串地址传给 puts


19. Linux x64 调用约定回顾

Linux x86-64 常用 System V AMD64 ABI。

整数和指针参数通常这样传:

参数序号 寄存器
第 1 个 rdi
第 2 个 rsi
第 3 个 rdx
第 4 个 rcx
第 5 个 r8
第 6 个 r9

返回值通常在:

1
rax

例如 C 代码:

1
2
3
4
5
6
7
int add(int a, int b) {
return a + b;
}

int main() {
return add(1, 2);
}

可能看到:

1
2
3
mov esi, 2
mov edi, 1
call add

表示:

1
2
3
4
第 1 个参数 1 放入 edi/rdi
第 2 个参数 2 放入 esi/rsi
调用 add
返回值在 eax/rax

20. Windows x64 调用约定回顾

Windows x64 前四个整数或指针参数通常这样传:

参数序号 寄存器
第 1 个 rcx
第 2 个 rdx
第 3 个 r8
第 4 个 r9

返回值通常也在:

1
rax

所以同样的函数调用在 Windows 下可能是:

1
2
3
mov edx, 2
mov ecx, 1
call add

表示:

1
2
3
第 1 个参数 1 放入 ecx/rcx
第 2 个参数 2 放入 edx/rdx
调用 add

Windows x64 还有 shadow space 等规则,入门阶段只需要先知道:

1
Linux 和 Windows 的前几个参数寄存器不同。

这对逆向非常关键。


21. C 代码如何对应汇编:加法函数

写一个程序 add_demo.c

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int add(int a, int b) {
int c = a + b;
return c;
}

int main() {
int result = add(1, 2);
printf("result = %d\n", result);
return 0;
}

编译:

1
gcc -g -O0 add_demo.c -o add_demo

反汇编:

1
objdump -d -M intel add_demo

你可能看到 add 类似:

1
2
3
4
5
6
7
8
9
10
11
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-0x14], edi
mov DWORD PTR [rbp-0x18], esi
mov edx, DWORD PTR [rbp-0x14]
mov eax, DWORD PTR [rbp-0x18]
add eax, edx
mov DWORD PTR [rbp-0x4], eax
mov eax, DWORD PTR [rbp-0x4]
pop rbp
ret

大致解释:

1
2
3
4
5
6
7
8
保存 rbp
建立栈帧
把参数 a 保存到栈上
把参数 b 保存到栈上
取出 a 和 b
相加
把结果放入 eax
返回

你看到的真实汇编可能略有不同,但核心思想类似。


22. C 代码如何对应汇编:if 判断

写程序 if_demo.c

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int main() {
int x = 10;

if (x == 10) {
printf("yes\n");
} else {
printf("no\n");
}

return 0;
}

编译:

1
gcc -g -O0 if_demo.c -o if_demo

反汇编:

1
objdump -d -M intel if_demo

你会看到类似:

1
2
3
4
cmp DWORD PTR [rbp-0x4], 0xa
jne <else>
call puts
jmp <end>

对应关系:

C 语言 汇编
if (x == 10) cmp + 条件跳转
then 分支 一段顺序代码
else 分支 另一段顺序代码
分支结束 跳到共同出口

逆向时,看到 cmpjcc,通常要想到:

1
这里可能是 if、while、for 或 switch 的一部分。

23. C 代码如何对应汇编:循环

写程序 loop_demo.c

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main() {
for (int i = 0; i < 3; i++) {
printf("i = %d\n", i);
}

return 0;
}

编译:

1
gcc -g -O0 loop_demo.c -o loop_demo

反汇编后,你通常会看到:

  • 初始化变量
  • 比较条件
  • 条件跳转
  • 循环体
  • 自增
  • 跳回比较处

循环的底层本质就是:

1
比较 + 条件跳转 + 无条件跳转

所以汇编里并没有真正的 forwhile

它们都会变成跳转结构。


24. GDB 中查看汇编

用 GDB 调试 add_demo

1
gdb ./add_demo

常用命令:

1
2
3
4
5
6
7
8
break main
run
disassemble main
disassemble add
layout asm
info registers
stepi
nexti

解释:

命令 用途
disassemble main 反汇编 main 函数
layout asm 显示汇编窗口
info registers 查看寄存器
stepi 单步执行一条机器指令,进入函数
nexti 单步执行一条机器指令,不进入函数

如果 layout asm 显示不正常,可以直接用:

1
2
disassemble main
x/10i $rip

x/10i $rip 表示:

1
从当前 rip 开始显示 10 条指令

25. objdump 和 GDB 的区别

objdump 用于静态查看文件中的反汇编。

例如:

1
objdump -d -M intel add_demo

它不运行程序,只分析文件。

GDB 是动态调试器。

它可以:

  • 运行程序
  • 下断点
  • 单步执行
  • 查看寄存器
  • 查看栈
  • 查看内存
  • 修改变量或寄存器

所以:

1
2
objdump 更像静态看地图
GDB 更像开车实时导航

逆向和漏洞分析中,两者经常配合使用。


26. Windows 对照:x64dbg 中看汇编

Windows 下用 x64dbg 打开 exe 后,默认主窗口就是汇编视图。

常见区域:

  • 左上:反汇编代码
  • 右上:寄存器
  • 左下:内存 Dump
  • 右下:栈

你可以观察:

  • 当前 RIP 指向哪条指令
  • RCX/RDX/R8/R9 中是否有参数
  • RAX 中是否有返回值
  • RSP 指向的栈内容
  • call 调用了哪个函数
  • ret 返回到哪里

如果你调试一个调用 MessageBoxA 的程序,可以观察:

1
rcx, rdx, r8, r9

这些寄存器中如何传入参数。


27. 汇编阅读的基本方法

初学者读汇编不要一行一行死抠。

建议按层次阅读。

27.1 先找函数边界

看:

  • 函数入口
  • 函数结尾
  • call
  • ret

先知道哪里是一个函数。


27.2 再找关键调用

重点看调用了什么函数:

  • printf
  • puts
  • malloc
  • free
  • open
  • read
  • write
  • CreateFileW
  • VirtualAlloc
  • CreateProcessW

函数调用常常比普通算术指令更有语义价值。


27.3 再看参数

根据调用约定,看调用前寄存器里放了什么。

Linux:

1
rdi, rsi, rdx, rcx, r8, r9

Windows:

1
rcx, rdx, r8, r9

27.4 再看分支

cmp 和跳转:

  • je
  • jne
  • jg
  • jl
  • jmp

这些通常对应条件判断和循环。


27.5 最后看局部变量

[rbp-...][rsp+...]

它们通常是:

  • 局部变量
  • 临时数据
  • 保存的参数
  • 栈上的缓冲区

28. 从逆向工程角度看本节内容

汇编是逆向工程的基础语言。

你需要逐渐建立这些直觉:

1
2
3
mov edi, 1
mov esi, 2
call add

可能是:

1
add(1, 2);
1
2
cmp eax, 0
jne label

可能是:

1
if (eax != 0) goto label;
1
2
lea rdi, [rip+0xe9b]
call puts

可能是:

1
puts("some string");

逆向不是把每条汇编翻译成 C,而是恢复程序意图。


29. 从漏洞分析角度看本节内容

漏洞分析中,你常常要看崩溃现场。

例如:

1
2
3
RIP: 0x4011a3
RSP: 0x7fffffffe280
RAX: 0x0

然后查看当前指令:

1
mov eax, DWORD PTR [rax]

如果 rax = 0,这就可能是空指针解引用。

再例如:

1
ret

执行前栈顶是:

1
0x4141414141414141

那么 retrip 可能变成这个值,导致崩溃。

所以汇编能帮助你判断:

  • 程序为什么崩溃
  • 哪个地址非法
  • 哪个寄存器异常
  • 输入如何影响控制流
  • 防护机制是否生效

30. 从恶意代码分析角度看本节内容

恶意代码经常故意隐藏高级语义。

反编译结果可能很乱,但汇编仍然可靠。

你需要关注:

  • 是否调用敏感 API
  • 参数指向哪里
  • 是否有异常跳转
  • 是否动态计算函数地址
  • 是否修改内存权限
  • 是否写入代码后跳转执行

例如看到:

1
2
3
call VirtualAlloc
call memcpy
call rax

可能意味着:

1
申请内存 -> 写入数据 -> 跳到该内存执行

这在恶意代码分析中非常值得关注。


31. 本节 Linux 实验:反汇编 add 程序

创建 add_demo.c

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int add(int a, int b) {
int c = a + b;
return c;
}

int main() {
int result = add(1, 2);
printf("result = %d\n", result);
return 0;
}

编译:

1
gcc -g -O0 add_demo.c -o add_demo

反汇编:

1
objdump -d -M intel add_demo

要求你找到:

  • main
  • add
  • call add
  • call printf
  • ret
  • 参数传递相关的 ediesi
  • 返回值相关的 eax

32. 本节 Linux 实验:GDB 单步执行汇编

启动:

1
gdb ./add_demo

执行:

1
2
3
4
5
6
7
8
9
break main
run
disassemble main
x/10i $rip
info registers
stepi
info registers
stepi
info registers

观察:

  • 每执行一条指令,rip 如何变化
  • 调用 add 前,ediesi 是什么
  • add 返回后,eax 是什么
  • 调用 printf 前,参数寄存器是什么

33. 本节重点总结

你需要记住这些核心结论:

  1. 汇编是机器码的人类可读形式。
  2. 反汇编是把机器码转换成汇编表示。
  3. 寄存器是 CPU 内部高速存储位置。
  4. rip 表示下一条要执行的指令地址。
  5. rsp 表示栈顶,rbp 常用作栈帧基址。
  6. mov 用于复制数据。
  7. [] 表示访问内存。
  8. add / sub 用于加减。
  9. cmp 通常配合条件跳转实现判断。
  10. jmp 是无条件跳转。
  11. callret 实现函数调用和返回。
  12. Linux x64 和 Windows x64 的参数寄存器不同。
  13. 逆向、漏洞分析和恶意代码分析都离不开汇编基础。

34. 本节课后作业

作业 1:反汇编 add 程序

完成 add_demo.c,执行:

1
2
gcc -g -O0 add_demo.c -o add_demo
objdump -d -M intel add_demo > add_demo.asm

提交内容:

1
2
3
4
1. add 函数的反汇编
2. main 函数中调用 add 的位置
3. 参数 1 和 2 分别放入了哪个寄存器
4. add 的返回值从哪个寄存器返回

作业 2:分析 if 程序

if_demo.c

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int main() {
int x = 10;

if (x == 10) {
printf("yes\n");
} else {
printf("no\n");
}

return 0;
}

反汇编后找到:

  • cmp
  • 条件跳转指令
  • then 分支
  • else 分支

回答:

1
2
3
1. if 判断对应哪条 cmp?
2. 条件不满足时跳到哪里?
3. then 分支执行完后是否有 jmp?

作业 3:GDB 单步汇编

用 GDB 执行:

1
2
3
4
5
6
7
break main
run
x/10i $rip
info registers
stepi
x/10i $rip
info registers

至少单步执行 10 条指令。

提交内容:

1
2
3
4
1. 单步执行前后的 rip 变化
2. 至少 3 条你能解释含义的汇编指令
3. 哪条指令是 call
4. call 执行后 rip 发生了什么变化

35. 自测题

题 1

机器码和汇编语言有什么关系?

题 2

raxrsprbprip 分别常见用途是什么?

题 3

Intel 语法中 mov eax, 1 是什么意思?

题 4

mov eax, [rbp-4]mov eax, rbp 有什么区别?

题 5

cmp 指令通常和什么指令一起使用?

题 6

Linux x64 前 6 个整数或指针参数通常放在哪些寄存器?

题 7

Windows x64 前 4 个整数或指针参数通常放在哪些寄存器?

题 8

为什么汇编对逆向工程很重要?


36. 自测题参考答案

答 1

机器码是 CPU 实际执行的二进制字节;汇编语言是机器码的人类可读文本表示。反汇编就是把机器码转换成汇编表示。

答 2

rax 常用于返回值和计算结果;rsp 指向栈顶;rbp 常作为栈帧基址;rip 表示下一条要执行的指令地址。

答 3

把立即数 1 复制到 eax 寄存器中。

答 4

mov eax, rbp 是把 rbp 寄存器的值复制到 eaxmov eax, [rbp-4] 是把 rbp-4 当作地址,读取该地址处的内存内容到 eax

答 5

cmp 通常和条件跳转指令一起使用,例如 jejnejgjl 等。

答 6

Linux x64 System V ABI 中,前 6 个整数或指针参数通常依次放在 rdirsirdxrcxr8r9

答 7

Windows x64 中,前 4 个整数或指针参数通常依次放在 rcxrdxr8r9

答 8

因为逆向时经常没有源码,只能通过反汇编理解程序。函数调用、条件判断、循环、API 参数、崩溃现场和控制流都需要通过汇编分析。


37. 下一节预告

下一节课会讲:

1
调试器的工作原理

你会学习:

  • 调试器为什么能让程序暂停
  • 断点是什么
  • 单步执行是什么
  • 寄存器窗口和内存窗口怎么看
  • Linux 的 ptrace
  • Windows Debug API
  • 恶意代码为什么会反调试
隐藏
换装
本文作者:burpow
本文链接:https://youthfulnesszxx.github.io/2026/05/28/第04节-x86-64汇编入门/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可