网易首页 > 网易号 > 正文 申请入驻

一口气看完45个寄存器,CPU核心技术大揭秘

0
分享至

  作者 | 轩辕之风O

  来源 | 编程技术宇宙 (ID:xuanyuancoding)

  头图 | CSDN 下载自东方IC

  序言

  前段时间,我连续写了十来篇CPU底层系列技术故事文章,有不少读者私信我让我写一下 CPU 的寄存器。

  寄存器这个太多太复杂,不适合写故事,拖了很久,总算是写完了,这篇文章就来详细聊聊x86/x64架构的 CPU 中那些纷繁复杂的寄存器们。

  长文预警,时速较快,请系好安全带~起飞~

  自1946年冯·诺伊曼领导下诞生的世界上第一台通用电子计算机ENIAC至今,计算机技术已经发展了七十多载。

  从当初专用于数学计算的庞然大物,到后来大型机服务器时代,从个人微机技术蓬勃发展,到互联网浪潮席卷全球,再到移动互联网、云计算日新月异的当下,计算机变的形态各异,无处不在。

  这七十多年中,出现了数不清的编程语言,通过这些编程语言,又开发了无数的应用程序。

  可无论什么样的应用程序,什么样的编程语言,最终的程序逻辑都是要交付给 CPU 去执行实现的(当然这里有些不严谨,除了 CPU,还有协处理器、GPU 等等)。所以了解和学习 CPU 的原理都是对计算机基础知识的夯实大有裨益。

  在七十多年的漫长历程中,也涌现了不少架构的 CPU。

MIPS PowerPC x86/x64 IA64 ARM ······

  这篇文章就以市场应用最为广泛的x86-x64架构为目标,通过学习了解它内部的100个寄存器功能作用,来串联阐述CPU底层工作原理。

  通过这篇文章,你将了解到:

CPU指令执行原理 内存寻址技术 软件调试技术原理 中断与异常处理 系统调用 CPU多任务技术

  
什么是寄存器?

  寄存器是 CPU 内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果以及一些 CPU 运行需要的信息。

  x86 架构 CPU 走的是复杂指令集(CISC)路线,提供了丰富的指令来实现强大的功能,与此同时也提供了大量寄存器来辅助功能实现。这篇文章将覆盖下面这些寄存器:

通用寄存器 标志寄存器 指令寄存器 段寄存器 控制寄存器 调试寄存器 描述符寄存器 任务寄存器 MSR寄存器

  
通用寄存器

  首当其冲的是通用寄存器,这些的寄存器是程序执行代码最最常用,也最最基础的寄存器,程序执行过程中,绝大部分时间都是在操作这些寄存器来实现指令功能。

  所谓通用,即这些寄存器 CPU 没有特殊的用途,交给应用程序“随意”使用。注意,这个随意,我打了引号,对于有些寄存器,CPU 有一些潜规则,用的时候要注意。

eax: 通常用来执行加法,函数调用的返回值一般也放在这里面 ebx: 数据存取 ecx: 通常用来作为计数器,比如for循环 edx: 读写I/O端口时,edx用来存放端口号 esp: 栈顶指针,指向栈的顶部 ebp: 栈底指针,指向栈的底部,通常用ebp+偏移量的形式来定位函数存放在栈中的局部变量 esi: 字符串操作时,用于存放数据源的地址 edi: 字符串操作时,用于存放目的地址的,和esi两个经常搭配一起使用,执行字符串的复制等操作

  在 x64架构中,上面的通用寄存器都扩展成为64位版本,名字也进行了升级。当然,为了兼容32位模式程序,使用上面的名字仍然是可以访问的,相当于访问64位寄存器的低32位。

rax rbx rcx rdx rsp rbp rsi rdi

  除了扩展原来存在的通用寄存器,x64架构还引入了8个新的通用寄存器:

r8-r15

  在原来32位时代,函数调用时,那个时候通用寄存器少,参数绝大多数时候是通过线程的栈来进行传递(当然也有使用寄存器传递的,比如著名的C++this指针使用 ecx 寄存器传递,不过能用的寄存器毕竟不多)。

  进入x64时代,寄存器资源富裕了,参数传递绝大多数都是用寄存器来传了。寄存器传参的好处是速度快,减少了对内存的读写次数。

  当然,具体使用栈还是用寄存器传参数,这个不是编程语言决定的,而是编译器在编译生成 CPU 指令时决定的,如果编译器非要在 x64 架构 CPU 上使用线程栈来传参那也不是不行,这个对高级语言是无感知的。

  标志寄存器

  标志寄存器,里面有众多标记位,记录了 CPU 执行指令过程中的一系列状态,这些标志大都由 CPU 自动设置和修改:

CF 进位标志 PF 奇偶标志 ZF 零标志 SF 符号标志 OF 补码溢出标志 TF 跟踪标志 IF 中断标志 ······

  在 x64 架构下,原来的 eflags 寄存器升级为64位的 rflags,不过其高32位并没有新增什么功能,保留为将来使用。

  指令寄存器

eip: 指令寄存器可以说是CPU中最最重要的寄存器了,它指向了下一条要执行的指令所存放的地址,CPU的工作其实就是不断取出它指向的指令,然后执行这条指令,同时指令寄存器继续指向下面一条指令,如此不断重复,这就是CPU工作的基本日常。

  而在漏洞攻击中,黑客想尽办法费尽心机都想要修改指令寄存器的地址,从而能够执行恶意代码。

  同样的,在 x64 架构下,32位的 eip 升级为64位的rip寄存器。

  
段寄存器

  段寄存器与 CPU 的内存寻址技术紧密相关。

  早在16位的8086 CPU 时代,内存资源宝贵,CPU 使用分段式内存寻址技术:

  16位的寄存器能寻址的范围是64KB,通过引入段的概念,将内存空间划分为不同的区域:分段,通过段基址+段内偏移段方式来寻址。

  这样一来,段的基地址保存在哪里呢?8086 CPU 专门设置了几个段寄存器用来保存段的基地址,这就是段寄存器段的由来。

  段寄存器也是16位的。

  段寄存器有下面6个,前面4个是早期16位模式就引入了,到了32位时代,又新增了 fs 和 gs 两个段寄存器。

cs: 代码段 ds: 数据段 ss: 栈段 es: 扩展段 fs: 数据段 gs: 数据段

  段寄存器里面存储的内容与 CPU 当前工作的内存寻址模式紧密相关。

  当CPU处于16位实地址模式下时,段寄存器存储段的基地址,寻址时,将段寄存器内容左移4位(乘以16)得到段基地址+段内偏移得到最终的地址。

  当 CPU 工作于保护模式下,段寄存器存储的内容不再是段基址了,此时的段寄存器中存放的是段选择子,用来指示当前这个段寄存器“指向”的是哪个分段。

  注意我这里的指向打了引号,段寄存器中存储的并不是内存段的直接地址,而是段选择子,它的结构如下:

  16个 bit 长度的段寄存器内容划分了三个字段:

PRL: 特权请求级,就是我们常说的ring0-ring3四个特权级。 TI: 0表示用的是全局描述符表GDT,1表示使用的是局部描述符表LDT。 Index: 这是一个表格中表项的索引值,这个表格叫内存描述符表,它的每一个表项都描述了一个内存分段。

  这里提到了两个表,全局描述符表 GDT 和局部描述符表 LDT,关于这两个表的介绍,下面介绍描述符寄存器时再详述,这里只需要知道,这是 CPU 支持分段式内存管理需要的表格,放在内存中,表格中的每一项都是一个描述符,记录了一个内存分段的信息。

  保护模式下的段寄存器和段描述符到最后的内存分段,通过下图的方式联系在一起:

  通用寄存器、段寄存器、标志寄存器、指令寄存器,这四组寄存器共同构成了一个基本的指令执行环境,一个线程的上下文也基本上就是这些寄存器,在执行线程切换的时候,就是修改它们的内容。

  控制寄存器

  控制寄存器是 CPU 中一组相当重要的寄存器,我们知道 eflags 寄存器记录了当前运行线程的一系列关键信息。

  那 CPU 运行过程中自身的一些关键信息保存在哪里呢?答案是控制寄存器!

  32位 CPU 总共有cr0-cr4共5个控制寄存器,64位增加了 cr8。他们各自有不同的功能,但都存储了 CPU 工作时的重要信息:

cr0: 存储了CPU控制标记和工作状态 cr1: 保留未使用 cr2: 页错误出现时保存导致出错的地址 cr3: 存储了当前进程的虚拟地址空间的重要信息——页目录地址 cr4: 也存储了CPU工作相关以及当前人任务的一些信息 cr8: 64位新增扩展使用

  其中,CR0 尤其重要,它包含了太多重要的 CPU 信息,值得单独关注一下:

  一些重要的标记位含义如下:

  PG: 是否启用内存分页

  AM: 是否启用内存对齐自动检查

  WP: 是否开启内存写保护,若开启,对只读页面尝试写入时将触发异常,这一机制常常被用来实现写时复制功能

  PE: 是否开启保护模式

  除了 CR0,另一个值得关注的寄存器是 CR3,它保存了当前进程所使用的虚拟地址空间的页目录地址,可以说是整个虚拟地址翻译中的顶级指挥棒,在进程空间切换的时候,CR3 也将同步切换。

  调试寄存器

  在x86/x64 CPU 内部,还有一组用于支持软件调试的寄存器。

  调试,对于我们程序员是家常便饭,必备技能。但你想过你的程序能够被调试背后的原理吗?

  程序能够被调试,关键在于能够被中断执行和恢复执行,被中断的地方就是我们设置的断点。那程序是如何能在遇到断点的时候停下来呢?

  对于一些解释执行(PHP、Python、JavaScript)或虚拟机执行(Java)的高级语言,这很容易办到,因为它们的执行都在解释器/虚拟机的掌控之中。

  而对于像C、C++这样的“底层”编程语言,程序代码是直接编译成CPU的机器指令来执行的,这就需要 CPU 来提供对于调试的支持了。

  对于通常的断点,也就是程序执行到某个位置下就停下来,这种断点实现的方式,在x86/x64上,是利用了一条软中断指令:int 3来进行实现的。

  注意,这里的int不是指高级语言里面的整数,而是表示 interrupt 中断的意思,是一条汇编指令,int 3则表示中断向量号为3的中断。

  在我们使用调试器下断点时,调试器将会把对应位置的原来的指令替换为一个 int 3 指令,机器码为 0xCC。这个动作对我们是透明的,我们在调试器中看到的依然是原来的指令,但实际上内存中已经不是原来的指令了。

  顺便提一句,两个 0xCC 是汉字【烫】的编码,在一些编译器里,会给线程的栈中填充大量的 0xCC,如果程序出错的时候,我们经常会看到很多烫烫烫出现,就是这个原因。

  言归正传,CPU在执行这条int 3指令时,将自动触发中断处理流程(虽然这实际上不是一个真正的中断),CPU将取出IDTR寄存器指向的中断描述符表IDT的第3项,执行里面的中断处理函数。

  而这个中断描述符表,早在操作系统启动之初,就已经提前安排好了,所以执行这条指令后,操作系统的中断处理函数将介入,来处理这一事件。

  后面的过程就多了,简单来说,操作系统会把触发这一事件的进程冻结起来,随后将这一事件发送到调试器,调试器拿到之后就知道目标进程触发断点了。这个时候,咱们程序员就能通过调试器的UI交互界面或者命令行调试接口来调试目标进程,查看堆栈、查看内存、变量都随你。

  如果我们要继续运行,调试器将会把之前修改的int 3指令给恢复回去,然后告知操作系统:我处理完了,把目标进程解冻吧!

  上面简单描述了一下普通断点的实现原理。现在思考一个场景:我们发现一个bug,某个全局整数型变量的值老是莫名其妙被修改,但你发现有很多线程,很多函数都有可能会去修改这个变量,你想找出到底谁干的,怎么办?

  这个时候上面的普通断点就没办法了,你需要一种新的断点:硬件断点

  这时候就该本小节的主人公调试寄存器登场表演了。

  在x86架构CPU内部,提供了8个调试寄存器DR0~DR7。

  DR0~DR3这是四个用于存储地址的寄存器

  DR4~DR5:这两个有点特殊,受前面提到的CR4寄存器中的标志位DE位控制,如果CR4的DE位是1,则DR4、DR5是不可访问的,访问将触发异常。如果CR4的DE位是0,则DR4和DR5将会变成DR6和DR7的别名,相当于做了一个软链接。这样做是为了将DR4、DR5保留,以便将来扩展调试功能时使用。

  DR6:这个寄存器中存储了硬件断点触发后的一些状态信息

  DR7:调试控制寄存器,这里面记录了对DR0-DR3这四个寄存器中存储地址的中断方式(是对地址的读,还是写,还是执行)、数据长度(1/2/4个字节)以及作用范围等信息

  通过调试器的接口设置硬件断点后,CPU在执行代码的过程中,如果满足条件,将自动中断下来。

  回答前面提出的问题,想要找出是谁偷偷修改了全局整形变量,只需要通过调试器设置一个硬件写入断点即可。

  描述符寄存器

  所谓描述符,其实就是一个数据结构,用来记录一些信息,‘描述’一个东西。把很多个描述符排列在一起,组成一个表,就成了描述符表。再使用一个寄存器来指向这个表,这个寄存器就是描述符寄存器

  在x86/x64系列CPU中,有三个非常重要的描述符寄存器,它们分别存储了三个地址,指向了三个非常重要的描述符表。

  gdtr:全局描述符表寄存器,前面提到,CPU现在使用的是段+分页结合的内存管理方式,那系统总共有哪些分段呢?这就存储在一个叫全局描述符表(GDT)的表格中,并用gdtr寄存器指向这个表。这个表中的每一项都描述了一个内存段的信息。

  ldtr:局部描述符表寄存器,这个寄存器和上面的gdtr一样,同样指向的是一个段描述符表(LDT)。不同的是,GDT是全局唯一,LDT是局部使用的,可以创建多个,随着任务段切换而切换(下文介绍任务寄存器会提到)。

  GDT和LDT中的表项,就是段描述符,描述了一个内存分段的信息,其结构如下:

  一个表项占据8个字节(32位CPU),里面存储了一个内存分段的诸多信息:基地址、大小、权限、类型等信息。

  除了这两个段描述符寄存器,还有一个非常重要的描述符寄存器:

  idtr:中断描述符表寄存器,指向了中断描述符表IDT,这个表的每一项都是一个中断处理描述符,当CPU执行过程中发生了硬中断、异常、软中断时,将自动从这个表中定位对应的表项,里面记录了发生中断、异常时该去哪里执行处理函数。

  IDT中的表项称为Gate,中文意思为,因为这是应用程序进入内核的主要入口。虽然表的名字叫中断描述符表,但表中存储的不全是中断描述符,IDT中的表项存在三种类型,对应三种类型的门:

任务门 陷阱门 中断门

  三种描述符中都存储了处理这个中断/异常/任务时该去哪里处理的地址。三种门用途不一,其中中断门是真正意义上的中断,而像前面提到的调试指令int 3以及老式的系统调用指令int 2e/int 80都属于陷阱门。任务门则用的较少,要了解任务门,先了解下任务寄存器。

  任务寄存器

  现代操作系统,都是支持多任务并发运行的,x86架构CPU为了顺应时代潮流,在硬件层面上提供了专门的机制用来支持多任务的切换,这体现在两个方面:

CPU 内部设置了一个专用的寄存器——任务寄存器 TR,它指向当前运行的任务。 定义了描述任务的数据结构 TSS,里面存储了一个任务的上下文(一系列寄存器的值),下图是一个32位 CPU 的 TSS 结构图:

  x86CPU 的构想是每一个任务对应一个 TSS,然后由 TR 寄存器指向当前的任务,执行任务切换时,修改 TR 寄存器的指向即可,这是硬件层面的多任务切换机制。

  这个构想其实还是很不错的,然而现实却打了脸,包括 Linux 和 Windows 在内的主流操作系统都没有使用这个机制来进行线程切换,而是自己使用软件来实现多线程切换。

  所以,绝大多数情况下,TR 寄存器都是指向固定的,即便线程切换了,TR 寄存器仍然不会变化。

  注意,我这里说的的是绝大多数情况,而没有说死。虽然操作系统不依靠 TSS 来实现多任务切换,但这并不意味着 CPU 提供的 TSS 操作系统一点也没有使用。还是存在一些特殊情况,如一些异常处理会使用到 TSS 来执行处理。

  下面这张图,展示了控制寄存器、描述符寄存器、任务寄存器构成的全貌:

  模型特定寄存器

  从80486之后的x86架构 CPU,内部增加了一组新的寄存器,统称为MSR 寄存器,中文直译是模型特定寄存器,意思是这些寄存器不像上面列出的寄存器是固定的,这些寄存器可能随着不同的版本有所变化。这些寄存器主要用来支持一些新的功能。

  随着x86 CPU 不断更新换代,MSR 寄存器变的越来越多,但与此同时,有一部分 MSR 寄存器随着版本迭代,慢慢固化下来,成为了变化中那部分不变的,这部分 MSR 寄存器,Intel 将其称为 Architected MSR,这部分 MSR 寄存器,在命名上,统一加上了IA32的前缀。

  这里选取三个代表性的 MSR 简单介绍一下:

