Skip to content

Commit 52188d2

Browse files
committed
Update CS253 Architectures II.md
1 parent 03032ba commit 52188d2

File tree

1 file changed

+96
-20
lines changed

1 file changed

+96
-20
lines changed

backup/CS253 Architectures II.md

Lines changed: 96 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
>
4040
> 8086 CPU的指令周期通常占用4个时钟周期,因此1GHz的处理器每秒约可执行2.5亿条指令。
4141
42-
### ALU: 算术逻辑单元
42+
#### ALU: 算术逻辑单元
4343

4444
8086的ALU支持以下基本操作:
4545
- **算术运算**
@@ -389,14 +389,61 @@ das ; 调整AL为88h (88的压缩BCD格式)
389389
| `CLI` | IF 置零, 关闭中断 |
390390
| `STI` | IF 设一, 打开中断 |
391391

392+
### 比较指令
393+
394+
`CMP` 命令(Compare,比较)是 8086 汇编语言中的一个非常重要的指令。它用于 **比较两个操作数的大小关系**,但 **不会修改任何操作数的值**`CMP` 命令的 **“结果”** 不是直接返回一个数值,而是 **设置 CPU 的标志寄存器 (Flags Register) 中的某些标志位**。 这些标志位反映了比较的结果,然后可以被后续的条件跳转指令(如 `JE`, `JNE`, `JL`, `JG` 等)使用,以实现程序的分支控制。
395+
396+
**`CMP` 指令的基本格式:**
397+
398+
```assembly
399+
cmp destination, source
400+
```
401+
402+
**`CMP` 指令的操作:**
403+
404+
`CMP destination, source` 指令 **在内部执行的操作是 `destination - source` (目的操作数减去源操作数)****但是,减法的结果不会被存储到任何寄存器或内存位置,而是直接被丢弃。** `CMP` 指令的 **唯一作用** 就是根据这次减法运算的结果 **设置标志寄存器中的标志位**
405+
406+
**`CMP` 指令影响的标志位 (Flags):**
407+
408+
`CMP` 指令主要影响以下几个标志位:
409+
410+
1. **零标志位 (Zero Flag, ZF)**:
411+
* **ZF = 1**: 如果 `destination - source = 0`,即 **`destination` 等于 `source`**,则 ZF 被设置为 1。
412+
* **ZF = 0**: 如果 `destination - source ≠ 0`,即 **`destination` 不等于 `source`**,则 ZF 被设置为 0。
413+
414+
2. **符号标志位 (Sign Flag, SF)**:
415+
* **SF = 1**: 如果 `destination - source` 的结果为 **负数** (结果的最高位为 1,在有符号数表示中),则 SF 被设置为 1。 这通常意味着在 **有符号数比较** 中,`destination` 小于 `source`
416+
* **SF = 0**: 如果 `destination - source` 的结果为 **非负数** (结果的最高位为 0),则 SF 被设置为 0。 这通常意味着在 **有符号数比较** 中,`destination` 大于等于 `source`
417+
418+
3. **进位标志位 (Carry Flag, CF)**:
419+
* **CF = 1**: 如果在 **无符号数减法** 中,发生了 **借位** (borrow),则 CF 被设置为 1。 这通常意味着在 **无符号数比较** 中,`destination` 小于 `source`
420+
* **CF = 0**: 如果在 **无符号数减法** 中,没有发生借位,则 CF 被设置为 0。 这通常意味着在 **无符号数比较** 中,`destination` 大于等于 `source`
421+
422+
4. **溢出标志位 (Overflow Flag, OF)**:
423+
* **OF = 1**: 如果在 **有符号数减法** 中,发生了 **溢出** (结果超出了有符号数的表示范围),则 OF 被设置为 1。 溢出标志用于判断 **有符号数运算结果是否溢出**。 在比较有符号数大小时,OF 需要和 SF 一起考虑。
424+
* **OF = 0**: 如果在 **有符号数减法** 中,没有发生溢出,则 OF 被设置为 0。
425+
426+
**常用的条件跳转指令和 `CMP` 结果的关系:**
427+
428+
| 条件跳转指令 | 含义 (通常用于) | 检查的标志位 |
429+
| ----------------------- | ------------------------------------------------------------ | ----------------- |
430+
| `JE``JZ` | 等于 (Equal) 或 结果为零 (Zero) | ZF = 1 |
431+
| `JNE``JNZ` | 不等于 (Not Equal) 或 结果非零 (Not Zero) | ZF = 0 |
432+
| `JG``JNLE` | 大于 (Greater) (有符号数) 或 不小于等于 (Not Less or Equal) | ZF = 0 且 SF = OF |
433+
| `JGE``JNL` | 大于等于 (Greater or Equal) (有符号数) 或 不小于 (Not Less) | SF = OF |
434+
| `JL``JNGE` | 小于 (Less) (有符号数) 或 不大于等于 (Not Greater or Equal) | SF ≠ OF |
435+
| `JLE``JNG` | 小于等于 (Less or Equal) (有符号数) 或 不大于 (Not Greater) | ZF = 1 或 SF ≠ OF |
436+
| `JA``JNBE` | 大于 (Above) (无符号数) 或 不小于等于 (Not Below or Equal) | CF = 0 且 ZF = 0 |
437+
| `JAE``JNB``JNC` | 大于等于 (Above or Equal) (无符号数) 或 不小于 (Not Below) 或 无进位 (No Carry) | CF = 0 |
438+
| `JB``JNAE``JC` | 小于 (Below) (无符号数) 或 不大于等于 (Not Above or Equal) 或 进位 (Carry) | CF = 1 |
439+
| `JBE``JNA` | 小于等于 (Below or Equal) (无符号数) 或 不大于 (Not Above) | CF = 1 或 ZF = 1 |
440+
392441
### 分支控制
393442

