寄存器¶
寄存器分为:通用寄存器、段寄存器、标志寄存器
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 33. 此指令的调试陷阱 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 中的描述符只能被所述的任务/进程访问。