(注:使用 英特尔64位指令集,也称CISC)
CISC:Complex Instruction Set Computer,复杂指令集计算机
RISC:Reduced Instruction Set Computer,精简指令集计算机
Architecture(架构):也称ISA (Instruction Set Architecture),是处理器设计中需要理解或编写汇编/机器代码的部分。 例如:Instruction set specification(指令集规范)、registers(寄存器)
Microarchitecture(微架构):架构的具体实现。 例如:Cache sizes(缓存大小)、Core frequency(核心频率)。
Code Form(代码形式):
Machine Code(机器码):处理器执行的字节级程序。
Assembly Code(汇编代码):机器码的文本表示形式。
Example ISAs(指令集架构示例):
CPU 核心组件与状态
Memory(内存)特性
CPU 和 Memory 的交互
C 程序到可执行程序的编译流程:
C 程序(.c 文件) → 汇编代码(.s 文件) → 目标文件(.o 文件) → 可执行文件(.exe 或无扩展名的可执行程序)。
C program -> Asm program -> Object Program -> Executable program
.c 文件和.s 文件是文本文件,.o 文件和可执行文件都是二进制文件。
经过编译(Compiler)、汇编(Assembler)和链接(Linker)三大步骤。
关键工具与作用:
常用选项:
-Og:开启基本调试优化。-S:生成汇编代码文件(.s)。-o:指定输出文件名称。gcc -Og p1.c p2.c -o p,将原代码p1.c、p2.c编译为可执行文件p并开启基本调试优化。静态库的作用:
.a 文件)被链接进可执行文件中,为程序提供必要的功能支持。整形数据只有1,2,4,8字节大小;
浮点数据有4,8,10字节大小;
代码与普通数据并无区别,是指一段由机器指令字节序列表示的可执行程序逻辑;
不支持聚合类型。
数据运算:汇编允许直接对寄存器和内存数据进行算术运算;
数据传输:汇编语言无法直接对内存中的数据进行复杂运算,因此需要将数据先加载到寄存器中进行操作,然后再存储回内存。
转移控制:汇编语言通过控制流指令来转移当前程序的执行位置,可以是条件或无条件的跳转。
*dest = t
指针赋值,将变量t储存到指针dest指向的位置。
movq %rax, (%rbx)
movq:move quadword,移动 8 字节数据;
%rax:寄存器,保存变量t;
(%rbx):表示寄存器%rbx存储的是内存地址,movq会将%rax的值写入该地址指向的内存。
0x40059e: 48 89 03
0x40059e:该指令在内存的地址;
48 89 03:该指令的机器码(3字节)。
48:表示 64 位操作数前缀(REX prefix)
89:是mov r/m64, r64的操作码
03:是 ModR/M 字节,表示源寄存器是%rax,目标内存地址由%rbx给出。
%rax |
%rsi |
%r8 |
%r12 |
|---|---|---|---|
%rbx |
%rdi |
%r9 |
%r13 |
%rcx |
%rsp |
%r10 |
%r14 |
%rdx |
%rbp |
%r11 |
%r15 |
如果使用%r版本(如上表),则为64位;如果使用%e版本,则为32位。当然也可以使用其低位的 2字节/16位 和1字节/8位。
%rsp/%esp寄存器称为栈指针/栈顶指针。
movq Sourse, Dest
movq 指令用于传输数据:
Source) 数据移动到“目标” (Dest) 中。使用 movq 可以:
在汇编指令中,操作数可以是以下三种类型:立即数、寄存器 和 内存。
1. Immediate (立即数):一个常量值,通常是整型数据。
格式:立即数以 $ 开头。
$0x400 表示十六进制值 0x400。$-533 表示负数 -533。编码方式:
2. Register (寄存器):程序在运行过程中使用的处理器内部寄存器。
x86-64 的整数寄存器:
一共有 16 个字长为 64-bit 的寄存器,如 %rax、%rbx 等。
常见寄存器:
%rax, %rcx, %rdx, %rbx, %rsp, %rbp, %rsi, %rdi。%r8 到 %r15,提供更灵活的运算。特殊用途:
%rsp: 堆栈指针(Stack Pointer),专门用于栈操作。%rbp: 栈基址寄存器(Base Pointer),通常用于函数调用中的栈帧管理。使用案例:
movq %rax, %rbx 将 %rax 的值复制到 %rbx。3. Memory (内存):程序操作的内存地址。
地址模式:
(%rax) 表示使用 %rax 储存的地址指向的内存单元。内存访问规则:
movq (%rbx), %rax 会读取 %rbx 指向的内存内容,存入 %rax。我们无法将一个直接数作为目标dest,也不能将内存作为内存的目标(即不可以movq Mem Mem)。故movq只有 5 种格式。
| Source | Dest | Code | C Analog |
|---|---|---|---|
| Imm | Reg | movq $0x4, %rax |
temp = 0x4; |
| Imm | Mem | movq $-147, (%rax) |
*p = -147 |
| Reg | Reg | movq $rax, %rdx |
temp2 = temp1 |
| Reg | Mem | movq $rax, (%rax) |
*p = temp |
| Mem | Reg | movq ($rax), %rdx |
temp = *p |
内存寻址包括常规寻址和偏移寻址:
| 模式 | 语法 | 数学公式 | 示例 |
|---|---|---|---|
| Normal | (%R) |
Mem[Reg[R]] |
movq (%rcx), %rax |
| Displacement | D(%R) |
Mem[Reg[R] + D] |
movq 8(%rbp), %rdx |
void swap(long *xp, long *yp){
long t0 = *xp;
long t1 = *yp;
*xp = t1;
*yp = t0;
}
swap:
movq (%rdi), %rax
movq (%rsi), %rdx
movq %rdx, (%rdi)
movq %rax, (%rsi)
其中的对应关系为:
| Register | Value |
|---|---|
%rdi |
xp |
%rsi |
yp |
%rax |
t0 |
%rdx |
t1 |
一般形式的内存寻址为:D(Rb,Ri,S)
其内存地址的计算规则是:Mem[Reg[Rb] + S * Reg[Ri] + D]
D (Displacement) - 偏移量
array[index] 或 base_address + offset。Rb (Base Register) - 基址寄存器
%rax, %rbp 等)。Ri (Index Register) - 索引寄存器
%rsp,因为 %rsp 是专用的堆栈指针)。S (Scale) - 比例因子/尺度
1, 2, 4, 8。
char)short)int)double 或 long)1,可以省略。假设地址:%rdx:0xf000,%rcx:0x0100
| Expression | Computation | Address |
|---|---|---|
0x8(%rdx) |
0xf000 + 0x8 |
0xf008 |
(%rdx, %rcx) |
0xf000 + 0x100 |
0xf100 |
(%rdx, %rcx, 4) |
0xf000 + 4 * 0x100 |
0xf400 |
0x80(, %rdx, 2) |
2 * 0xf000 + 0x80 |
0x1e080 |
代码:leaq Src, Dst.
Src:表示地址模式的表达式(涉及偏移量、基址、索引、比例因子等)。Dst:目标寄存器,用于存储计算的地址。计算地址而不引用内存:
p = &x[i] 可以通过 leaq 快速实现。计算算术表达式:
常用于计算类似如下形式的数学表达式:x + k * y
其中,k 可能是 1, 2, 4, 8 (常见比例因子,对应常规跨字节的数据访问)。
long m12(long x){
return x*12;
}
leaq (%rdi, %rdi, 2), %rax # t <- x + 2*x = 3*x
salq $2, %rax # t <- 3*x << 2 = 12*x
[operation] Src, Dest:
| 指令 | 操作 | 说明 |
|---|---|---|
addq |
加法 | Dest = Dest + Src |
subq |
减法 | Dest = Dest - Src |
imulq |
乘法 | Dest = Dest * Src |
salq/shlq |
算术左移 | Dest = Dest << Src |
sarq |
算术右移 | Dest = Dest >> Src (符号填充) |
shrq |
逻辑右移 | Dest = Dest >> Src (补零) |
xorq |
按位异或 | Dest = Dest ^ Src |
andq |
按位与 | Dest = Dest & Src |
orq |
按位或 | Dest = Dest \| Src |
[operation] Dest:
| 指令 | 操作 | 说明 |
|---|---|---|
incq |
加1 | Dest = Dest + 1 |
decq |
减1 | Dest = Dest - 1 |
negq |
取负 | Dest = - Dest |
notq |
逐位取反 | Dest = ~Dest |