0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

45个寄存器、CPU核心技术大揭秘(下)

jf_78858299 来源:编程技术宇宙 作者:轩辕之风O 2023-04-03 14:36 次阅读

调试寄存器

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

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

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

对于一些解释执行(PHP、PythonJavaScript)或虚拟机执行(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寄存器 ,中文直译是模型特定寄存器,意思是这些寄存器不像上面列出的寄存器是固定的,这些寄存器可能随着不同的版本有所变化。这些寄存器主要用来支持一些新的功能。

随着x86CPU不断更新换代,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

总结

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

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

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5308

    浏览量

    119977
  • cpu
    cpu
    +关注

    关注

    68

    文章

    10824

    浏览量

    211088
  • X64
    X64
    +关注

    关注

    0

    文章

    5

    浏览量

    7831
  • X86构架
    +关注

    关注

    0

    文章

    6

    浏览量

    6520
收藏 人收藏

    评论

    相关推荐

    解析CPU中的寄存器

    8位寄存器在16位寄存器中,而16位寄存器在32位寄存器中。
    发表于 09-19 10:10 3948次阅读

    CPU核心技术

    CPU核心技术           核心(Die)又称为内核,是CPU最重要的组
    发表于 12-18 09:54 1434次阅读

    移位寄存器怎么用_如何使用移位寄存器_移位寄存器的用途

    移位寄存器是一具有移位功能的寄存器,是指寄存器中所存的代码能够在移位脉冲的作用依次左移或右移。本文主要介绍了移位
    发表于 12-22 15:49 2w次阅读

    寄存器变量

    C语言中使用关键字register来声明局部变量为寄存器变量。寄存器变量的值会被存放在CPU寄存器中,每当需要使用它们时,CPU就可以直接
    发表于 06-03 10:13 2339次阅读

    通过了解寄存器的功能与作用去揭秘CPU核心技术

    这篇文章就以市场应用最为广泛的x86-x64架构为目标,通过学习了解它内部的100寄存器功能作用,来串联阐述CPU底层工作原理。
    的头像 发表于 04-27 14:32 4868次阅读
    通过了解<b class='flag-5'>寄存器</b>的功能与作用去<b class='flag-5'>揭秘</b><b class='flag-5'>CPU</b><b class='flag-5'>核心技术</b>

    CS,IP和PC寄存器

    CS寄存器和IP寄存器:首先强调一,这两寄存器非常非常重要,CS的全拼为“Code segment”,即代码段
    发表于 12-17 18:31 2次下载
    CS,IP和PC<b class='flag-5'>寄存器</b>

    如何在VHDL中实现一简单的寄存器

    寄存器是设备中用于存储数据的常见电子元件。这些是最小的数据保存元素,用于存储 CPU 正在处理的操作数或指令。有不同类型的寄存器,即指令寄存器、程序
    发表于 07-29 16:48 4544次阅读
    如何在VHDL中实现一<b class='flag-5'>个</b>简单的<b class='flag-5'>寄存器</b>

    如何使用ALU,RAM,寄存器打造一CPU 1

    CPU简介 **「计算机的心脏是中央处理单元,简称“CPU”」** 。这篇文章就利用前几篇文章中提到过的ALU,RAM,寄存器组件做一CPU
    的头像 发表于 01-30 15:56 801次阅读

    如何使用ALU,RAM,寄存器打造一CPU 2

    CPU简介 **「计算机的心脏是中央处理单元,简称“CPU”」** 。这篇文章就利用前几篇文章中提到过的ALU,RAM,寄存器组件做一CPU
    的头像 发表于 01-30 15:56 746次阅读
    如何使用ALU,RAM,<b class='flag-5'>寄存器</b>打造一<b class='flag-5'>个</b><b class='flag-5'>CPU</b> 2

    如何使用ALU,RAM,寄存器打造一CPU 3

    在指令表中我们看到ADD指令的后四位 **「寄存器 OR RAM地址一列中,列出来的不是之前的RAM地址而是两位的寄存器ID」** 。两位可以表示四数字,正好对应ABCD四
    的头像 发表于 01-30 16:01 1100次阅读
    如何使用ALU,RAM,<b class='flag-5'>寄存器</b>打造一<b class='flag-5'>个</b><b class='flag-5'>CPU</b> 3

    cpu寄存器和存储的区别

    cpu寄存器和存储的区别 寄存器存在于CPU中,速度很快,数目有限;存储是内存,速度稍慢,但
    发表于 03-21 15:12 1360次阅读

    45寄存器CPU核心技术揭秘(上)

    寄存器这个太多太复杂,不适合写故事,拖了很久,总算是写完了,这篇文章就来详细聊聊**x86/x64架构**的CPU中那些纷繁复杂的寄存器们。
    的头像 发表于 04-03 14:35 1713次阅读
    <b class='flag-5'>45</b><b class='flag-5'>个</b><b class='flag-5'>寄存器</b>、<b class='flag-5'>CPU</b><b class='flag-5'>核心技术</b>大<b class='flag-5'>揭秘</b>(上)

    CPU的6主要寄存器

    CPU寄存器是中央处理内的组成部分,是有限存贮容量的高速存贮部件。寄存器CPU内部的元件,包括通用
    的头像 发表于 02-03 15:15 3857次阅读

    CPU寄存器的用途

    在计算机体系结构中,中央处理单元(CPU)无疑是整个系统的核心CPU负责执行指令、处理数据、控制计算机系统的运行等关键任务。而在这个过程中,寄存器扮演着至关重要的角色。本文将详细探讨
    的头像 发表于 05-30 17:09 1222次阅读

    寄存器分为基本寄存器和什么两种

    寄存器是计算机中用于存储数据的高速存储单元,它们是CPU内部的重要组成部分。寄存器可以分为基本寄存器和扩展寄存器两种类型。 一、基本
    的头像 发表于 07-12 10:31 1095次阅读