Ruixiang Li

Machine Level Programming I Basic

(注:使用 英特尔64位指令集,也称CISC)

CISC:Complex Instruction Set Computer,复杂指令集计算机

RISC:Reduced Instruction Set Computer,精简指令集计算机

C,Assembly,Machine code

Definitions

Architecture(架构):也称ISA (Instruction Set Architecture),是处理器设计中需要理解或编写汇编/机器代码的部分。 例如:Instruction set specification(指令集规范)、registers(寄存器)

Microarchitecture(微架构):架构的具体实现。 例如:Cache sizes(缓存大小)、Core frequency(核心频率)。

Code Form(代码形式)

Example ISAs(指令集架构示例)

Assembly/Machine Code View

CPU 核心组件与状态

Memory(内存)特性

CPU 和 Memory 的交互

Turning C into Object Code

C 程序到可执行程序的编译流程

关键工具与作用

常用选项

静态库的作用

汇编特点

1.数据类型

2.操作Operations

机器码示例

1.C Code

*dest = t

指针赋值,将变量t储存到指针dest指向的位置。

2.Assembly

movq %rax, (%rbx)

3.Object Code

0x40059e:  48 89 03

0x40059e:该指令在内存的地址;

48 89 03:该指令的机器码(3字节)。

Assembly Basic:Registers,operands,move

x86-64 整数寄存器

%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寄存器称为栈指针/栈顶指针

Moving Data

代码:

movq Sourse, Dest

movq 指令用于传输数据:

使用 movq 可以:

操作数

在汇编指令中,操作数可以是以下三种类型:立即数、寄存器 和 内存。

1. Immediate (立即数):一个常量值,通常是整型数据。

2. Register (寄存器):程序在运行过程中使用的处理器内部寄存器。

3. Memory (内存):程序操作的内存地址。

Combinations

我们无法将一个直接数作为目标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

内存寻址模式(Memory Addressing Modes)

内存寻址包括常规寻址偏移寻址

模式 语法 数学公式 示例
Normal (%R) Mem[Reg[R]] movq (%rcx), %rax
Displacement D(%R) Mem[Reg[R] + D] movq 8(%rbp), %rdx

核心要点:

  1. Normal 寻址是最基础的内存访问,用于访问寄存器指向地址的内存内容(C 指针解引用)。
  2. Displacement 寻址允许灵活地操作复杂的数据结构(例如栈、数组、结构体),可以访问基址加偏移量的内存(C 栈、数组等)

example:

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) - 偏移量

Rb (Base Register) - 基址寄存器

Ri (Index Register) - 索引寄存器

S (Scale) - 比例因子/尺度

地址计算:

假设地址:%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

Arittmetic & logical operations

地址计算load effective address

代码leaq Src, Dst.

用途 (Uses)

  1. 计算地址而不引用内存

    • 用于将某个地址计算结果存储到寄存器,而不真的读取该地址的内存内容。
    • 例如:C 代码中 p = &x[i] 可以通过 leaq 快速实现。
  2. 计算算术表达式

    • 常用于计算类似如下形式的数学表达式:x + k * y

    • 其中,k 可能是 1, 2, 4, 8 (常见比例因子,对应常规跨字节的数据访问)。

Example

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