Instruction Addressing Modes
寻址方式回答两个问题: 下一条指令在哪里? 本条指令要使用的操作数在哪里? 前者称为指令寻址,后者称为数据寻址。在一条指令中,操作码决定“做什么”,寻址方式决定“到哪里找操作对象”。 为什么需要不同寻址方式指令采用不同寻址方式是为了让指令系统可缩短指令字长,扩大寻址空间,提高编程灵活性。 指令寻址指令寻址是确定下一条将要执行的指令地址。下一条指令地址始终由程序计数器 PC 给出。 顺序寻址顺序寻址是默认情况:执行完当前指令后,PC 自动指向下一条指令。 若采用定长指令字结构,且主存按字编址,常写作: $$PC \leftarrow (PC) + 1$$ 这里的 1 表示“一个指令字”。若主存按字节编址,且一条指令占 n 字节,则应理解为: $$PC \leftarrow (PC) + n$$ Note PC 实际增加多少,取决于指令长度和主存编址方式。 若采用变长指令字结构,CPU 取到指令开头后,需要根据操作码判断这条指令总长度,再把 PC 改为下一条指令的起始地址。 跳跃寻址跳跃寻址由转移类指令指出下一条指令地址。CPU...
x86 Assembly Basics
从高级语言到机器码C/C++ 程序到可执行文件通常经历预处理、编译、汇编、链接几个阶段。其中与本章最相关的是: 高级语言:面向人,描述算法逻辑,例如 y = a * b + c。 汇编语言:用助记符描述机器指令,例如 mov eax, ebx。 机器语言:CPU 真正执行的二进制编码。 汇编语言和机器语言大体一一对应。读汇编时重点看三件事: 指令要做什么操作。 操作数来自哪里。 结果写回哪里,是否改变程序执行流。 基本格式同一条 x86 指令可以有不同汇编格式: 项目 Intel 格式 AT&T 格式 操作数顺序 op dst, src op src, dst 寄存器 eax %eax 立即数 5 $5 主存地址 [ebx + 8] 8(%ebx) 读写长度 byte ptr、word ptr、dword ptr 指令后缀 b、w、l 例如同样是把 ebx + ecx * 4 + 8 所指地址处的 32 位数据读入 eax: 12345; Intelmov eax, dword ptr [ebx + ecx * 4 +...
Function Calls And Stack Frames
函数调用在机器级的工作是: 从调用者跳转到被调用函数的第一条指令。 被调用函数结束后,能回到调用点后面的那条指令,并继续使用调用者原来的执行状态。 因此,一次函数调用必须保存返回地址、保存必要的上下文、传递参数、提供局部变量空间,并把返回值交回调用者。 函数调用栈运行中的进程有自己的虚拟地址空间。用户栈通常位于高地址区域,并向低地址增长。每发生一次函数调用,就会在栈上形成一个新的栈帧;函数返回时,这个栈帧被撤销。 栈帧可以理解为某一次函数调用的“现场”: 参数:调用者传给被调用者的数据。 返回地址:被调用函数结束后应该回到哪里。 保存的旧 ebp:用于恢复调用者栈帧。 局部变量:被调用函数自己的临时数据。 必要时保存的寄存器值:避免调用其他函数时破坏中间结果。 递归调用并不特殊。每递归一次,就多压入一层栈帧。不同递归层的参数和局部变量互不覆盖,因为它们在不同的栈帧里。 esp 与 ebp在 32 位 x86 的典型栈帧模型中: esp 指向当前栈顶,执行 push、pop、call、ret 时会变化。 ebp 指向当前栈帧的基地址,函数体内通常保持不变。 因为...
Page Replacement Algorithms
页面置换算法请求分页系统发生缺页故障后,如果主存中还有空闲页框,直接把缺失页面调入即可;如果没有空闲页框,就必须从某个驻留集中选一页换出。页面置换算法解决的就是“换出哪一页”。 页面换入、换出都需要外存 I/O,代价远大于普通访存。因此,好的置换算法应尽量减少缺页次数,尤其要避免把很快又会访问的页面换出。 Note FIFO、LRU、Random 的基本思想在 另一处 中已经出现过。这里重点看它们在页框、缺页故障、访问位、修改位中的执行过程。 基本指标设页面访问序列长度为 $N$。 指标 含义 缺页次数 访问页面不在主存的次数 置换次数 缺页且没有空闲页框,需要换出旧页的次数 缺页率 $\text{缺页次数}/N$ 缺页不一定发生置换。开始时页框可能为空,此时缺页只是调入页面;只有页框已满后再缺页,才需要置换。 Example 3 个页框初始为空,访问 7, 0, 1 会连续缺页 3 次,但没有发生页面置换,因为每次都有空闲页框。 ↻ + − OPT最佳置换算法 OPT...
Memory Mapped Files And mmap
内存映射文件与 mmap内存映射文件把文件的一段内容映射到进程的虚拟地址空间。映射建立后,程序可以像访问普通内存一样读写这段地址;文件数据的调入、写回由操作系统结合缺页机制完成。 12int fd = open("data.bin", O_RDWR);void *p = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 这里的 p 是一个虚拟地址。程序访问 p[i] 时,CPU 仍然发出虚拟地址;MMU 查页表;若对应文件页尚未在主存中,就触发缺页故障,由 OS 从文件读入对应页面。 mmapmmap 的关键是建立映射关系: $$\text{进程虚拟页} \longleftrightarrow \text{文件中的某个页大小区间}$$ 一次典型访问过程: open 打开文件,得到文件描述符。 mmap 在进程虚拟地址空间中划出一段区域。 OS...
Virtual Memory And Demand Paging
传统存储管理有两个限制: 一次性:作业必须一次性全部装入主存后才能运行。 驻留性:作业装入后通常一直驻留在主存,直到运行结束。 这两个限制会降低主存利用率:程序运行时往往只会在一段时间内集中访问少量代码和数据,暂时不用的部分不必长期占用主存。 虚拟存储器的核心思想是:基于局部性原理,只把当前需要的页面装入主存;暂时不用的页面留在外存;访问到不在主存的页面时,再由操作系统把它调入。 虚拟存储器在用户看来,系统好像提供了一片比实际主存更大的内存;实际物理主存没有变,只是操作系统和硬件共同把主存与外存组织成了一个逻辑上的大地址空间。 虚拟存储器有三个特征: 特征 含义 多次性 作业不必一次性全部装入主存,可以分多次调入 对换性 作业运行过程中,页面可以在主存和外存之间换入、换出 虚拟性 从逻辑上扩充内存容量,使用户看到的容量大于实际主存容量 容量上限 虚拟存储器的最大容量受 CPU 地址结构限制,实际可用容量还受主存与外存容量限制: $$\text{虚拟存储实际容量} = \min(\text{CPU 寻址范围}, \text{主存容量} +...
Exception And Interrupt Brief
异常与中断CPU 正常执行指令时,可能因为某个事件临时改变控制流,转去执行操作系统内核中的处理程序。这个机制常被统称为“中断机制”,分为以下两种: 异常:由 CPU 内部原因产生,通常和当前正在执行的指令有关。 中断:由 CPU 外部设备产生,通常和当前正在执行的指令无关。 异常异常来自 CPU...
Memory Management Overview
存储管理多个程序如何同时装入内存?如何互不干扰?如何让程序看到一套稳定的地址空间? 存储管理主要处理四件事: 功能 要解决的问题 内存空间的分配与回收 哪个进程占用哪段内存,进程结束后如何释放 地址转换 程序中的逻辑地址如何变成真正访问主存的物理地址 内存保护 一个进程不能越界访问其他进程或操作系统的内存 内存共享 多个进程如何共享同一段代码或同一份数据 内存扩展 物理内存不够时,如何让程序仍然能运行 程序如何进入内存C程序从源码到可执行文件,要经过预处理、编译、汇编、链接四个阶段;可执行文件还必须被装入内存,CPU 才能执行。 存储管理更关心后半段: 编译形成目标模块。 链接把目标模块和库函数合成装入模块。 装入程序把装入模块放入内存。 CPU...
Cache Memory
Cache主存容量大,但速度仍然比 CPU 慢得多。Cache 逻辑上位于 CPU 和主存之间(物理上通常集成在CPU内部),对于所有程序员和 OS 透明,用更快的 SRAM 保存主存中近期可能访问的数据副本,从而缓和 CPU 与主存之间的速度差距。 Cache 依赖的是局部性原理: 局部性 在 Cache 中的体现 时间局部性 刚访问过的主存块留在 Cache 中,短时间内再次访问时可命中 空间局部性 一次从主存调入整个块,后续访问相邻地址时可直接命中 Cache 与主存之间以块为单位交换数据。主存被划分为若干主存块,Cache 被划分为若干 Cache 行;一行 Cache 存放一个主存块的副本。 Note “Cache 行”“Cache 块”常指同一个东西:Cache 中能容纳一个主存块的空间。 Cache 对于所有程序员和 OS 透明,即 Cache 功能全部由硬件实现。 现代处理器中的 Cache 常见两种组织特征: 组织方式 含义 作用 分离 Cache 将指令 Cache 和数据 Cache 分开,常记为 I-Cache 与...