寄存器

寄存器分为:通用寄存器、段寄存器、标志寄存器

8086寄存器

8086 寄存器是 16 位,其中通用寄存器又可以分为高8位和低8位单独使用。

15 0 +——————————————————————————-+ | AX | 累加器 +——————————————————————————-+ | BX | 基址寄存器,存内存访问的基址,与 SI 和 DI 结合使用 +——————————————————————————-+ | CX | 计数器 +——————————————————————————-+ | DX | 数据寄存器 +——————————————————————————-+

+——————————————————————————-+ | SP | 栈顶指针寄存器 +——————————————————————————-+ | BP | 栈基址寄存器 +——————————————————————————-+ | SI | 源索引寄存器 +——————————————————————————-+ | DI | 目标索引寄存器 +——————————————————————————-+

+——————————————————————————-+ | CS | 代码段寄存器 +——————————————————————————-+ | DS | 数据段寄存器 +——————————————————————————-+ | SS | 堆栈段寄存器 +——————————————————————————-+ | ES | 附加段寄存器 +——————————————————————————-+

+——————————————————————————-+ | IP | 指令指针寄存器 +——————————————————————————-+

+——————————————————————————-+ | | | | | OF | DF | IF | TF | SF | ZF | | AF | | PF | | CF | 标志寄存器 +——————————————————————————-+

标志寄存器各个位: |标志位|说明| |——|—-| |OF|用于处理有符号数的溢出。当有符号数运算结果超出可表示范围,OF置为1;否则置为0| |DF|控制字符串操作的方向,当DF为1字符串操作从高地址向低地址进行;反之亦反| |IF|用于控制中断的开启和屏蔽。当IF设置为1时,标志中断允许;否则中断不允许| |TF|在调试模式下使用,用于单步执行程序并进行调试。TF置1,处理器进入单步模式,在单步模式下,每执行一条指令后,处理器会触发一个软中断(调试异常),以便调试器能捕获并检查执行的指令和寄存器状态| |SF|用于指示操作结果运算的符号。当结果为负数时候,SF置为1;否则置为0| |ZF|用于指示操作结果是否为0。操作结果为0则置为1,否则为0| |AF|用于处理BCD(二进制编码的十进制)运算。当一个低位数的十六进制数发生从低位到高位的进位时候,AF被设置为1;否则,它被清0| |PF|用于指示结果中1的个数的奇偶性。结果有偶数个1则置为1;否则置为0| |CF|处理无符号数的进位和借位操作。当发生进位或借位时候,CF被设置为1;否则被清0|

通用寄存器

  • AX: 累加器,常用于存放函数返回值或进行算术运算

  • BX: 基址寄存器,常用语存放执行或数据对象的地址

  • CX: 计数器,常用于循环和字符串操作

  • DX: 数据寄存器,用于存放运算过程中的数据

  • SI: 源变址寄存器,用于存放源数据的指针

  • DI: 目的变址寄存器,用于存放目标数据的指针

  • SP: 堆栈指针寄存器,用于指向堆栈的栈顶

  • BP: 基址指针寄存器,用于指向堆栈的栈底

段寄存器

  • CS: 代码段寄存器

  • DS: 数据段寄存器

  • ES: 附加段寄存器

  • SS: 栈段寄存器

标志寄存器

  • EFLAGS: 标志寄存器

80386 寄存器

通用寄存器

  • EAX: 累加器,常用于存放函数返回值或进行算术运算

  • EBX: 基址寄存器,常用语存放执行或数据对象的地址

  • ECX: 计数器,常用于循环和字符串操作

  • EDX: 数据寄存器,用于存放运算过程中的数据

  • ESI: 源变址寄存器,用于存放源数据的指针

  • EDI: 目的变址寄存器,用于存放目标数据的指针

  • ESP: 堆栈指针寄存器,用于指向堆栈的栈顶

  • EBP: 基址指针寄存器,用于指向堆栈的栈底

段寄存器

  • CS: 代码段寄存器,指向当前执行的代码段

  • DS: 数据段寄存器,指向当前数据段

  • ES: 附加段寄存器,用于附加数据段的指针

  • SS: 栈段寄存器,指向当前堆栈段

  • FS: 附加段寄存器,用于附加数据段的指针

  • GS: 附加段寄存器,用于附加数据段的指针

注意:都是16位

指令指针寄存器

  • EIP:指向下一条将执行的指令地址

标志寄存器

  • EFLAGS:包含了多个标志位,用于记录和控制程序的状态和条件

31                              21   20    19    18   17   16   15  14  12-13    11   10    9   8    7    6    5    4    3    2    1   0
+-----------------------------+----+-----+-----+----+----+----+---+----+-------+----+----+----+----+----+----+----+----+----+----+---+----+
|            0 0              | ID | VIP | VIF | AC | VM | RF | 0 | NT | IO/PL | OF | DF | IF | TF | SF | ZF |  0 | AF |  0 | PF | 1 | CF |
+-----------------------------+----+-----+-----+----+----+----+---+----+-------+----+----+----+----+----+----+----+----+----+----+---+----+

