(注:使用 英特尔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 |