计算机系统 期中知识点速查

用途:考前快速翻阅的浓缩手册,覆盖教材第 1-6 章全部核心考点
标准:每条内容都能在 50 分钟机考中帮你快速回忆并答题
配合使用:[[计算机系统课程笔记]]、[[计算机系统期中题库]]
链接计算机系统专栏


Ch1 概论与编译流程

编译四阶段

阶段 工具 输入 → 输出 gcc 参数 能检查的错误
预处理 cpp .c.i -E 宏定义错误、缺失头文件
编译 cc1 .i.s -S 语法错误、类型错误
汇编 as .s.o -c 汇编指令合法性
链接 ld .o → 可执行 (无) 符号未定义/重复定义
  • .o 文件是二进制,不能用文本编辑器直接查看
  • .s 文件是汇编文本,可以查看
  • -g 生成调试信息,-O1/-O2 优化级别

CPU 与存储器

  • CPU 组成:运算器 + 控制器 + 寄存器(存储器不属于 CPU)
  • PC(程序计数器):保存下一条要执行的指令地址(IA32 中叫 %eip
  • 存储器层次:寄存器 > L1 > L2 > L3 > 主存 > 磁盘(速度↓ 容量↑ 造价↓)
  • 操作系统三大抽象:进程(CPU+ 主存 +I/O)、虚拟存储器(主存 + 磁盘)、文件(I/O)
  • 计算机能直接执行的是机器语言(不是汇编、不是高级语言)
  • 一条指令包含:操作码 + 操作数
  • 时钟周期是计算机操作的最小时间单位

主存(内存)

  • 主存是临时存储设备,存放程序和数据
  • 机器级程序使用的是虚拟地址(不是物理地址)
  • 1 字节 = 8 位(bit),字节是最小可寻址单位
  • 内存容量 = 2 地址位数 2^{地址位数} 2地址位数 字节

Ch2 二进制与信息表示

进制转换速查

十六进制 ↔ 二进制:每 1 位十六进制 = 4 位二进制

十六进制 0 1 2 3 4 5 6 7 8 9 A B C D E F
二进制 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

十进制 → 二进制:整数部分除 2 取余(从下往上),小数部分乘 2 取整(从上往下)

二进制小数:小数点右侧每位权重为 2 − 1 , 2 − 2 , 2 − 3 , … 2^{-1}, 2^{-2}, 2^{-3}, \ldots 21,22,23,

  • 只能精确表示 x / 2 k x/2^k x/2k 形式的小数
  • 1/3、1/5、1/10 等在二进制中是无限循环

位运算 vs 逻辑运算

运算 位运算 逻辑运算
&(逐位) &&(整体 0/1)
|(逐位) ||(整体 0/1)
~(逐位取反) !(非零→0,零→1)
异或 ^(逐位)

关键区别

  • !0x41 = 0x00(非零取反为 0)
  • ~0x41 = 0xBE(逐位取反)
  • 0x69 && 0x55 = 0x01(两个非零,逻辑与为 1)
  • 0x69 & 0x55 = 0x41(逐位与)

移位操作

操作 指令 规则
逻辑左移 shl / sal 右端补 0
算术左移 sal / shl 右端补 0(与逻辑左移等价)
逻辑右移 shr 左端补 0
算术右移 sar 左端补符号位
  • C 语言中,无符号数右移是逻辑右移,有符号数右移是算术右移
  • 左移 k 位 = 乘以 2 k 2^k 2k
  • 算术右移 k 位 ≈ 除以 2 k 2^k 2k(向负无穷舍入)
  • inc/dec 不改变 CFadd/sub 改变 CF

大小端

  • 小端(Little Endian):最低有效字节在最低地址(x86 使用小端)
  • 大端(Big Endian):最高有效字节在最低地址
  • 大小端只影响字节间排列顺序,字节内部存储不变

例:0x01234567 在小端存储(地址递增):67 45 23 01

数据类型大小

类型 32 位系统 64 位系统
char 1 1
short 2 2
int 4 4
long 4 8
float 4 4
double 8 8
指针 4 8
  • unsigned char 范围:[0, 255]
  • char 范围:[-128, 127]
  • short 范围:[-32768, 32767]

Ch5-1 整数表示

B2U 与 B2T

  • B2U(无符号): ∑ i = 0 w − 1 x i ⋅ 2 i \displaystyle\sum_{i=0}^{w-1} x_i \cdot 2^i i=0w1xi2i
  • B2T(补码): − x w − 1 ⋅ 2 w − 1 + ∑ i = 0 w − 2 x i ⋅ 2 i -x_{w-1} \cdot 2^{w-1} + \displaystyle\sum_{i=0}^{w-2} x_i \cdot 2^i xw12w1+i=0w2xi2i

补码求法

正数:补码 = 原码
负数:|x| 的二进制 → 全部取反 → +1

例:-25 的 8 位补码

  • 25 = 0001 1001
  • 取反 = 1110 0110
  • +1 = 1110 0111 = E7H

有符号 ↔ 无符号转换

核心:位模式不变,解释规则变

  • T2U(有符号→无符号):负数变大正数,新值 = 原值 + 2^w
  • U2T(无符号→有符号):大正数变负数,新值 = 原值 - 2^w
  • C 语言陷阱:有符号数与无符号数混合运算时,有符号数隐式转为无符号

截断

  • 直接保留低 k 位
  • 无符号截断: x m o d    2 k x \mod 2^k xmod2k
  • 有符号截断:先按无符号截断,再按补码重新解释

例:4 位 1011(补码=-5,无符号=11)截断到 3 位 → 011 → 补码=3,无符号=3

溢出判断

无符号加法溢出 s = x + y s = x + y s=x+y,若 s < x s < x s<x(或 s < y s < y s<y),则溢出

补码加法溢出

  • 正溢出:正 + 正 = 负(结果为 x + y − 2 w x + y - 2^w x+y2w
  • 负溢出:负 + 负 = 正(结果为 x + y + 2 w x + y + 2^w x+y+2w
  • 正 + 负永远不溢出

乘除与移位

  • 乘以 2 k 2^k 2k = 左移 k 位
  • 无符号除以 2 k 2^k 2k = 逻辑右移 k 位
  • 有符号除以 2 k 2^k 2k = 算术右移 k 位(向负无穷舍入)
  • 编译器常用移位 + 加法代替乘法(如 x*12 = x*8+x*4 = (x<<3)+(x<<2)
  • 整数除法比乘法慢

Ch5-2 浮点数

IEEE 754 格式

V = ( − 1 ) s × M × 2 E V = (-1)^s \times M \times 2^E V=(1)s×M×2E

符号 s 阶码 exp 尾数 frac
float (32 位) 1 bit 8 bit 23 bit
double (64 位) 1 bit 11 bit 52 bit

Bias = 2 k − 1 − 1 2^{k-1} - 1 2k11(float: 127,double: 1023)

三种类型

类型 阶码 E M 用途
规格化 非全 0 非全 1 exp - Bias 1.frac 大多数浮点数
非规格化 全 0 1 - Bias 0.frac 极小值和 ±0
特殊值 全 1 frac=0→±∞; frac≠0→NaN 特殊情况
  • 规格化值的尾数有隐含的前导 1(即 M = 1.frac)
  • 非规格化值的 E = 1 - Bias(不是 0 - Bias!为了与规格化平滑过渡)
  • 浮点数的正负由符号位 s 决定(不是阶码决定)
  • 阶码位数 → 影响范围;尾数位数 → 影响精度
  • 基数(2)在机器数中隐含不出现

舍入

  • 默认:向偶数舍入(Round to Nearest Even)
  • 中间值(恰好在两个可表示值正中间)→ 向偶数方向凑
  • 二进制中 " 向偶 "= 舍入后最低位为 0

浮点运算

  • 加法步骤:对阶(小阶向大阶对齐)→ 尾数加法 → 规格化 → 舍入 → 判溢出
  • 浮点加法满足交换律,不满足结合律
  • 浮点乘法满足交换律,不满足结合律分配律
  • (3.14 + 1e20) - 1e20 = 0(不是 3.14!因为精度丢失)

C 语言类型转换

转换 结果
int → double 精确(double 有 52 位尾数,够装 32 位 int)
int → float 不会溢出,但可能舍入(float 只有 23 位尾数)
float/double → int 向零截断,可能溢出(行为未定义)

Ch3 VSPM 原型机

  • MOVB:从内存读一个字节到寄存器
  • MOVC:将立即数(常数)写入寄存器
  • MOVD:将寄存器值写入内存
  • JMP:无条件跳转
  • JG:大于时跳转(基于条件码判断)

Ch4 ATT 汇编语言

MOV 指令族

指令 操作数大小
movb 1 字节
movw 2 字节
movl 4 字节
movq 8 字节

限制:不能两个操作数都是内存,必须经过寄存器中转

零扩展 vs 符号扩展

指令 含义 高位填充
movzbl byte → long 零扩展 补 0
movzwl word → long 零扩展 补 0
movsbl byte → long 符号扩展 补符号位
movswl word → long 符号扩展 补符号位

例:%dh = 0xCD%eax = 0x98765432

  • movzbl %dh, %eax%eax = 0x000000CD(高位补 0)
  • movsbl %dh, %eax%eax = 0xFFFFFFCD(CD 最高位为 1,补 1)
  • movb %dh, %al%eax = 0x987654CD(只改低字节,高位不变)

LEA 指令

leal D(Rb, Ri, S), Dest → Dest = Rb + Ri × S + D

  • 不访问内存,纯地址/算术计算
  • 不设置条件码
  • S 只能是 1, 2, 4, 8

常见题型:

  • leal 9(%eax,%ecx,2), %edx → %edx = 9 + x + 2y(不是 9(x+2y))
  • leal (%eax,%ecx,5), %edx → %edx = x + 5y(不是 5x)
  • leal 6(%eax), %edx → %edx = x + 6(不是 6x)

寻址模式

类型 格式 计算 示例
立即数 $Imm 值就是 Imm $0x400
寄存器 %reg R[reg] %eax
绝对 Imm M[Imm] 0x400
间接 (%reg) M[R[reg]] (%eax)
基址+偏移 Imm(%reg) M[Imm + R[reg]] 8(%ebp)
比例变址 Imm(Rb,Ri,S) M[Imm + R[Rb] + R[Ri]×S] (%edx,%ecx,4)

Intel vs ATT 格式区别

区别 ATT Intel
操作数顺序 源, 目的 目的, 源
寄存器前缀 %eax eax
大小后缀 movl 无后缀
内存引用 8(%ebp) [ebp+8]
立即数前缀 $

算术指令要点

  • inc/dec 不改变 CF(与 add 1 的区别!)
  • salshl 完全等价(都是逻辑/算术左移,补 0)
  • sar 算术右移(填符号位),shr 逻辑右移(填 0)

Ch6-1 条件码与控制

四个条件码

条件码 名称 含义
CF Carry Flag 最高位进位/借位(无符号溢出)
ZF Zero Flag 结果为 0
SF Sign Flag 结果为负(最高位为 1)
OF Overflow Flag 有符号溢出

不设置条件码的指令leamov

CMP 与 TEST

  • cmp b, a:计算 a - b,只设条件码不存结果
  • test b, a:计算 a & b,只设条件码不存结果
  • test %eax, %eax:检测 %eax 是否为零/负

跳转指令

指令 条件 含义
je / jz ZF=1 等于/零
jne / jnz ZF=0 不等于/非零
js SF=1 负数
jg ~(SF⊕OF) & ~ZF 大于(有符号)
jge ~(SF⊕OF) 大于等于(有符号)
jl SF⊕OF 小于(有符号)
jle (SF⊕OF) | ZF 小于等于(有符号)
ja ~CF & ~ZF 高于(无符号 >)
jae ~CF 高于等于(无符号 >=)
jb CF 低于(无符号 <)

有符号比较核心:a < b ⟺ SF ⊕ OF = 1

条件传送

cmovX Src, Dest:条件为真时执行 mov,否则不操作

  • cmova:CF=0 且 ZF=0 时传送(无符号大于)

Ch6-2 过程调用与栈帧

栈操作

  • 栈向低地址方向增长
  • pushl Src%esp -= 4,然后 M[%esp] = Src
  • popl DestDest = M[%esp],然后 %esp += 4
  • pushl %ebp 等价于 subl $4, %esp + movl %ebp, (%esp)

CALL / RET / LEAVE

指令 等价操作 作用
call Label push 返回地址 + jmp Label 调用过程
ret pop %eip 返回调用者
leave movl %ebp, %esp + popl %ebp 恢复栈帧
  • call 之后 %esp 减 4(压入返回地址)
  • 返回地址 = call 指令之后那条指令的地址(不是 call 本身的地址)

栈帧结构(从高地址到低地址)

参数 n
...
参数 1         ← 调用者栈帧
返回地址        ← call 指令压入
旧 %ebp        ← 被调用者 push %ebp
局部变量        ← 被调用者栈帧
临时空间
              ← %esp(栈顶)

寄存器保护约定(IA32)

类型 寄存器 谁负责保存
调用者保存 %eax, %ecx, %edx 调用者在 call 前保存
被调用者保存 %ebx, %esi, %edi 被调用者在使用前 push,返回前 pop
  • 返回值存在 %eax
  • %esp 栈顶指针,%ebp 帧指针
  • IA32 参数通过传递;x86-64 前 6 个参数通过寄存器(%rdi, %rsi, %rdx, %rcx, %r8, %r9)

关键判断

  • 局部变量通过分配(不是堆)
  • 程序寄存器组是唯一能被所有过程共享的资源 → 正确
  • 函数不创建栈帧的条件:所有局部变量在寄存器中 + 不调用其他函数
  • pop %eip不合法(不存在这条指令)

Ch6-3 数据结构

数组

  • T A[N]:分配 N × sizeof(T) 字节连续内存
  • A[i] 地址 = 基址 + i × sizeof(T)
  • 汇编:movl (%edx,%eax,4), %eax → 访问 int 数组 A[i]

二维数组

  • T D[R][C]:行优先,占 R × C × sizeof(T) 字节
  • D[i][j] 地址 = 基址 + (i × C + j) × sizeof(T)

结构体对齐(三规则)

  1. 首地址必须是最大成员字节数的整数倍
  2. 每个成员地址必须是自身字节数的整数倍(不够就插填充)
  3. 总大小必须是最大成员字节数的整数倍(末尾补填充)

优化技巧:大尺寸字段放前面,可减少填充

联合体

  • 所有成员共享同一基地址
  • 总大小 = 最大成员的大小

安全

  • 缓冲区溢出:向栈上缓冲区写入过多数据,覆盖返回地址
  • 三层防御
    1. ASLR(地址空间布局随机化):每次运行地址不同
    2. Stack Canary(栈金丝雀):在返回地址前插入随机值,返回前校验
    3. NX bit(不可执行位):栈/堆标记为不可执行
  • " 限制访问形式 "不是防溢出机制
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