控制寄存器

  • CR0(32位):控制处理器的运行模式和系统特性

  • CR2(32位):存储引起页故障的线性地址

  • CR3(32位):页目录表的基地址

  • CR4(32位):控制处理器的系统特性

    31                                                                   12 11               0
    +----------------------------------------------------------------------+-----------------+
CR3 |    页目录地址(12-31)                                                 | 保留(0-11)      |
    +----------------------------------------------------------------------+-----------------+


    31                                                                                       0
    +----------------------------------------------------------------------------------------+
CR2 |           页面故障地址                                                                 |
    +----------------------------------------------------------------------------------------+


    31                                                                                       0
    +----------------------------------------------------------------------------------------+
CR1 |           未使用                                                                       |
    +----------------------------------------------------------------------------------------+


      31   30   29                         18         16         5    4    3    2    1     0
    +----+----+----+---------------------+----+-   -+----+     +----+----+----+----+----+----+
CR0 | PG | CD | NW |    ...              | AM | .. |  WP | ... | NE | ET | TS | EM | MP | PE |
    +----+----+----+---------------------+----+-   -+-+--+     +----+----+----+----+----+----+

CR0各个位的含义 |位|含义| |–|—-| |PE|当PE位被设置为1时候,处理器运行在保护模式下,启用内存分段、特权级别和保护机制;当PE设置为0时候,处理器运行在实模式下| |MP|80386中没有用到,后续处理器中用于支持协处理器的监视| |EM|当EM位设置为1时候,处理器运行在虚拟8086模式下,以支持运行旧的16位实模式软件;当EM设置为0时候处理器运行在保护模式下| |TS|TS被设置为1时候,表示处理器经历了任务切换,任务切换后需要进行指令序列的重新加载| |ET|这个位在80386处理器中没有使用,后续的处理器中指示处理器的扩展类型| |NE|当NE被设置为1时候,处理器在浮点数运算时候会产生异常;当NE被设置为0时候,处理器在浮点数运算出错时候会产生错误码| |WP|当WP设置位1时候,禁止对只读或只执行页进行写操作。当WP位被设置为0时候允许对只读或只执行页进行写操作| |AM|当AM被设置为1时候,处理器对内存访问进行对齐检查,如果发现未对齐的内存访问,会产生异常。当AM被设置位0时候,不进行对齐检查| |NW|当NW位被设置为1时候,禁用写透功能,即禁止将数据写入高速缓存。当WM被设置为0时候,启用写透功能| |CD|将CD值设为1时候,禁用数据和指令高速缓存。当CD设置为0时候启用高速缓存| |PG|当PG设置为1时候,启用分页机制,允许使用分页机制进行虚拟内存管理。当PG被设置为0时候,禁用分页机制|

IDT与GDT

IDT 和 GDT 是从 80286 80386 开始引入的(后续确定)。 IDT 是一个存储中断向量和处理程序地址的表格;它包含了处理器能够响应的所有中断和异常的信息。 GDT 是一个存储段描述符的表格,它用于定义和管理内存分段;其中每个段描述符描述了一个内存段的属性和位置,GDT中的段描述符包含了段基址、段限长、访问权限等信息。通过GDT,处理器可以实现内存分段和保护基址,提供了对内存的灵活控制和访问。

IDT 和 GDT 是为了支持保护模式和内存分段模式加入的一种机制

注意:8086 中只有类似 IDT 的概念,因为 8086 类似实模式,因此没有 GDT 概念。

注意:8086 中没有中断描述符表,只有中断向量表

8086 中断向量表

中断向量表位于内存的固定位置,其起始位置为 0x0000:0x0000,结束位置为 0x0000:0x03FF,每个中断在表中占用4个字节。中断向量表的结构如下: Offset 00 Offset 02 … Offset 1C

偏移 大小 描述
0 2 bytes
2 2 bytes
... ... ...

每个中断的入口地址由两部分组成:段内偏移地址和段地址。通过这两个值,可以确定中断服务程序的实际地址。

中断向量表的大小为 32*4 字节,即总共 128 字节。其中,每个中断占用 4 字节,共有 32 个中断(从0到31),因此中断向量表的大小为128字节。

要访问中断向量表中的第 n 号中断向量,可以使用: 偏移地址:n * 4

注意:IVT中前32个中断向量通常是由 Intel 保留(x86默认最大256中断),用于处理各种系统级别中断。从第 32 号中断开始可以由用户自定义和使用。

需要注意的是,在8086处理器中,中断向量表是固定的,无法动态修改。每个中断有一个预定义的入口地址,不能灵活配置和管理中断。

IDT