IA32_SYSENTER_CS IA32_SYSENTER_ESP IA32_SYSENTER_EIP

  这三个MSR寄存器是用来实现快速系统调用

  在早期的x86架构 CPU 上,系统调用依赖于软中断实现,类似于前面调试用到的int 3指令,在 Windows 上,系统调用用到的是int 2e,在 Linux 上,用的是int 80

  软中断毕竟还是比较慢的,因为执行软中断就需要内存查表,通过 IDTR 定位到 IDT,再取出函数进行执行。

  系统调用是一个频繁触发的动作,如此这般势必对性能有所影响。在进入奔腾时代后,就加上了上面的三个 MSR 寄存器,分别存储了执行系统调用后,内核系统调用入口函数所需要的段寄存器、堆栈栈顶、函数地址,不再需要内存查表。快速系统调用还提供了专门的 CPU 指令sysenter/sysexit用来发起系统调用和退出系统调用。

  在64位上,这一对指令升级为syscall/sysret

  总结

  以上就是全部要介绍的寄存器了,需要说明一下的是,这并不是 x86 CPU 全部所有的寄存器,除了这些,还存在 XMM、MMX、FPU 浮点数运算等其他寄存器。

  这篇文章以 x86/x64 架构 CPU 为目标,通过对 CPU 内部寄存器的阐述,串讲了 CPU 执行代码机制、内存寻址技术、中断与异常处理、多任务管理、系统调用、调试原理等多种计算机底层知识。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
努力探索新时期中美正确相处之道(大使随笔)

努力探索新时期中美正确相处之道(大使随笔)

人民网
2026-05-14 06:50:46
日媒吐槽世乒赛:有些队小组赛故意输球 世界第1的中国队就输了2场

日媒吐槽世乒赛:有些队小组赛故意输球 世界第1的中国队就输了2场

风过乡
2026-05-14 12:19:29
母亲和初恋搭伙,对方月入两万全上交,床下东西让我连夜带她回家

母亲和初恋搭伙,对方月入两万全上交,床下东西让我连夜带她回家

晓艾故事汇
2026-05-14 17:36:33
马斯克站C位,黄仁勋皮衣换西装!17位大佬同框暴露“霸总相”

马斯克站C位,黄仁勋皮衣换西装!17位大佬同框暴露“霸总相”

商务范
2026-05-14 15:12:10
转发周知!15日起售,60周岁及以上老年旅客可享淡季火车票优惠

转发周知!15日起售,60周岁及以上老年旅客可享淡季火车票优惠

每日经济新闻
2026-05-13 18:56:46
云南电工挫败黑社会团伙,1人对抗120名混混,造成对方9死48伤

云南电工挫败黑社会团伙,1人对抗120名混混,造成对方9死48伤

莫地方
2026-05-15 01:30:04
阿姨这身打扮也是够时髦了

阿姨这身打扮也是够时髦了

牛弹琴123456
2026-05-13 17:10:28
广电总局官宣,机顶盒再见!

广电总局官宣,机顶盒再见!