394443
条件跳转是短跳转, 操作数是一个字节, 允许向后跳转 -128 或向前跳转 +127
395444

396445
无条件跳跃可以跳得更远, 可以直接地址跳转, 允许 +/-32K 的跳转, 甚至允许跳转到AX寄存器!
397446

398-
#### 常用指令
399-
400447
| 指令 | 含义 | flag | 反指令 | 反含义 | 反 flag |
401448
| ------ | ---------------- | ---------------- | ------ | -------------------- | ---------------- |
402449
| `JA` | Above | `ZF=0 and CF=0` | `JNA` | Not Above | `ZF=1 or CF=1` |
@@ -524,7 +571,7 @@ $\begin{flalign*}
524571

525572
实际上程序只花了15s来运行, 计算出来的时钟频率是1200MHz, 是目标机器的时钟频率(300MHz)的4倍,原因是现代处理器使用 **指令并行** 技术
526573

527-
### 打印数字的方法
574+
### 打印数字
528575

529576
基于栈的实现:
530577

@@ -1253,6 +1300,11 @@ MOSFET 主要由以下几个部分构成:
12531300
>
12541301
> 这里MOSFET讲的很抽象,参考[【硬核科普】带你认识CPU第00期——什么是MOSFET](https://www.bilibili.com/video/BV1nL411x7jH/)
12551302
1303+
### 区分
1304+
1305+
- **N 型 (N-channel) MOSFET:** 载流子是**电子 (Electrons)** - 记住 **N 代表 Negative (负)**,电子带负电,需要 **正栅极电压 (Positive Gate Voltage)** 才能导通。
1306+
- **N 型 (N-channel) MOSFET:** 载流子是**空穴 (Holes)** - 记住 **P 代表 Positive (正)**,空穴可以被认为是带正电的,需要 **负栅极电压 (Negative Gate Voltage)** 才能导通。
1307+
12561308
### 互补金属氧化物半导体 (CMOS)
12571309

12581310
**互补金属氧化物半导体 (Complementary Metal-Oxide-Semiconductor, CMOS)** 电路是现代数字电路中最主流的电路形式。CMOS 电路利用 **PMOS (P 沟道 MOSFET)****NMOS (N 沟道 MOSFET)** 的互补特性,实现低功耗、高性能的逻辑功能。
@@ -1451,7 +1503,7 @@ IN acc, port
14511503
8086 架构支持多种类型的中断,可以根据**触发来源**进行分类:
14521504
14531505
- **硬件中断 (Hardware Interrupt)**:
1454-
- 由**外部硬件设备**通过**处理器的引脚**发出中断请求信号。
1506+
- 由外部硬件设备通过**处理器的引脚**发出中断请求信号。
14551507
- **INTR (Interrupt Request)** 引脚:**可屏蔽中断**,可以通过设置**中断标志位 (IF)** 来**屏蔽**或**使能**。
14561508
- **NMI (Non-Maskable Interrupt)** 引脚:**非可屏蔽中断**,**优先级高于 INTR**,通常用于处理**更紧急的硬件错误**,如电源故障或内存奇偶校验错误。
14571509
- **异常中断 (Exception Interrupt)**:
@@ -1494,24 +1546,47 @@ IN acc, port
14941546
14951547
**中断向量表 (Interrupt Vector Table, IVT)** 是计算机系统中**管理和处理中断** 的核心数据结构。
14961548
1497-
- **作用**:**存储中断服务例程 (ISR) 的入口地址**。当**中断发生**时,**CPU** 会根据**中断号** 在 **中断向量表** 中**查找** 相应的 **入口地址**,然后 **跳转到该地址** 执行 **中断处理程序**。
1498-
- **存储位置**:**中断向量表** 通常位于 **RAM (随机访问存储器)** 的 **起始地址** 区域,即 **前 1024 字节** (地址范围:**0000:0000 到 0000:03FF**) 。
1549+
- **作用**:**存储中断服务例程 (ISR) 的入口地址**。当**中断发生**时,CPU会根据**中断号** 在 **中断向量表** 中查找相应的入口地址,然后**跳转到该地址执行中断处理程序**。
1550+
- **存储位置**:**中断向量表** 通常位于RAM (随机访问存储器的起始地址区域,即 **前 1024 字节** (地址范围:**0000:0000 到 0000:03FF**) 。
14991551
- **条目结构**:**每个中断向量** 在中断向量表中占用 **4 个字节**。
15001552
- **前 2 个字节**:存储 **指令指针 (IP, Instruction Pointer)**,即 **ISR 代码段内的偏移地址**。
15011553
- **后 2 个字节**:存储 **代码段选择器 (CS, Code Segment)**,即 **ISR 代码所在的段地址**。
1502-
- **地址计算**:对于给定的**中断号 `n`**,其在中断向量表中的起始地址可以通过以下公式计算:
1554+
- **地址计算**:对于给定的中断号 `n`,其在中断向量表中的起始地址可以通过以下公式计算:
15031555
15041556
`中断向量地址 = 中断号 * 4`
15051557
1506-
例如,假设 **中断号为 `0x21` (十进制 33)**:
1558+
例如,假设 **中断号为 `0x3`**:
15071559
1508-
- **中断向量表位置**:`0x0000:0084` (`0x21 * 4 = 0x84`)
1509-
- **入口地址解析**:如果 `0x0084` 处存储的值为 `0x1234:0x5678`,则表示 **中断处理程序的入口地址** 为 **代码段 `0x1234`,偏移地址 `0x5678`**。CPU 将跳转到 **物理地址 `0x1234 * 16 + 0x5678`** 处开始执行 ISR 代码。
1560+
- **中断向量表位置**:`0x0C:0x0F`
1561+
- **入口地址解析**:例如 ``0x0C:0x0F`` 处存储的值为 `0x0070:0x06F4`,则表示 **中断处理程序的入口地址** 为 代码段 `0x0070`,偏移地址 `0x06F4`。CPU 将跳转到 **物理地址 `0x0070 << 4 + 0x06F4`** 处开始执行 ISR 代码。
15101562
15111563
**中断向量表结构示意图**
15121564
15131565
![img](https://s2.loli.net/2025/01/20/TXYK9F5cGUJI2a1.jpg)
15141566
1567+
**重写中断向量表的例子**
1568+
1569+
```assembly
1570+
; 保存原INT 8h中断向量
1571+
cli ; 禁用中断
1572+
xor ax, ax
1573+
mov es, ax ; ES=0000h(中断向量表段)
1574+
mov bx, 8*4 ; INT 8h向量地址(8h*4=20h)
1575+
1576+
; 保存原处理程序地址
1577+
mov ax, es:[bx]
1578+
mov old_ip, ax
1579+
mov ax, es:[bx+2]
1580+
mov old_cs, ax
1581+
1582+
; 设置新中断向量
1583+
mov ax, OFFSET isr
1584+
mov es:[bx], ax
1585+
mov ax, cs
1586+
mov es:[bx+2], ax
1587+
sti ; 重新启用中断
1588+
```
1589+
15151590
### 中断控制器 8259A
15161591

15171592
#### 8259A 的功能与连接
@@ -1691,10 +1766,9 @@ EOI_command:
16911766

16921767
**自定义中断服务例程 (ISR)** 是指**程序员** **自己编写****中断处理程序**,用于**替换** 系统默认的 **ISR**,以实现特定的中断处理逻辑。
16931768

1694-
- **应用场景**
1695-
- **硬件驱动程序**:为特定的硬件设备编写 ISR,处理设备发出的中断请求,实现设备的数据传输、控制等功能。
1696-
- **实时系统**:在实时系统中,需要编写定制化的 ISR,以满足系统对中断响应时间、处理逻辑的特定需求。
1697-
- **系统功能扩展**:通过自定义 ISR,可以扩展系统的功能,例如实现**自定义的定时器****热键检测** 等。
1769+
- **硬件驱动程序**:为特定的硬件设备编写 ISR,处理设备发出的中断请求,实现设备的数据传输、控制等功能。
1770+
- **实时系统**:在实时系统中,需要编写定制化的 ISR,以满足系统对中断响应时间、处理逻辑的特定需求。
1771+
- **系统功能扩展**:通过自定义 ISR,可以扩展系统的功能,例如实现**自定义的定时器****热键检测** 等。
16981772

16991773
**自定义定时器 ISR 的示例**
17001774

@@ -1703,6 +1777,8 @@ EOI_command:
17031777
- **自定义 ISR 替换**:程序员可以**编写自己的 ISR 代码****替换** 原有的 **INT 08H** 中断处理程序,从而实现**自定义的定时器功能**
17041778
- **周期性执行**:由于 **INT 08H** 大约每 **50ms** 左右 **自动执行一次**,因此可以利用它来实现**周期性的任务**,例如 **计时器****实时数据采集****周期性系统监控** 等。
17051779

1780+
1781+
17061782
### 直接访问屏幕内存 (VRAM)
17071783

17081784
**直接访问屏幕内存** 是一种**高效的屏幕显示技术**,允许程序**直接** **读写** **视频 RAM (Video RAM, VRAM)**,从而**快速** **控制屏幕显示内容**
@@ -2918,29 +2994,29 @@ call Print
29182994

29192995
#### 使用三态缓冲器
29202996

2921-
三态设备用另一根控制线来断开设备与总线的连接。当断开连接的时候,它的输入阻抗变得非常大,这样就能避免总线争用的情况了。
2997+
三态设备用另一根控制线来断开设备与总线的连接。当断开连接的时候,它的输入阻抗 (High-impedance) 变得非常大,这样就能避免总线争用的情况了。
29222998

29232999
![img](https://s2.loli.net/2025/02/12/AgRbmW2oTGNVzai.png)
29243000

2925-
### 仲裁
3001+
### 仲裁 (Arbitration)
29263002

29273003
不同设备可能希望同时使用总线,这个时候需要总线仲裁用于避免总线上的冲突或竞争。
29283004

2929-
#### 级联
3005+
#### 级联 (Cascading)
29303006

29313007
当设备想要使用总线时,它会拉高 Request 信号。 如果 Busy 信号为高电平,表示总线正忙,控制器将忽略新的 Request 信号。 反之,如果 Busy 信号为低电平,控制器则发送 Grant 信号给该设备,允许其使用总线。 收到 Grant 信号后,设备会立即拉高 Busy 信号,并将数据放到总线上传输。
29323008

29333009
![img](https://s2.loli.net/2025/02/12/lb1pjHLfEuRwS9i.png)
29343010

2935-
#### 轮询
3011+
#### 轮询 (Polling)
29363012

29373013
当设备想要使用总线时,它会拉高 Request 信号。 一旦收到请求,控制单元就开始挨个查看轮询线,看看哪个设备想要用总线。 找到了想用的,就把 Busy 信号拉高,然后把数据线连通,让这个设备用。
29383014

29393015
通俗一点来就像点名一样:设备想用总线先举手 (发出请求)。然后控制器一个一个地问:“1 号,你要用总线吗? 2 号,你要用总线吗? 3 号,你要用总线吗?...”,一旦点到某个举手的设备,控制单元就说:“好,给你用!” 然后把 Busy 信号设为“忙碌”,并把数据线连通,让这个设备传输数据。“点名”的顺序决定了谁先被服务,也就是谁的优先级最高。 如果 1 号总是先被点到,那么 1 号的优先级就最高。
29403016

29413017
![img](https://s2.loli.net/2025/02/12/18kxLOaZqwTBgJr.png)
29423018

2943-
#### 独立请求
3019+
#### 独立请求 (Independent Request)
29443020

29453021
每个外设单元都有单独的请求线 (Request) 和授权线 (Grant)。优先级由总线控制单元来决定。不过缺点就是比较复杂,因为每个单元都需要单独的请求线和授权线。
29463022

0 commit comments

Comments
 (0)