IDT 数量不超过 256 (因为x86上有256个中断,0 - 31,也就是前32个中断处理系统级别的中断)

IDT 可以在物理内存的任何位置,处理器通过 IDTR 获取IDT的位置。

IDT 操作指令 LIDT 和 SIDT,分别是加载IDT寄存器和存储IDT寄存器,其中 LIDT 必须在 CPL 为 0 时候才能执行(CPL=0表示当前代码特权级别最高,CLP可以取值0、1、2、3),用于把内存操作数中的线性基值和限制值加载到IDT寄存器;SIDT将存储在IDTR中的基值复制到一个内存位置,该指令可以在任何特权级别上执行。

LIDT 和 SIDT 两个操作指令都有一个显示的操作数:内存中6字节的地址。

中断和异常的优先级

优先级 中断或异常的类型
最高 1. 除调试故障外的错误
2. 捕获指令 INTO, INT n, INT 3
3. 此指令的调试陷阱
4. 下条指令调试错误
5. NMI中断(硬件中断,比如硬件故障、系统崩溃或其它紧急情况)
最低 INTR 中断

IDT寄存器和表

6字节中,4字节用于存储 IDT 的起始地址(IDT BASE),2 字节用于存储IDT长度,或者说是IDT描述子的数量(IDT LIMIT)

                  15                0
                  +-----------------+
                  |    IDT LIMIT    |
+-----------------+-----------------+
|             IDT BASE              |
+-----------------|-----------------+
31               15                 0

IDT 描述符

IDT 可以包含三种描述符中的任意一种:

  • Task gates (任务门)

  • Interrupt gates (中断门)

  • Trap gates (陷阱门)

31              23                  15                    7                    0
+---------------+-------------------+---+-----+-----------+--------------------+
|           (NOT USED)              | P | DPL | 0 0 1 0 1 |     (NOT USED)     | 4
+-----------------------------------+---+-----+-----------+--------------------+
|           SELECTOR                |               (NOT USED)                 | 0
+-----------------------------------+---------------------+--------------------+
                                80386 TASK GATE


31              23                  15                    7                    0
+--------------+--------------------+---+-----+-----------+-------+------------+
|          OFFSET 31 .. 16          | P | DPL | 0 1 1 1 0 | 0 0 0 | (NOT USED) | 4
+--------------+--------------------+---+-----+-----------+-------+------------+
|           SELECTOR                |             OFFSET 15 .. 0               | 0
+-----------------------------------+---------------------+--------------------+
                                80386 INTERRUPT GATE


31             23                   15                    7                    0
+--------------+--------------------+---+-----+-----------+-------+------------+
|          OFFSET 31 .. 16          | P | DPL | 0 1 1 1 1 | 0 0 0 | (NOT USED) | 4
+-----------------------------------+---+-----+-----------+-------+------------+
|           SELECTOR                |             OFFSET 15 .. 0               | 0
+-----------------------------------+---+-----+-----------+-------+------------+
                                80386 TRAP GATE

当中断和异常响应时候,处理器使用中断或异常标识符来索引到 IDT 中的描述符(IDT中有三种描述符)。当处理器索引到 中断门 或者 任务门 的时候,它以类似调用门的调用方式调用处理程序;如果处理器找到一个任务门,它会以类似对任务门的调用方式来进行任务切换。

GDT

80386 GDT 寄存器 GDTR 是 48 位,每个描述符占8个字节(64位),其中包括段基址、段限制、段的特权信息,最多提供 65536 个描述符的访问。

GDT 寄存器的高16位存储GDT的基址的高16位,低32位存储基址的低32位。

GDT(Global Descriptor Tables),即:全局描述符表,既然有GDT那相应的也有LDT(局部描述符表)。

描述符表就是一个包含描述符的 8 字节内存数组,描述符表在长度上是可变的,最多可以包含8192(2^13)个描述符。但是处理器不使用描述符表的第一个条目

处理器通过 GDTR 和 LDTR 寄存器在内存中定位 GDT 和 LDT。这两个寄存器在线性地址空间中存储表的基址和段限制,对应的操作指令分别是:LGDT、SGDT 和 LLDT、SLDT

GDT 和 LDT

  • GDT 是一个全局的描述符表,用于存储系统中所有的段描述符

  • GDT 通常由操作系统初始化并管理,它定义了系统中所有的全局段,如代码段、数据段、堆栈等。

  • GDT 中的描述符可以被整个系统的所有任务/进程共享和访问

  • LDT 是每个任务/进程的私有描述符表,用于存储任务/进程特定的段描述符

  • 每个任务/进程都可以有自己独立的LDT,每个LDT由一个LDT描述符来引用,该描述符存储在GDT中。

  • LDT 通常由操作系统在任务/进程创建时候分配和初始化,它可以定义任务/进程特定的段,如局部数据段、局部堆段等

  • LDT 中的描述符只能被所述的任务/进程访问。