果粉俱乐部
2026-05-14 13:55:05
特朗普走下车一瞬间,一只喜鹊忽然从天而降,稳稳的落在了旁边

特朗普走下车一瞬间,一只喜鹊忽然从天而降,稳稳的落在了旁边

漫川舟船
2026-05-14 16:49:29
不少女网约车司机宣布退出女性友好计划,直言不想接女乘客

不少女网约车司机宣布退出女性友好计划,直言不想接女乘客

映射生活的身影
2026-05-12 20:56:00
离谱!婚礼司仪报价800元被砍到500元 新娘还要求随礼600元:忙活一场倒贴100元

离谱!婚礼司仪报价800元被砍到500元 新娘还要求随礼600元:忙活一场倒贴100元

闪电新闻
2026-05-14 16:23:35
卖不动了,日系车集体退守中国

卖不动了,日系车集体退守中国

21世纪经济报道
2026-05-13 23:28:25
爽快!中美会晤提出的第一个要求,中方开场白定调,太高明了

爽快!中美会晤提出的第一个要求,中方开场白定调,太高明了

爱看剧的阿峰
2026-05-14 18:59:00
“10周的工作量,AI只用4天!”Anthropic发布会全程实录:你引以为傲的复杂工程,在模型眼里只是个玩具

“10周的工作量,AI只用4天!”Anthropic发布会全程实录:你引以为傲的复杂工程,在模型眼里只是个玩具

AI科技大本营
2026-05-12 20:40:18
黄仁勋被问英伟达是否会向华为出售芯片:这是个多么奇怪的问题啊

黄仁勋被问英伟达是否会向华为出售芯片:这是个多么奇怪的问题啊

泡泡网
2026-05-14 17:50:15
4-3创造奇迹,0-4横扫出局!NBA最大的伪强队,四巨头真该散伙了

4-3创造奇迹,0-4横扫出局!NBA最大的伪强队,四巨头真该散伙了

老侃侃球
2026-05-14 16:28:08
曝知名网红董赤赤与公司闹翻!账户欠50多万,另起炉灶患严重抑郁

曝知名网红董赤赤与公司闹翻!账户欠50多万,另起炉灶患严重抑郁

裕丰娱间说
2026-05-14 13:35:10
向央视要价41亿!FIFA秘书长访华首要目的:促成谈判 赚中国人钱

向央视要价41亿!FIFA秘书长访华首要目的:促成谈判 赚中国人钱

风过乡
2026-05-14 21:35:53
四个维度分析:快船交易哈登换加兰+次轮签谁赚谁亏?加兰成赢家

四个维度分析:快船交易哈登换加兰+次轮签谁赚谁亏?加兰成赢家

你的篮球频道
2026-05-14 11:39:10
“你就是小偷”,9岁男孩骑走同小区女孩自行车后放回,被女孩家人在业主群辱骂多天,法院判女孩方赔2000元

“你就是小偷”,9岁男孩骑走同小区女孩自行车后放回,被女孩家人在业主群辱骂多天,法院判女孩方赔2000元

扬子晚报
2026-05-14 20:57:01
2026-05-15 04:12:49
CSDN incentive-icons
CSDN
成就一亿技术人
26541文章数 242285关注度
往期回顾 全部

科技要闻

马斯克说会谈很顺利 黄仁勋点赞 库克比耶

头条要闻

马斯克幼子装扮“火”了 衣服包包都是中国造

头条要闻

马斯克幼子装扮“火”了 衣服包包都是中国造

体育要闻

争议抽象天王山,和季后赛最稳定中锋

娱乐要闻

何九华官宣当爸!全程不提孩子妈

财经要闻

李强会见美国工商界代表

汽车要闻

双零重力座椅/AI智能体/调光天幕 启境GT7内饰发布

态度原创

艺术
数码
房产
手机
公开课

艺术要闻

帕特里克镜头下的戴安娜:光影与情感的极致呈现

数码要闻

与“AMD+AMG”赛道相见,英特尔、迈凯伦F1车队达成战略合作

房产要闻

海南楼市新政要出!拟调公积金贷款额度,最高可贷168万!

手机要闻

荣耀600系列国行版终来到,跟海外版完全两个样!

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版