type
status
date
slug
summary
tags
category
icon
password
Hide-in-Web
Hide-in-Web
Hide-in-Config
Hide-in-Config
comment
Pin
Pin
Link
🎉欢迎大家来到我的博客!!🎉
此页面是关于周老师微机原理课程的笔记,周老师的讲课真的挺不错的,只不过有些视频的声音不尽人意,加上摄像头老是乱动,截图很困难。
不过办法总比困难多,我花费了很多时间将散乱的截图拼接起来,既方便我自己复习,也方便大家学习和参考。
请大家尽量用电脑来进行查看,会有最好的显示效果。
后面还会二刷课程,对一些笔记内容进行补充( ̄︶ ̄)↗ 希望对大家有帮助!!
网课课程排布

绪论
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- 课程安排
- 智能电子信息系统的设计
- 微型计算机系统的组成
- 早期计算机的组成
- 微处理器
- 存储器
🔗 Relevant Information
📝 Class Notes
课程安排
前四章的内容是关于软件的,主要是汇编语言的学习,前三章是基础知识的介绍,第四章是程序的设计;
第五章到第十章的内容是关于硬件的设计。

由于经过 CPU 处理的数据传输到 DA 转换器后,有些是模拟量数据,有些是串行数据,有些是并行数据,因此需要有微机接口对数据进行转换以匹配具体的器件。
课程学习中应用到的 CPU 器件是 Intel 的 8086 芯片。
微型计算机系统的组成
计算机系统都是由硬件系统和软件系统组成的。
早期计算机的组成

ALU (算术逻辑单元):计算机硬件最基础的功能就是要能够进行运算,而运算既包括加减乘等算数运算,又包括与或非等逻辑运算,因此需要算术逻辑单元。
控制器:而为了能够操控 ALU 进行运算,就必须要有控制器的指挥。
存储器: 有了控制器和 ALU 后,我们需要有进行运算的数据,这些数据一部分存储在存储器中,由控制器进行调用,由 ALU 进行运算,而运算后的数据结果会通过数据线重新传回存储器中进行储存。
输入输出设备(I/O 设备):早期的计算机也常通过外部设备(也由控制器控制)来获取数据进行运算并输出,输出的数据也可存入存储器中。
在上图中,绿色的线称为控制线,传输的是控制信息,红色的线是数据线传输的是数据信息,还有一类信息是地址信息,用于控制器检索存储器中数据的位置(通过地址码)。而传输控制信息、数据信息、地址信息的线统称为总线(用于传输信息的通路),不同的信息需要不同的总线进行传递,传输控制信息的称为控制总线(CB),传输数据信息的称为数据总线(DB),传输地址信息的称为地址总线(AB)。
图中蓝色方框所示的内容即为中央处理器,通常集成在一块芯片中。
微处理器
微处理器(CPU),顾名思义,大小必须是比较小的。
引脚
引脚就是微处理器与外界进行通信的接口,引脚可以是控制总线,传输控制信息,也可以是数据总线,传输数据信息。
复用引脚
如果一个处理器需要有几十个与外界通信的接口,那么引脚数量增加的同时,微处理器的大小必然也会增大,但为了保证微处理器的大小比较小,因此厂家们便引入了复用引脚,即一个引脚可以既可以用于输入数据,也可以输出数据,或是输出地址数据。但必须保证在某个数据传输时不会有其他数据混在一起。
微处理器级总线和系统总线

如果一个引脚是数据和地址复用引脚,那么就需要将引脚连接到某个设备,将数据和地址信息分开,其中数据信息可以是双向的,而地址数据只能是单向输出的,因为地址数据是 CPU 发射出来用于寻找特定的 io 设备或是某个存储器设备的,传输的是地址码。
当然,如果引脚也复用了控制总线,也可以双向传递,有微处理器传输出去的信息称为控制信息,由外部设备反馈回来的信息称之为状态信息。
任何器件都是通过挂接在系统总线上来实现与 CPU 的通信的,系统总线形成电路不仅解决了引脚服用分开的问题,同时也增强了 CPU 带动负载的能力(单个微处理器驱动负载的能力比较弱)。
存储器
任何系统的存储器都是 RAM 和 ROM 两个部分组成的。
RAM 通常储存的是临时性的数据,掉电后数据后丢失,而 ROM 存储的是系统程序的数据,掉电后不会丢失数据。 因此称 RAM 为数据存储器,ROM 为程序存储器。
计算机中的 RAM 和 ROM
我们日常使用的计算机中的 ROM 是紫外线可擦除的 1p ROM,ROM 中存放的是 BIOS (Basic Input output system)程序,计算机通电后先从 BIOS 程序中读取代码,先对 内存(RAM) 进行质检,确认 RAM 中的每个比特位是否都是能写能读的;质检完以后执行 BIOS ,对主板上的 io 接口程序进行初始化;初始化以后,从外部设备磁盘上读取操作系统到内存。
计算机中的数制与码制(第一章)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- 各种进制的数的转换
- 二进制的运算
- 寄存器作用及分类
- 加法和减法
- PSW
- 与或非运算
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
计算机中存储和处理的数据都只能是二进制的数字,因此外界输入的数据最终都要转换成二进制数。
二进制数 ↔ 十进制数
十进制数转换为二进制数可以采用短除法。
二进制数转换为十进制数可以采用位置加权法。
十进制 ↔ 十六进制
按照这个顺序转换 十进制 → 二进制 → 十六进制(四位一组)。
十六进制转换为十进制就将过程逆过来即可。
二进制的运算(寄存器)
二进制的运算涉及到加减乘和除。
寄存器
计算机每次进行运算时都需要将数据输入到 CPU ,而如果每次运算都要从 CPU 外部搬入数据,计算机的速度显然较低,因此,通常在 CPU 内部还会有寄存器的存在,用于临时存放数据,提高计算机的速度。
CPU 内部寄存器数量越多,速度越快,但相应地其体积也会越大。
8 位寄存器的分类

数字和名称的区分
在汇编语言中,有时候数字和名称常常会让编译器混淆,因此需要对这两者进行区分。
具体的区分方式是,数字采用 0~9 开头,如 0BAH,H 表示 16 进制,而名称采用字母开头。
加法和减法运算
主要用到 mov 和 ADD 两个助记符。
mov AL, 97:可以理解为赋值运算符,将 97 这个数赋值给 AL 这个寄存器。在汇编语言中称为数据传输语句。
这里需要注意的是,97 不需要写成 二进制数 的形式,因为在汇编程序中写好的语句会先经过汇编语言转换成二进制数,也就是说 97 会在汇编时先转换成计算机可以读取的形式。


微处理器状态字寄存器

什么是 psw ?


在计算器进行了两数的运算后,寄存器才可以进入状态,具体进入哪一个状态需要通过 PSW,也就是 微处理器状态字寄存器 才可以知道。
与、或、异或、非以及测试运算

- DST 是 Destination 的缩写,表示目标寄存器/存储单元。
- SRC 是 Source 的缩写,表示源寄存器/存储单元。

补码
= ;
=
变补/求负
所谓的变补或是求负,指的就是已知一个数的补码,求其负数的补码的过程。
要实现上面的过程,只需要对该补码再取其补码即可,通过下面的示例可以更理解这一点:

BCD 数
BCD 的含义是 Binary-Coded Decimal,即二进制编码十进制。而实现 BCD 有多种方式,8421 就是其中一种。
如果使用 8421 码编码,在计算机内部存储时,有组合 BCD 的方式和分离BCD 的方式两种进行存储。加法和减法既有组合 BCD 数的运算,也有分离 BCD 数的运算,而乘法和除法只有分离 BCD 数的运算。

在进行 BCD 数的运算时不能忘记调整,调整包括 +6 调整和 -6 调整,调整的助记符是 DAA。

ASCⅡ 码
计算机中的数字都采用二进制表示,字符都采用 ASCⅡ 码表示。ASCⅡ 码 的第一位都是 0,也就是说 ASCⅡ 码 使用 7 位二进制数表示字符。
在本门课中需要掌握的 ASC Ⅱ 码:
可显字符:
数字 ‘0’ ~ ‘9’ (加上单引号表示是一个字符):30H ~ 39H 。
字母 ‘A’ ~ ‘F’ :41H ~ 47H 。
字母 ‘a’ ~ ‘f’ :61H ~ 67H 。
非可显字符:
回车: 0DH
换行: 0AH
空格:20H
如果要将数字字符和字母字符转换为十六进制数字,则数字字符应该减去 30H,字母字符应该减去 37H。
作业
只有本节视频说了作业,后面的视频好像都没说。
作业 1.9、1.10(1 5 7)、1.11(1 2 5)、1.12(1 7)、1.13(2 3)、1.15(3 7)
8086 的结构与功能(第二章)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- 8086 结构
- 外部结构
- 内部结构
- 堆栈
- 微处理器的功能结构
- BIU 部分理解
- EU 部分理解
- 微处理器的寄存器组织
- 存储器地址空间与数据存放格式
- 地址空间
- 数据存放格式(字型、字节型等)
- 存储器分段与物理地址形成
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
8086 结构介绍
微处理器的外部结构
8086 有 40 个引脚,其中 ~ , ~ 共 20 个引脚是专门传输地址信息的,前者既能够给外部存储器提供地址,也可以给 IO 提供地址,而后者只能给外部存储器提供地址。因此,能够给外部存储器分配的内存是 1 MB(),给 IO 分配的内存是 B = 。
8086 CPU 有 16 条数据总线、 20 条地址总线和 16 条控制总线。
I/O 接口是连接 CPU 与 I/O 设备的控制电路,在 I/O 接口中,有一个 I/O 端口寄存器,用于与 CPU 之间的数据交换,计算机也为其分配一个地址(端口地址), CPU 也是依据这个地址与端口打交道的。端口地址具体如何理解可以参照下图:

上图的具体理解:
这张图描述了CPU与I/O设备之间的数据双向传输过程。图中的I/O接口电路(也称为I/O控制器)负责管理CPU和打印机(I/O设备)之间的通信。具体步骤如下:
- 数据输出过程:
- 数据输出端口:CPU通过数据输出端口将数据发送到I/O接口电路。
- 命令端口:CPU通过命令端口发送命令,指示I/O接口电路将数据传送到打印机。
- 打印机接收数据:I/O接口电路将数据从数据输出端口传送到打印机。
- 数据输入过程:
- 状态输入端口:打印机通过状态输入端口向I/O接口电路发送状态信号,表示其当前的工作状态或是否有数据需要传输。
- I/O接口电路处理:I/O接口电路接收到状态信号后,将其传送给CPU。
- CPU接收状态信息:CPU根据状态信息做出相应的处理决定,例如是否继续发送数据或等待打印机完成当前任务。
某些微处理器采用统一的地址空间对存储器和 I/O 端口寻址, 即存储器和 I/O 端口进行统一的地址编码,一个地址要么对应于存储单元,要么对应于端口寄存器,读写控制信号用来区分 CPU 进行读/写操作。在这种方式下,对存储器和 I/O 端口的存取指令是一样的。(统一的地址空间意味着将存储器地址与 I/O 端口地址混合起来,用连续的地址编码来管理,具体是存储器地址还是 I/O 地址需要看地址对应的端口来决定)。如MCS-51。
优点:I/O 驱动程序编写方便,灵活。缺点:浪费了存储器地址空间。
但大多数微处理器则是采用两个独立的地址空间,即存储器地址空间和 I/O 地址空间,这时,某存储单元和 I/O 端口可能对应于相同的地址值。那么如何区分 CPU 是存取存储单元还是 I/O 端口?采用存储器读写信号和 I/O 读写信号来区分。在这种方式下,对存储器和对 I/O 端口读写指令是不同的。如 8086。
优点:节约了存储器地址空间。缺点:指令记忆复杂,I/O 驱动程序设计不灵活。(既需要记忆存储器地址指令、有需要记忆 I/O 地址指令)
寻址:
对于汇编程序有两种常见的寻址方式,一种是直接寻址,一种是间接寻址。
微处理器的内部结构
了解微处理器的工作原理,逐渐掌握汇编语言设计的编程模型。


在控制器中,器件的运行顺序是 程序计数器 → 指令寄存器 → 指令译码器 → 控制逻辑部件 → 程序计数器…
在上面的过程中,控制器件每次只能取一条指令放入寄存器中,指令译码后执行然后再取下一条指令,因此这种方式的效率是十分低的,才有了后面的 8086 CPU 的出现。
堆栈
由先进后出原则组织的一段传输器区域。堆栈的区域是程序员在编程的时候自己定义的。
放入数据的过程为 push(助记符),拿出数据的过程称为 pop(助记符)。对于 8086 而言,堆栈必须按字操作。

如果在堆栈的过程中,指针超出堆栈的空间,那么就会发生栈的溢出。溢出后计算机就会死机。因此在设计堆栈的区域的时候,要根据实际需求来,并且留出 30% 的富余量。
栈顶是活动的,栈底是固定的。
栈底为高地址,栈顶为低地址。
微处理器的功能结构

图中展示了微处理器的功能结构。
BIU 部分的理解
BIU 负责从外部存储器中取指令,并将取回的指令放入队列中。
1. BIU(总线接口单元)的理解
- CS, DS, SS, ES:这些寄存器是段寄存器,分别代表代码段(Code Segment)、数据段(Data Segment)、堆栈段(Stack Segment)和附加段(Extra Segment)。段寄存器存储段地址,用于定义内存中某个特定段的起始地址。
- IP:指令指针寄存器(Instruction Pointer),它保存的是当前指令在代码段中的偏移量,即段内偏移地址。
2. 段地址和段内地址的关系
- 在 8086/8088 处理器中,内存地址由段地址和段内地址(偏移量)共同确定。段地址存储在段寄存器中,而段内地址通常由 IP 或其他寄存器提供。
- 物理地址的计算方式是将段地址左移4位(即乘以16),然后加上段内地址。计算公式如下:
这种方法使得一个段可以表示 64KB 的内存范围。
3. BIU 与地址产生和总线控制的关系
- 地址产生与总线控制:地址产生单元通过读取段寄存器和指令指针(IP)寄存器的值,生成物理地址并与总线控制逻辑合作,负责内存和I/O的读取和写入操作。
- BIU 在生成物理地址后,通过总线接口将这些地址和数据传输到系统总线,然后访问相应的内存或I/O设备。
EU 部分的理解
EU 主要负责从指令队列中获取指令,并对该指令加以执行。

在上述过程中,总线一直处于忙碌状态,也就意味着效率大大的提高。
微处理器的寄存器组织
共有 14 个 16 位的寄存器,通用寄存器有 8 个(数据寄存器 4 个,地址指针寄存器 2 个,变址寄存器 2 个),段寄存器 4 个,控制寄存器 2 个。
通用寄存器
数据寄存器
数据寄存器有 4 个 —— AX(又称为累加器), BX(又称基址寄存器), CX(又称计数寄存器), DX(又称数据寄存器)。
因此在使用目的操作数时尽可能多的使用 AX;在使用段内地址时尽量使用 BX;在使用循环操作时尽量使用 CX;
地址指针和变址寄存器
地址指针寄存器 → BP;
与 BX 基址寄存器不同,由 BP 提供的段内偏移地址默认在堆栈段(SS),而由 BX 提供的段内偏移地址默认在数据段。
如何将 BP 提供的段内偏移地址更改为数据段?
堆栈指针寄存器 → SP;
源变址寄存器 → SI;
默认是 DS 段的。
目的变址寄存器 → DI .
默认是 DS 段的。
那么源变址寄存器和目的变址寄存器的用途是什么呢?
在计算机内部对字符串进行操作时,可以直接从数据层面进行操作,但是为了提高效率,汇编语言中直接开辟了一块专门用于对字符串进行操作的指令。

以 数据搬家 为例,要想利用字符串操作的指令,首先数据必须位于数据段(DS),其次,字符串的偏移地址必须保存在 SI 内;目的串必须定义在附加数据段(ES),字符串的偏移地址必须由 DI 寄存。这就是 SI 和 DI 两个寄存器名字中 “源” 和 “目的” 的由来。
那么名字中的 “变” 体现在什么方面呢?
在计算机执行 MOVSB(按字节移动)指令后,SI 和 DI 的地址会自动的加 1 或减 1,也就是上移或下移,以实现数据的移动。
段寄存器
CS → 代码段寄存器(无需用户初始化,用户无权操作,由操作系统完成)
换句话说, CS 不能作为目的操作数,不能对 CS 进行写操作。
DS → 数据段寄存器(需要用户初始化地址)
ES → 附加数据段寄存器(需要用户初始化地址)
SS → 堆栈段寄存器(需要用户初始化地址)
指令指针寄存器
包括指令指针寄存器(IP)和微处理器状态字寄存器(PSW)。
指令指针寄存器等同于程序计数器(PC),用于保存下一条即将要执行指令的段内偏移地址。
PSW 共有 6 个反映 ALU 结果状态的标志位,状态标志位—— ZF, AF, SF, OF, PF, CF,其中除了 AF 以外其他都是条件分支程序设计当中的条件之一。

PSW 中还有 3 个控制标志位,用于控制 cpu 运行状态,分别是 —— DF(方向控制),IF (中断控制),TF(陷阱标志)。
DF :程序启动时自动清零,当使用 CLD 代码时,DF = 0;当使用 STD 代码时,DF=1。
IF :中断分为程序内部中断和外部中断,当 IF 为 1 时,能够响应 外部中断 的请求,当 IF 为 0 时,只能够响应内部中断的请求,内部中断是无法被屏蔽的。
存储器地址空间与数据存放格式
地址空间
共 20 根地址线
给存储器编址的地址线有 20 根,为 ;
给 I/O 编址的地址线有 16 根,为 ;
在 IBM PC 机中,给 I/O 分配地址的地址线有 10 根,为 ,因为在显示应用中给 I/O 的地址往往用不了 的内存。1 KB 的内存中,前半 k 的部分分配给主板上的 I/O 作地址,后半 k 分配给插件板上的 I/O 作地址。

数据存放格式
字节型、字型、双字型。
字节型数据: 在 DS 段有定义。

伪指令的含义:
在微机原理和汇编语言编程中,伪指令(也称为伪操作或汇编伪指令)是由汇编器(assembler)解释和处理的指令,但这些指令在实际的机器代码中并不存在。换句话说,伪指令并不会被直接翻译成机器指令(即二进制代码),而是指导汇编器如何处理源代码的某些方面。伪指令主要用于程序组织、内存分配、定义常量等操作。
字型数据:

数据对准与未对准的概念:

当字型数据的低位地址为偶地址时,称该地址是对准的,否则是未对准的。对于对准的地址而言,读写数据操作的速度更快,只需要花费一个总线周期的时间。而对于未对准的数据,需要花费两个总线周期的时间。
存储器的分段与物理地址的形成
为什么要进行分段?
在 8086 内部,用于外部存储器寻址的地址线是 20 条,但是用于存储器寻址的寄存器(如 BX BP SI DI等)的大小却都是 16 位的,只能为存储器提供 ,也就是 64 位的地址。为了能将 1 MB 的空间都能够寻址完,需要将存储器分成许许多多的逻辑段进行管理。
如何分段?
段地址的最大空间为 64 KB,每个逻辑段的起始地址必须能够被 16 整除。
存储器的分段:

不同逻辑段之间会相互重叠,段地址的起始地址必须能够被 16 整除,段地址和段内偏移地址都是 16 位的。
在实际应用当中,逻辑段一般是不会发生重叠的,用户编写的程序经过汇编语言汇编后,会依次形成所需要使用的逻辑段,下一个逻辑段会在上一个逻辑段的结束地址后寻找可以被 16 整除的地址。
物理地址(PA)的形成:
由逻辑地址 → 物理地址的过程,就是物理地址的形成。
物理地址 = 段地址 * 16 + 段内偏移地址,段内偏移地址也称段内有效地址(EA),因此,公式也可以写成
PA = 段地址 * 16 + EA 。物理地址是唯一的。
BIU 和 EU 如何相互配合完成指令操作:

以
MOV [BX], AX;
操作为例,首先告诉 BIU 要进行传输器写操作了,取指令的操作暂停,帮 EU 完成存储器读写操作,此时 BIU 会将 CS 段地址的值传给 BIU 内部的 ALU,并乘以 16 ,然后 EU 通过内部地址总线将 BX 内部的值传输给 BIU 的 IP,段内偏移地址,并将 IP 中的段内偏移地址也传给 ALU,ALU 计算后得到物理地址。最后 EU 将 AX 内的数据放入数据总线,BIU 将物理地址放入地址总线,EU 给外部传输器发送一条写命令,即可完成数据传送的操作。各类指令的地址信息:

8086 指令系统及程序设计(第三章与第四章部分内容)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- 汇编语言指令
- 冒泡排序法
- 8086 系统指令
- 宏指令
- 信息保护、恢复
- 子程序
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
汇编语言指令
名词解释:
指令系统: cpu 能够识别的所有指令的集合。
机器语言:指令代码语言 → 机器语言程序,指令繁琐难记。
汇编语言:符号化语言 → 汇编语言程序 → 机器语言程序。将汇编语言源程序 → 机器语言程序 的过程称为汇编。
汇编程序及文件
用于汇编的程序为 MASM.exe ,使用 5.0 以上的版本。
各个汇编文件间的关系:
- 编写汇编语言源代码,并保存在
.asm
文件中。
- 使用汇编器将
.asm
文件编译为.obj
目标文件。
- 使用链接器
LINK.exe
将一个或多个.obj
文件链接成可执行文件(如.exe
)。
- 如果需要调试,可以使用
DEBUG.exe
来加载和调试生成的可执行文件。
汇编语言程序中语句的种类
- 指令语句。凡是 cpu 能够执行的语句称为指令语句,能够会汇编成指令代码。
- 伪指令语句。CPU不能直接执行的语句,不能汇编成二进制指令代码。是汇编器要明白的语句。
- 宏指令语句。是8086本身没有的指令语句,是用户宏定义伪指令定义的一条新的语句。类似于 C 中的函数。
汇编语言中的语句组成
变量名 助记符 操作数:如
DAT1 DB 12H, -12, 12
。标号名: 助记符 操作数:如
NEXT: MOV AX, BX
。标号名可以储存语句所在行的地址,方便程序员后续调用此地址的内容。
无论是变量名还是标号名,都是名称,需要以字母开头。
书本内有关指令的部分内容:


标号的介绍:

如果要获得标号的段地址,可以使用 SEG,如果要获得其偏移地址,可以使用 OFFSET。
变量的介绍:



属性操作符和 PTR

$ 运算符
还有一个特殊的操作符
$
,作为位置计数器。例: DAT1 DW $
就定义了一个 16 位的变量 DAT1,存放的是 DAT1 当前的地址。
常用指令
- CBW 指令。
意思是 Convert Byte to Word,CBW
指令会将AL
寄存器中的8位有符号数扩展为16位,将结果存储在AX
寄存器中,并实现符号位的扩展。 如果AL
中的最高位(符号位)是0,则AH
会被清零;如果最高位是1,则AH
全部置为1(即符号扩展)。
8086 指令分类


数据与转移地址的寻址方式
寻址方式指的是求操作数所在地或所在存储器单元地址的方式。
数据的寻址方式:

在 x86 汇编语言中,
MOV
指令的操作数必须遵循以下规则:- 源操作数和目标操作数之间必须有一个是寄存器,另一个可以是内存地址、立即数或寄存器。
- 直接的内存到内存操作是不被允许的,因为处理器无法在一条指令中直接处理两个内存地址。
- 在 MOV 指令中,不能进行操作数的运算,如
MOV AX, DAT1 - DAT2
立即数寻址


寄存器寻址

在寄存器寻址时,有几个注意点
- 源操作数与目的操作数的类型要一致。如 MOV AX, BX 不能写成 MOV AX, BL
- 源操作数与目的操作数至少有一方类型要明确。如 MOV WORD PTR [0200H], 53H,要有类型转换符。
- 当使用段寄存器 DS, ES, SS 作为目的操作数时,源操作数不能是立即数,立即数要先传递到通用寄存器中。
存储器寻址
要寻找的操作数在存储器的某单元中,存储操作数单元的 EA,可以由以下五种方式求得。
直接寻址。指令中直接写出操作数单元的地址。


在直接寻址的过程中,要注意的是 两存储器单元之间是不能直接操作,操作包括寻址、相加或是其他运算。例如 
MOV DAT1, DAT2
就是错误的,需要先将其移动到寄存器中,再进行下一步操作。
寄存器间接寻址。[BX] [SI] [DI]

注意:
MOV [AX], [SI]
这样的语句是错误的,需要先将其中一个地址取出放入寄存器里,再移到另一个寄存器中。寄存器相对寻址。【BX, BP, SI, DI + 8/16 位 disp(相对偏移量)】

示例:

基址【BX BP】变址【SI, DI】寻址 (格式: [BX][SI])

基址,变址且相对寻址 {【BX, BP】, 【SI, DI】+ 8/16位 disp}

隐含寻址

转移地址的寻址方式:
无条件转移指令,如 JMP 既可以实现段内转移,也可以实现段间转移;
而在 8086 系统中,所有的条件转移指令都只能在段内转移,且转移的范围为 -128 ~ 127 之间。
如果在程序设计时,使用条件转移指令,但转移的范围超出了上面提到的范围,那么需要使用 JUMP 语句搭桥。
所有的条件转移指令都采用段内直接寻址(或者叫做段内相对寻址)。
JMP 指令的介绍及其与 IP 的关系
JMP
指令和 IP
(指令指针)之间的关系是非常密切的。在8086汇编语言中,JMP
指令用于改变程序的执行顺序,直接修改 IP
的值,使程序跳转到一个新的地址继续执行。JMP
指令的基本工作原理:IP
寄存器:IP
寄存器存储了当前正在执行的指令的地址(相对于当前代码段CS
的偏移)。- 每次执行完一条指令后,
IP
会自动递增,指向下一条指令的地址。
JMP
指令:JMP
是“跳转”指令,它直接修改IP
的值,使得程序不会顺序执行下一条指令,而是跳转到由JMP
指令指定的新地址。- 通过
JMP
指令,程序的执行流可以跳转到代码的其他部分。
JMP
和 IP
的关系:- 修改
IP
:JMP
指令的执行实际上就是把IP
的值设置为跳转目标地址的过程。无论是短跳、近跳还是远跳,JMP
都是通过改变IP
的值来实现跳转的。
- 目标地址:
JMP
指令通过提供一个目标地址或偏移量来设定新的IP
值。这个目标地址可以是绝对地址,也可以是相对于当前IP
的一个偏移量。
段内直接寻址(相对寻址)

在使用无条件转移语句 JMP 时,指针 IP 的值的计算:
无条件跳转指令(JMP)的类型:
8086 中的无条件跳转指令
JMP
有以下几种形式:- 短跳转(Short Jump):
- □□(两个字节)
- 操作码:1字节
- 偏移量:8位(即1字节,表示 -128 到 127 之间的偏移)
- 跳转范围:-128 到 +127 字节范围内的代码。
- 近跳转(Near Jump):
- □□□(三个 字节)
- 操作码:1字节
- 偏移量:16位(即2字节,表示 -32,768 到 32,767 之间的偏移)
- 跳转范围:当前代码段内任意位置。
- 远跳转(Far Jump):
- 操作码:1字节
- 偏移量:段偏移地址 + 16位段地址(共4字节)
- 跳转范围:可以跳转到任意代码段中的任意位置。
IP 值的计算:
- 短跳转:
- 假设当前
IP
的值为P
。 - 如果是短跳转,指令的偏移量
offset
是一个8位的有符号数。 - 在执行
JMP
后,新的IP
值为P + 2 + offset
,其中 2 表示JMP
指令占用的字节数。2 个字节数包括 JZ 占用的 1 个字节 和 disp 所占用的 1 个字节。而为什么是 IP + 2 呢?因为IP 指的是地址,IP+1 指向的地址可以存放一个字节的内容,IP + 2 的也是存放一个字节,这两个字节被占用了,因此需要 IP + 2。
- 近跳转:
- 假设当前
IP
的值为P
。 - 如果是近跳转,偏移量
offset
是一个16位的有符号数。 - 在执行
JMP
后,新的IP
值为P + 3 + offset
,其中3表示JMP
指令占用的字节数。
- 远跳转:
- 如果是远跳转,
JMP
指令不仅改变IP
的值,还会改变段寄存器CS
的值。 - 新的
IP
值为offset
提供的值,而CS
则由段地址部分提供。
例子:
- 短跳转:
- 如果
IP = 0100H
,JMP
的8位偏移量是10
,那么新的IP
值为0100H + 2 + (-10)
=00F8H
。
- 近跳转:
- 如果
IP = 0100H
,JMP
的16位偏移量是20H
,那么新的IP
值为0100H + 3 + 20H
=0123H
。
- 远跳转:
- 如果执行远跳转指令
JMP 1234:5678H
,那么CS
被设置为1234H
,IP
被设置为5678H
。
例题:
题目:
8086 CPU 执行JZ、L1 指令时 P=0100H, disp=FDH,指令执行后(IP)=?
求解过程:
IP = P + 2 + FD H = 00FF H。(至于为什么要加 2 看上面有关指针 IP 计算的内容)

段内间接寻址

例题:假设有一段代码,可以实现的功能如下:当 AL = 1时,跳转到 L1; 当 AL = 2 时,跳转到 L2;当 AL = 3 时,跳转到 L3,该如何实现呢?
8086 系统的各种指令
数据传送类指令
除 SAHF、 POPF 指令外,其余传送类指令 CPU 执行后,对 6 个状态位标志均无影响。

语法规则
- 立即数只能做源操作数;
- 类型要明确;
- 类型要一致;
- DS ES SS 做目的时源操作数不能为立即数;
- CS IP 不能做目的操作数;
- 两存储器单元之间不能直接操作;
- 指令语句中不允许两个变量参与运算。
通用传送类指令

取有效地址指令

在进行 LEA 指令的时候,目的操作数最好是放在 BX, BP, SI, DI 中,放在AX BX里面也可以,但是这样就不能间接寻址相对寻址,源操作数必须是五种存储器寻址方式之一指明的单元。

取地址指针指令(用的不多)

标志传送指令

数据交换指令

源操作数与目的操作数均不能是立即数;
字节转换指令

例题:

堆栈操作指令




算数运算类指令
CPU 只要参加运算,其结果就会影响状态标志。段寄存器不能参与运算。上述规则不仅适合于算术运算,也适合于逻辑运算。
加法指令

ADD 加法指令为 不进位加法指令,ADC 为进位加法指令。

INC DST
指令为自增指令,将 DST 的内容加一后赋值给 DST,其中 DST 的内容不能是立即数,INC
指令只有五个标志位,不包含 CF 进位标志位。减法指令

比较指令

比较指令相当于进行了减法运算但不储存结果,只记录过程中符号位的变化,方便后续进行相关的条件语句。
8086 指令系统中涉及到的条件语句指令:
求负(取负)指令

将源操作数取负后重新设置状态标志位。
例题:
题目:
在存储器的 BUFFER,有一个 16 位的带符号数,求该数的绝对值,并将结果放回原处。
求解过程:
① 分析题目,提出算法
求一个数的绝对值其实可以使用一个分段的数学表达式来表示,。
因此需要先判断 x 与 0 的大小,如果小于 0 需要进行取负的操作。
② 绘制流程图

③ 编写程序
乘法指令

执行乘法指令后,只影响 CF 和 OF 两个标志位,其他标志位的结果没定义。
除法指令

例题:
题目:

求解过程:

符号扩展指令

BCD 数调整指令


加法调整指令:

减法调整指令:

乘法调整指令:

除法调整指令:

逻辑运算类指令

逻辑与:

逻辑或:

逻辑异或:

逻辑非:

TEST 指令:

移位类指令



条件转移指令
无条件转移指令 JMP 既可以实现段内转移,又可以实现段间转移; 有条件转移指令只能实现段内转移。

循环指令

LOOP 指令


LOOPZ 指令
LOOPNZ 指令
JCXZ 指令

字符串操作指令






在执行了上述的操作指令后, SI 和 DI 的值都会发生改变,但具体是往增加的方向改变还是减小的方向改变需要看 DF 的值。若 DF = 0 ,则往增加的方向改变,若 DF =1,则往减小的方向改变。具体增减多少,要看调用的类型。
串操作指令的左边可以增加重复前缀,具体重复的次数存放在 CX 中。

输入输出指令
在前面,我们采用 MOV 指令来访问存储器设备,但是对于 IO 端口而言,我们不能使用 MOV 指令进行访问。IO 端口有专门的输入输出指令。
端口输入指令

在使用间接寻址的过程中,如果采用的是 DX ,则不需要加上中括号(因为 DX 在 IN 和 OUT 指令中直接代表的是端口地址);
如果使用的是 SI, DI, BX,那么需要加上中括号。
这意味着采用间接寻址时, DX 不需要做类型转换,但是 SI DI BX 需要,如 IN AL, DX
端口输出指令

CPU 执行一条指令所花费的时间称为总线周期,对于端口输入操作而言,需要花费 4 个总线周期,对于端口输出操作,多了一个等待周期,需要花费 5 个总线周期。
其他指令
标志位处理指令

处理器控制指令

宏指令

定义:

宏调用与宏展开:

宏指令中的标号与变量:

使用 LOCAL 的示例:

在新程序中使用 DATAMOV 宏指令时, NEXT 的地址就会自动设置为 ??0000 ??0001,这样就避免了 调用 DATAMOV 两次以上时,NEXT 会重叠。
宏指令与子程序的区别
- 定义和使用方式:
- 宏指令: 宏指令是在汇编代码中定义的一段代码块,可以在程序中多次调用。每次调用时,宏指令会被展开为相应的汇编代码。也就是说,宏指令的代码会被直接插入到调用宏指令的位置。
- 子程序: 子程序是一段可以在程序中调用的代码段,但与宏指令不同的是,子程序在调用时不会展开代码,而是通过跳转的方式执行代码,然后返回调用处。
- 性能:
- 宏指令: 由于每次调用宏指令时,代码都会被展开,因此在程序中多次调用宏指令会增加代码的长度。这在代码规模较大时可能会导致程序的可执行文件变大。
- 子程序: 子程序的代码仅在内存中存在一份,不管调用多少次都只占用这一份代码空间,因此可以有效减少可执行文件的大小。
- 效率:
- 宏指令: 宏指令在编译时展开,减少了程序运行时的跳转操作,因此在执行速度上可能比子程序快。
- 子程序: 子程序调用时会有跳转和返回操作,因此可能稍微降低程序执行的效率。
- 灵活性:
- 宏指令: 宏指令比较灵活,可以通过参数生成不同的代码块,但它不能像子程序那样使用局部变量和返回值。
- 子程序: 子程序支持使用局部变量、参数传递和返回值,适合处理更复杂的逻辑和数据操作。
子程序
将 8086 中完成某个特定功能的外挂程序称为子程序,和 C++ 的函数一样。
子程序又称为是一个过程。
子程序的定义代码如下:
<子程序名> PROC [类型]
子程序名和标号名和变量名一样,需要以字母开头且有实际意义。类型可以是 NEAR ,也可以是 FAR 。如果类型是 NEAR ,类型名可以缺省。子程序可以通过 CALL 来调用(后面会细说),如果 CALL 指令与子程序不在一个段内,就需要显式指明是 FAR 类型的。
子程序内部的代码称为子程序体,或是功能体。在子程序段结束后,要在末尾加上
RET
(return) 语句,这样程序地址就会返回到调用语句的下面一段代码处,继续源程序的运行。如果是段间调用的代码,理论上来说最后的返回语句应该是 RETF
,但是由于在子程序定义的时候就已经声明了类型,因此也可以用 RET
来替代。在定义完一个子程序体后,RET 的作用是告诉调用的指令要返回了,但是在 RET 的后面还要加上一个 <子程序名> ENDP
来在形式上结束这个程序段,有始有终,此处的子程序名与 PROC
前面的要相同。子程序名一旦定义,就具有了三个属性——① 段地址属性; ② 段内偏移地址属性(EA);③ 类型的属性。
在实际的设计中,一般都是采用程序模块化的方式来编写程序的,这样设计的程序如果要加入新的功能或模块 ,只需要另外设计一个子程序,再将 CALL 语句加入源程序就可以了。
子程序的调用与返回
子程序调用的代码:
CALL <子程序名>
,程序调用的过程中,堆栈段自动进行如下的操作:
段间子程序调用:

虽然程序调用过程中会自动地进行堆栈的操作,但是,如果在子程序内部有进行对战的操作,一定要记住 PUSH 和 POP 两个要配上对,否则会破坏 SP 指针,使得程序无法正常返回。
课本中关于子程序调用的说明:

课本中关于子程序返回的说明:

信息的保护与恢复
信息的保护与恢复是通过堆栈来完成的。
信息的保护与恢复既可以在子程序外进行,也可以在子程序内进行,但推荐在子程序内进行。
不管如何,一定要记住先入后出原则,PUSH 和 POP 要配上对。
主程序与子程序之间参数的传递
有三种方式:
- 寄存器传递(寄存器只有 14 个,传递的参数有限);
- 存储器单元传递(要在数据段定义存储器单元);
- 堆栈方式传递。
子程序的说明文档
子程序的说明文档是为了让别人能够理解子程序的功能,方便别人调用。
需要包含的内容:
- 子程序名;
- 子程序的功能;
- 子程序的入口参数;
- 子程序的出口参数;
- 用到的寄存器(避免用户之前使用了子程序中相同的寄存器,造成原数据的丢失);
- 调用示例。
子程序的嵌套
子程序理论上是可以无限嵌套的,但是实际上却又受到堆栈区域大小的影响,不建议设置太多的嵌套,不利于调试。
子程序的嵌套是自上而下的,但是调试是自下而上的。
可再入子程序

程序的中断与调用
这个部分和第八章的牵扯比较多,因此将这一部分的内容全部都放到第八章的笔记中。
汇编语言程序设计(第四章)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- 伪指令
- 条件分支
- 冒泡排序法
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
程序设计基础(伪指令)
程序设计的步骤

段定义伪指令

微机原理中表示结尾的标志:
- END 。用于标志整个程序的结束。它通常用于程序的最后一行,表示汇编程序的结束。
- ENDS。S 表示 SEGMENT,用于标志段定义的结束。
- ENDP。P 表示 PROGRAM,用于标志子程序定义的结束。
STACK 类型:

系统会自动创建一个 256 B 大小的空间用于堆栈操作,如果想要插手这个过程,可以使用下面的方式:

在堆栈段定义过程中如果使用了 TOP LABEL WORD 手动设置了地址,那么在进行段初始化的过程中需要手动初始化堆栈段(如图中红框部分所示),更改 SP 的位置,改变堆栈段的大小。如果没有使用 TOP ,或是不打算更改 SP,那么红框部分可以省去,因为系统会自动进行初始化操作。
LABEL 伪指令

ASSUME 伪指令(代码段)

在段定义之后,就要进行 ASSUME 操作,要注意的是,如果 ASSUME 指令无法在一行内完成,换行时,仍要使用新的 ASSUME 开头。

END 伪指令

程序结束时最终需要些写的代码如下:

EQU 伪指令和 “=”伪指令

GPT 对 EQU 伪指令的解释
在微机原理中的汇编语言中,
EQU
和 =
是两种常用的伪指令,用于定义常量或符号名称。虽然它们在功能上有相似之处,但有一些关键的区别。EQU
指令
- 作用:
EQU
指令用于为一个符号赋予一个固定的值。该值在整个程序中是恒定的,不能被重新定义或修改。
- 类比:在 C++ 中,
EQU
指令的作用可以类比为const int a = 3;
。EQU
定义的符号是不可变的,就像const
修饰的变量在 C++ 中不能被修改一样。
上述代码中,
MAXLEN
被定义为常量 100,在程序的其他地方都可以使用 MAXLEN
来表示 100,但不能重新赋值。=
指令
- 作用:
=
伪指令也用于给符号赋值,但与EQU
不同的是,使用=
定义的符号可以在程序中被多次重新定义。
- 类比:在 C++ 中,
=
伪指令的作用类似于普通变量的赋值操作,例如int a = 3;
,后续可以再次为a
赋值。
上述代码中,
MAXLEN
的值可以从 100 变为 200。关键区别
- 不可变性:使用
EQU
定义的符号在程序中只能被定义一次,其值在程序中不可改变。这类似于 C++ 中的const
常量,一旦定义就不能修改。这样可以确保程序的某些关键值在运行时保持不变,提高程序的稳定性和可预测性。
- 可变性:使用
=
定义的符号可以在程序中多次被重新定义,每次定义都会覆盖上一次的值。这类似于普通变量的赋值,可以在不同的地方进行更新和修改。这种灵活性在某些场景下可能更为实用,但同时也带来了更多的风险,因为程序中的同一符号可以在不同的地方代表不同的值,可能导致逻辑错误。
ORG 伪指令

分支程序设计
单分支语句:只有一个条件判断语句。多分支语句:有多个条件判断语句。
程序调试时要保证每个分支的独立性,即要把条件成立的程序测试一遍,同时还要把条件不成立的情况测试一遍。
分支程序设计要点:
- 正确选择分支的条件和条件转移指令。
- 在编写程序时要保证每个分支程序的正确性。
循环程序设计
循环程序的组成:
- 初始化部分;
- 循环工作部分;
- 参数修正部分;
- 循环出口判定;
- 结果处理。
冒泡排序法:


总线及其形成(第五章)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- 总线
- 74LS244 74LS245 74LS373
- 最小工作方式 最大工作方式
- 各种引脚
- 8088 与 8086 的区别
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
总线的定义及分类
定义:
总线是一种用于在计算机系统的不同组件之间传输数据的通信系统。它可以将处理器、内存、输入/输出设备等连接在一起,使得这些组件能够互相交换数据。总线的作用类似于一条高速公路,它在系统中充当数据的“通道”。
分类:
- 片内总线;
- 元件级总线(板内);
对于频率比较高的总线,走线时尽量不要呈 90°,同时外部还要加上屏蔽网。
- 内总线(系统总线);
板与板之间连接的总线,像常见的计算机插槽间的总线就是内总线。本章主要涉及这一类总线。
- 外总线(通信总线)。
几种常用芯片的介绍
- 74LS244 器件(8 位数据单向缓冲器)
LS 指的是速度,74 指的是工作温度,74 系列的缓冲器主要适用于民间使用,而 54 系列的缓冲器更多的是军用,价格更高,工作温度范围更广。

当 时,输出 1Y1 ~ 1Y4 随着输入 1A1 ~ 1A4 变化,当 时,无论输入怎么变,输出都不会发生变化。
控制的是 2Y1 ~ 2Y4 是否随着输入 2A1 ~ 2A4 输出,以此类推。
2. 74LS245(八路双向总线收发器)



- 74LS373(8位锁存器)
- 74LS374
- 74LS138





如 CBA = 000 时, 。
8086 cpu 引脚功能
MN/MX非 (最小工作方式与最大工作方式)


最小工作方式(最小方式):给外部存储器 or I/O 的读/写控制信号由 CPU 引脚直接产生(单处理系统)。
最大工作方式(最大方式):不是由上述器件产生,而是由 8086 CPU 外部的总线控制芯片 8088 产生(多处理系统)。

最小工作方式:

最大工作方式:

最小方式下的引脚功能:
CLK 信号

RESET 引脚
cpu 通过 RESET 端口进行复位,RESET 为复位引脚,高电平有效,高电平有效时间至少大于等于 4 个时钟周期 T。

DEN 非引脚和 DT/R非 引脚
:

:

M/IO非

WR 引脚和 RD 引脚
:

:

~ 引脚

在 状态下,可以使用 74LS373 器件将地址总线上的地址锁存,锁存的地址就称为系统级的地址总线。在其他 T 状态下,总线就可以有其他的用途。



ALE 是用于控制 74LS73 的 G 端口的,用于控制 74LS73 是否锁存数据,上升沿跟随,下降沿锁存。
ALE 引脚

READY 引脚

BHE非/S₇
BHE 又称为高字节允许信号。

当 CPU 对偶地址进行读写操作时,肯定有 ,当 CPU 对奇地址进行读写操作时,肯定有 。同时电路结构中规定,偶地址中的内容一定是靠低 8 位总线传输,奇地址中的内容一定是靠高 8 位总线传输数据,这是电路结构规定的。

在上面的表格中,只有当 和 都为 0 的时候,才能够同时读或写偶地址和奇地址的数据,同时只有当 为低电平的时候高字节的数据线才能够启用,高字节数据才被允许写入。
而对于一个字节的数据而言,高位的数据存放在高地址中,低位的数据存放在低地址中。
将上面两点结合起来,假设一个字的数据存放在 AX 中,准备写入 [2000H],由于对准的是偶地址,调用表 5.2 中对偶地址操作的字指令,此时 和 都为 0 ,那么 AL 和 AH 中的数据就会分别写入 [2000H] 和 [2001H] 中,耗费一个总线周期的时间。

假设一个字的数据存放在 AX 中,但准备写入地址 [2001H] 中,由于是奇地址,调用表 5.2 中的对奇地址字操作的指令,此时 和 分别为 0 与 1,先使用 ~ 写入低地址单元,再使用 ~ 写入高地址单元。

为什么奇地址需要两个总线周期?
在地址是对准的时候,低字节数据能够通过低地址总线 ~ 总线传输数据,此时 ,而高字节的数据会尝试是否能够同时进行传输,高 8 位数据此时对准的是奇地址,能够使用高地址总线 ~ 传输数据,要想使用高地址总线,首先会判断 是否满足,由于 已经等于 0,因此只能让 ,可以同时写入数据,耗费一个总线周期的时间。
当地址不是对准的时候,低 8 位数据只能写入奇地址,要想写入奇地址只能使用高地址总线,将高 8 位数据和低 8 位数据分别看作是两个字节,要想让低字节写入奇地址,那么此时必须让 (表 5.2 中),此时高 8 位的数据会尝试是否能够同时进行传输,高 8 位数据对准的是偶地址,由于 不能同时为 0,因此只能分为两个总线周期。
NMI INTR INTA非

HOLD 和 HLDA

8086 引脚示例

常用引脚

最大方式的特点

最大方式就是通过 ,, 的组合让 8288 发出控制信息,与最小方式不同,并不是通过 cpu 本身发出信息来进行控制的。
最小方式最大方式总结




当题目描述为在 8088 系统中,而没有提及究竟是最大系统还是最小系统时,一律将其看作是最大系统。
8086 与 8088 的区别

- 数据总线宽度:
- 8086:拥有 16 位的数据总线,这意味着它可以一次性传输 16 位的数据。因为数据总线宽,所以它在处理器和内存之间的数据传输速度更快。
- 8088:只有 8 位的数据总线,因此它每次只能传输 8 位数据。虽然它的内部结构仍然是 16 位的,但因为外部总线是 8 位的,所以数据传输速度会比 8086 慢一些。
- 性能影响:
- 由于 8086 的数据总线是 16 位的,它能够更快地从内存中读取和写入数据,这使得它在处理大量数据时性能更好。
- 8088 的 8 位数据总线虽然在性能上不如 8086,但它与当时的许多 8 位系统硬件兼容性更好,成本也更低。
- 的影响:
- 在8086 系统中,地址分为奇地址和偶地址,需要通过 来进行寻址,而在 8088 系统中,没有 ,也没有奇地址和偶地址的分别。
这一章节的内容我当时看的没有特别的认真,后面一定好好再补补🐶(对不起‼️周老师😶🌫️)
存储器设计(第六章)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- ROM SRAM
- 存取时间 存储周期
- 6264 存储器
- 位扩展 字节扩展
- 8088 系统存储器扩展设计
- 8086 系统存储器扩展设计
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
存储器分类
外存——暂存暂时不用的数据和程序叫做外存,如硬盘。
内存——存储现在要用的存储器和数据叫做内存,大多由半导体构成,又称半导体存储器。

在本门课中,主要是设计 静态 SRAM。SRAM 常用的是 62 系列,如 6264(,本门课程需要掌握的) 6212()。

设计的技术指标
- 容量上,尽量选择容量大的器件来进行设计。
使用太多容量小的器件会增大系统的功耗,增加散热。
- 速度。

最小读出时间和最小写入时间:

最后再减去 T 是为了留出一定的富余量,在工程上一般要让器件留有 30% 的富余量。
的理解:信号的反射会对信号造成延时,当两个器件之间的阻抗不匹配的时候,一个器件发出的信号另一个器件吸收不完全,就会发生反射,反射回来的信号又会因为吸收不完全而再次反射回去,造成延时。

还有一种情况也会造成 ,即当两根传输线挨得比较近的时候,会有耦合电容的存在,耦合电容的大小与线的长度以及线与线之间的距离有关。耦合电容的存在会使得交流信号对其他线路产生影响。
存储器芯片的介绍
6264 存储器
存储器内存是 8k X 8. 即地址总线是 13 根,每个存储单元的容量是 1 个字节,8位。

6264 存储器是双片选存储器,只有当 的时候,存储器才有可能是工作的,一般情况下 都接高电平,于是器件就会称为是单片选器件。 和 两个引脚分别用于读操作和写操作,读操作是通过地址总线读取 的数据,写操作是相反的,将 的数据写入地址线 指向的地址单元。
6264 存储器在 8088 系统与 8086 系统中的连接:

位扩展和字节扩展

存储器扩展设计
8088 系统:


第三问涉及的检修程序有以下几种:
- (粘连故障)55H 和 AAH 法。向器件输入1 个字节的数据,看输出是否正常。55H → 01010101 B;AAH → 10101010 B。
- (链桥故障)谷值/峰值检测。
第二小题:

8086 系统:


常用芯片的接口技术(第七章)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- I/O 接口电路 接口技术
- I/O 端口地址 信息的种类
- 独立编址 统一编址
- 无条件输入/输出
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
什么是常用芯片?
输出端口: 74LS373 74LS374 74LS273
输入端口:74LS244 74LS245
I/O 接口概念
由于设备种类繁多,要求通信的信息格式多样,所以 CPU(计算机)与设备之间不能直接通信。
因此需要在二者之间设计一个电路将二者连接起来。该电路就称为 I/O 接口电路。
对于 I/O 接口电路分为 I/O 硬件设计和 I/O 软件设计两种,它们合起来称为 I/O 接口技术。
I/O 接口组成
一种信息通过一个 I/O 端口进行传输,一个 I/O 端口要分配一个 I/O 端口地址。
信息的种类有三种:① 数据信息(入/出);② 状态信息(入);③ 命令信息(出)。

I/O 端口是用寄存器的设计来实现的。
I/O 地址的编址方式
- 独立编址(用于 8086 系统)。

I/O 地址寻址只有两种方式,一种是直接寻址,另一种是对寄存器的间接寻址。独立编址方式比较不灵活。寻址方式越多,就越灵活。
- 统一(映像)编址。
外部存储器与外部的 I/O 统一共享了地址。cpu 将外部 I/O 系统同样当作是一个存储器单元来使用,因此对于外部存储器的指令,对于外部的 I/O 端口依然适用。但缺点是外部 I/O 端口占用了外部存储器的地址,浪费了存储器的存储空间。

输入输出方式
程序直接控制的输入输出方法(in/out 指令)
- 无条件输入/输出方式。
只要有输入数据,那么输出设备无条件就会接收,如外接一个 LED 灯。
或者是通过开关控制是否输入数据的也是无条件的,永远处于数据准备好的状态。

cpu 与输出设备之间需要设计一个锁存器来锁存数据,因为 cpu 不可能一直与一个输出设备连接,让该输出设备一直占用总线资源,通过锁存器可以让输出设备保持在锁存值的状态下。锁存的端口大多使用 74LS374 或是 74LS273,但是很少使用 74LS373,因为 373 的 G 端口是高电平有效的,会造成系统的不稳定。
- 查询法输入输出。

电路实现简单,但是效率低。举一个夸张的例子,当 cpu 在 8 点开始运行的时候,查询设备状态,如果设备没有准备好,那么 cpu 就会继续查询,很可能到了 12 点都还在查询过程中,始终没有准备好。
查询法例题:
题目:
A/D 变换器的电原理图与主要工作时序如下:

A/D 变换器能否对 端口进行采集变换受控制信号 控制,当给 输入正脉冲的时候,正脉冲的下降沿启动 A/D 变换,A/D 变换需要一定的时间,在这段时间内,会输出状态 EOC。在变换时间结束后,有效数据才会经过 进行传输。
题目要求:数据的输出需要有一个数据输出端口,数据输出端口的地址为 8001 H;还需要设计一个状态输出端口用于输出 EOC 的状态,地址为 8003 H;要启动变换,需要设计一个命令输出端口输出一个命令给 ,地址为 8005 H。
(1) 将此 A/D 变换器与 8086 最小变换总线系统连接起来;
(2)编写对 采集一次,并将变换后的数据存入 ADBUF 单元的程序。
解答:

因为取的 8001 H, 8003 H, 8005 H 都是奇地址,因此最低位可以使用 $\overline{BHE}$ 来代替。
- 中断法。

使用中断法来进行输入输出大大提高了效率,但是 8259 内部的设计却十分复杂,不过好在 8259 在设计好后可以作为芯片量产。
- DMA 方法(硬件的方法)→ 硬件复杂,但是输入输出全靠硬件实现,在本门课中不要求掌握。
中断系统与可编程中断控制器(第八章)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- 中断 中断源
- NMI INTR
- 执行中断的过程
- 中断向量表 中断向量
- INT 21H
- BIOS 功能
- 8259A 引脚及功能 级联
- 8259A 内部组成
- IBM PC/AT 机 端口地址 中断类型号基值
- 初始化命令字编程
- 操作命令字编程
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
中断的基本概念
中断的定义:
计算机在程序运行过程中,由于发生了某些“紧急事件”,需要进行特殊处理(转向中断服务子程序执行),处理后返回到程序中断处继续执行,这种过程称为中断处理过程。
中断源的定义:
谁向CPU引起了中断请求,就是那个中断源,中断源可以在CPU内部,也可以在CPU外部。
中断服务子程序指的是为提出中断请求的中断源服务的程序就称为中断服务子程序。
8086外部中断源请求输入引脚有两个,一个是NMI,一个是INTR。
对于NMI外部中断输入响应请求,CPU要无条件响应,这种请求称为外部非可屏蔽中断请求。
对于 INTR 外部中断请求,CPU 是否响应受 IF 中断标志位的控制。
中断的分类:
内部中断、外部不可屏蔽中断、外部可屏蔽中断。
8086 的中断结构

除数为0,商溢出两种情况下会自动触发除法错误中断。
在程序执行过程中,如果程序能够连续执行,就称为程序的全速执行,如果运行到某条语句后,tf = 1,那么就会出发单步中断。
INTO 是一条指令,INTO 溢出指的是如果 OF = 1,那么运行到这条语句的时候就会触发中断,如果 OF = 0,那么就不会触发。
INT 3 设置的是断点调试。在程序中,我们常常会分段调试程序,在段分界点处设置一个 INT 3 断点(与标号类似),程序运行到断点处后,会自动调用用户写好的屏幕显示程序,测试前面是否运行顺利。通常将断点调试和单步中断结合起来进行,断点调试又称为 单字节中断。
INT n 是等待用户按键的指令, n 表示的是按键对应的 ASCII 码。

8086 系统中通过终端类型号来识别中断源,而 51 单片机是通过程序编程来识别中断源。
中断类型号:
识别中断源的号码称为中断类型号,范围在 0 ~ 255。
不同中断源的中断类型号:
- 除法出错 → N = 0;
- 单步中断 → N = 1;
- 断点中断 → N = 2;
- INT 3 → N = 3;
- INT n → N = n。
NMI 中断请求:
上升沿有效,CPU 无法拒绝的中断。
INTR 中断请求:
高电平有效,CPU 可以拒绝。般情况下用 STI 指令使 IF=1,确保中断开放。
该引脚会外接一个中断控制器(如 8259 A),中断控制器可以接受多个外部中断的请求,并通过 INT 端口与 cpu 联系。中断控制器还会有 ~ 8 个端口与 cpu 相连,用于 cpu 初始化中断控制器,可以在初始化的过程中主动屏蔽掉一些端口的中断请求,这样,不管 IF 是否置 0,中断控制器本身就会拒绝某些中断的输入。
在初始化的过程中,用户也需要分配中断控制器与外部中断源的中断类型号,但只需要手动分配 的即可,剩余的 IR 端口系统会顺序分配。
系统处理中断的过程
当遇到中断请求后,第一步,cpu 会将正在执行的指令执行完;
第二步,如果是外部可屏蔽中断,在 IF = 1 的情况下,cpu 会保护中断现场,即保存此时的 PSW, IP, CS (压栈保护);
第三步,如果是外部可屏蔽中断,那么就需要从 8259 中获取中断信号,执行中断程序;如果是内部中断或是 NMI 中断,由于类型号是固定的,那么就不会有第三步的过程,直接进行第四步;
第四步,清除 IF TF 标志位,清 IF 的目的,是为了确保在运行中断服务程序的过程中不受外部中断的干扰。清 TF 的目的,是让 cpu 在执行中断服务的指令时能够连续执行下去,若 TF =1,则会触发下一步的中断,所以清 TF 是为了防止出现陷阱中断。
第五步,将受到中断请求时的 n 乘以 4 得到中断向量的值(起始地址),将中断向量表中对应的起始地址赋值给 IP,起始地址的下一个字地址赋值给 CS;
第六步,执行地址所对应的中断服务程序。
等到中断程序执行完后,会执行 IREP 指令,PSW, IP, CS 又会返回,称为现场恢复。

从 cpu 收到中断请求到执行中断服务程序一共经历了 5 步,这 5 步称为是外部可屏蔽中断的响应过程。
中断向量表
中断向量指的是中断服务子程序的入口地址。
一个中断向量在字节表中存放占了四个字节,因为一个中断向量是 32 位,包括 16 位段地址和 16 位偏移地址。中断向量表的大小是 1024B,可以存放 256 个中断向量。

DOS 中断 INT 21 H 的功能
入口参数都是 AH。
从键盘输入字符(01 H, 07H, 08H):

调用方法:
向屏幕输出一个字符(02H):

调用方法:
实现回车+换行(02 H):

控制台输入/输出(06H):

DL 中存放 0FFH 的时候,表示的是控制台输入;DL 中如果想要输出字符,存放的就是输出字符的 ASCII 码。
向屏幕输出一串字符(09H):

显示系统时间(2DH):


终止进程(4CH):

BIOS 功能(部分)
通过 INT 10H 进行中断调用,入口参数为 AH。
显示器清屏功能(00H):

设置光标位置(02H):

可编程控制器 8259A 及其应用
引脚及功能(外部特性)

和 既可以进行写操作也可以进行读操作, 是片选信号,即是否允许 8259 A 启动, 是片内寻址的地址线,在 的情况下, 如果为 0,那么就会选中一个 I/O 端口地址,如果为 1 则会选中另一个。虽然只能选中两个端口地址,但是 8259 A 的内部却远不止一个寄存器存在。 

INT 引脚是用于向 cpu 发出中断请求的,与 cpu 的 INTR(外部可屏蔽中断)连接。当 cpu 响应请求时,会从 cpu 的 引脚向 8259 A 的 引脚发送两个负脉冲信号,第一个负脉冲信号用于告诉 8259A 它发出的中断请求 cpu 响应了,第二个脉冲信号是告诉 8259 A 将对应外设发出的中断类型号发送给 cpu,同时 cpu 内部也会在第二个负脉冲的总线周期中自动读取中断类型号。
8259A 的 引脚应该与 cpu 的 引脚相连,因为在 cpu 发送第二个负脉冲时,只有低 8 位做好了接受数据的准备。

老师说,级联缓冲基本上是不会使用的, 一般不处于缓冲方式。
在级联方式下,由主片与 cpu 进行沟通交流,8259A 收到中断信号时,会汇总给主片,由主片向 cpu 的 INTR 端口发送信号,cpu 响应后,会将负脉冲信号发送给主片。假设主片的 端口与某个从片级联,主片收到第一个负脉冲后,8259A 会从 发出从片选择代码 001,从片通过 接受 001 的代码并检测是否匹配,与 001 代码匹配的从片会处于准备状态,随时准备输出中断类型号,当 cpu 发送第二个负脉冲后,从片会将中断信号发送给 cpu。
内部组成

器件介绍:




中断结束方式:
① 自动结束方式(一般不使用)。它的作用是将中断类型号发送给 cpu,同时将 ISR 中的对应位清零。
② 非自动结束方式。它在将中断类型号发送给 cpu 的时候,并不会将 ISR 对应位清零,而是在 cpu 运行完中断结束程序后,发出指令告诉 8259 A 我的运行要结束了,让 8259A 先结束。
因此,外部可屏蔽中断不仅受 IF 控制,还受 8259 A 内部是否会屏蔽的影响。

初始化命令字 :
ICW1 可以设置 8259 A 是单片工作还是级联工作,还可以设置 8259 A 输入信号的有效形式是高电平还是低电平、上升沿等;
ICW2 用于设置中断类型号的基址(即 的地址),一旦基址确定了,其他地址也就确定了;
ICW3 只有在级联时才会发挥作用,用于告诉从片它的级联输出被级联在主片上的哪个输入了;
ICW4 用于设置缓冲方式、中断结束方式以及 优先权的排列方式,是固定优先权(优先级由 逐级递减,又称正常嵌套方式)还是循环优先权(指的是最开始的时候 最高, 中断请求响应后, 级就最高, 级就最低,以此类推)。
操作命令字 :
给 OCW1 写命令,相当于给 IMR 中写命令;
给 OCW2 写命令只在 8259A 处于非自动结束方式时有用,用于 cpu 快结束中断程序时让 8259A 先结束命令;
OCW3 一般不会使用。
IBM PC/AT 机
8259A 的工作过程

8259A 的编程
初始化命令字编程




操作命令字编程


例题:
题目:

题目中 “中断请求” 部分可以看作是一个锁存器, 是一个清零端。0BH 指的是 IR₃ 的中断类型号基值。
求解过程:
这个例题还是很复杂的,但老师说考试不会这样考,但是上面的例题有助于理解编写中断程序的步骤。
可编程定时器/计数器芯片 8253/8254 及其应用(第九章)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- 引脚功能
- 8253 内部组成
- 定时器
- 单脉冲形成
- 分频器
- 方波发生器
- 软件触发/硬件触发
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
可编程定时器/计数器 通常用于在器件固定的情况下,我们希望对器件的功能作出调整的时候。
引脚功能


从引脚定义中就可以注意到,8253 内部是没有 RESET 这个端口的,因此在工作期间系统 RESET 了对 8253 无影响。
8253 内部共有 3 个 16 位的计数器,其中每个计数器都有 GATE, CLK 和 OUT 这 3 个端口以及 6 种工作方式(方式 0 ~ 方式 5),通过下标来进行区分。有些工作方式是高电平有效,在门控信号为高电平的时候,可以对 CLK 进行计数。也有些工作方式是边沿有效或是低电平有效。
CLK 用于输入计数器的计数时钟,下降沿有效。
OUT 会定时时间到输出端(分频)。

和 端口用于选择端口,片内寻址。
8253 对于每个计数器都有一个控制字寄存器,它是通过控制字来控制具体选择哪一个计数器的。
8253 的内部组成及工作原理

cpu 设置计数器初值时是先写低 8 位 ,后写高 8 位 ,因为数据线只有 8 位;
在写完初值后,在第一个时钟下降沿就会把 和 (分别为计数器寄存器 CR 的低 8 位和高 8 位)的值写入减法计数器 。
在 8253 的内部,还有与计数器匹配的锁存器,如果是与第一个计数器匹配,那么它就是 (输出锁存器的低 8 位)和 (输出锁存器的高 8 位),锁存器的值会始终随着对应减法计数器 的值变化而变化。
用户可以通过 cpu 读取到 的值,但由于cpu 的时钟和计数器的时钟不同,因此想要读取 的值时,cpu 要先发送命令将锁存器的值锁住,然后发送命令读取锁存器的值,当锁存器中的值被读取后,锁存器就会自动开锁,此时它的值又会跟随 的变化而变化。
输入的 CLK 不能超过 2MHz
方式控制字寄存器

工作方式介绍
每个计数器都有方式 0 ~ 方式 5 六种工作方式。
方式 0(定时器)
方式 0 介绍(课本内容)


特点(课本内容)


当 在计数过程中经历了一个下降沿后,计数器会先停止计数,等待 变高后再继续(GATE 为电平控制时):

方式 1(单脉冲形成)
方式 1 介绍(课本内容)

特点(课本内容)


⭐!重点记!⭐ 方式 2(分频器)
方式 2 介绍(课本内容)

特点(课本内容)


与方式 0 不同,方式 2 的分频信号是自动写入的,也就是说,在一开始设置了分频系数后,后面计数器只要计数到 0 就会自动打入 6 重新开始计数
对于方式 2,分频的效果最终是体现在 OUT 端口的,因为 OUT 端口要每隔 N 才会重新开始计数。
⭐!重点记!⭐ 方式 3(方波发生器)
方式 3 介绍(课本内容)


特点(课本内容)



方式 4(软件触发产生选通信号)
方式 4 介绍(课本内容)

特点(课本内容)

方式 5(硬件触发产生选通信号)
方式 5 介绍(课本内容)

特点(课本内容)

6 种方式的总结

计数器的应用
计数器除了能够作为定时器唤醒 cpu 外,还有一个比较有趣的应用——看门狗。
有时候,在运行某段程序时,cpu 出了点问题, IP 指针突然指向了其他地方,不再在程序段内,那么很可能会导致 cpu 死机,即俗称的“程序走飞了”。
为了应对这个问题,我们可以在程序内部定点设置计数器,即看门狗,计数器的计数值恰好是运行程序段所需要的时间,或是略大于这个程序段的运行时间(因为程序的每条指令都是有总线周期的,因此可以实现),当计数器的数值达到预设的数值时,程序停止运行,这样就可以避免 IP 指针跳转到其他地方无法退出指令,造成死机。
当然,在某些情况下,我们希望程序能够跳转到原先走飞的位置,而并非在走飞后从头开始运行程序。为了实现这个目的,我们可以在程序段内每隔几条指令就设置一个计数器,计数器的计数值就是运行到下一个计数器所需要的时间。这样每运行一段程序,计数器的值都需要增加才能保证程序正常运行(应该是叫做“喂狗”),当程序走飞后,看门狗会记录走飞的位置,及时把 ip 叫回来,提高了系统的稳定性。
可编程并行接口芯片8255A(第十章)
💡 Key Words
这里的关键词只是帮助大家看完右侧的笔记后回忆内容,不是跳转链接!!
- 8255A 引脚及功能
- 方式 0 方式 1 方式 2
- 工作方式控制字
- 读取端口 C 状态
🔗 Relevant Information
第一版:
第三版:
📝 Class Notes
现实应用中还有可编程的串行器件 8250 和 8251(姊妹片)
为什么需要 8255A?

8255A 的引脚及功能
共有 40 个引脚,分为与外设相连的引脚和与 cpu 相连的引脚来记。


与外设相连的部分:
由于是并行接口,一个端口是 8 位,共有 3 个端口,因此输出端口共 24 个引脚。三个端口分别叫做 PA, PB, PC 。
PA 口和 PB 口都是可编程的,既可以将外设的数据传输到 cpu,也可以将 cpu 的数据传输到外设。
PC 口可以当作 8 位用,也可以当作是两个 4 位用,在实际应用中, 可以辅助 PA 口作用,将它们合起来称作是 A 组。 可以辅助 PB 口作用,将它们称作是 B 组。
在 8255A 内部有一个工作方式控制器端口,是 8 位的。
与 cpu 相连的部分:
RESET 是复位端口,交给芯片的复位信号宽度应该小于等于 cpu 的复位宽度。
是片外寻址端口, 和 是片内寻址端口,它们三者结合起来可以选择对应的端口。
8255A 内部有四个端口(PA, PB, PC, 控制端口),需要通过 A₀ A₁ 来进行片内寻址。

8255A 的工作方式与工作方式控制字
工作方式:
方式 0 :无联络信号的输入/输出,相当于是无条件输出的方式,使用 PA/PB/PC 作为输入/输出端口
方式 1 :有联络信号的输入/输出,使用 PA/PB 作为输入/输出端口,PC 端口不能用于输入/输出,因为它的高四位要作为联络端口与外设之间进行联络;
方式 2:双向端口(准双向),只能使用 PA 口。
在方式 0 和方式 1 中,一个端口传输数据时是作输出还是输入,它就只能是作为输出还是输入。而方式 2 下的端口既可以作输出,也可以作输入,但是不能同时为输出输入,因此为准双向的。
为什么方式 2 只能使用 PA 口?
因为在 PA口用作输入的时候,它需要两根 PC 线来进行联络通讯,其中一根用于外设发送数据告诉 8255 “我发送数据过去了”,另一根用于8255 发送数据给外设告诉外设“我把数据取走了”。
同理,在 PA口用于输出的时候,它也需要两根 PC 线来进行联络通讯,输入输出一共占用了 4 根 PC 线。上面使用的 4 根 PC 线都是 A 组的,都是高位的 PC 线。
但是 8255 还需要用一根 PC 线作为中断,在前面 4 根 PC 线已经被占用的前提下,只能向 B 组借一根 PC 线用于中断,那么 B 组就没有足够的 PC 线构成 PB 的准双向输入输出,因此只能使用 PA 口。
工作方式控制字:

例题:
题目:

求解过程:

方式 1 输入信号的具体过程:



首先,假设外设是通过 PB 口向 8255 A 发送数据的,由于 上一直有数据存在,因此 外设 需要有一个端口连接到 8255A,当有有效数据传输过来时,告诉 8255A “我要发送有效数据了”。这个端口就是选通端口 (strobe, 端口),它的下标 B 表示是 B 端口。
外设要发送数据时,会提前从选通端口发送一个低电平给 8255A,8255A 收到信号后会将外设发过来的 8 位数据暂时先存放到缓冲器中,在 cpu 取走数据前,8255A 都不能接收新的数据进来了。因此,在 8255A 上还有一个 (input buffer full)端()口用于判断缓冲器是否已满,如果缓冲器满了,它会发出高电平,告诉外设缓冲器已经满了,不能再发送新的数据过来了。
cpu 查询数据是否能够取走的方法有以下几种:
查询法:
对于 cpu 而言,如何知道 8255A 缓冲区数据已经满了呢?它会通过一次 in 操作查询 8255A 的 端口是否为高电平,如果是高电平,那么 cpu 就会将数据及时取走。cpu 取走数据后, 端口信号会再次变低,此时外设就又可以写入数据了。
与方式 0 的区别:方式 0 中,cpu 在任何情况下都可以读取到有效数据,而在方式 1 下,只有缓冲器是满的时候才可以读到数据。
中断法:
在 8255A 的内部有 和 两个中断触发器,只有在中断触发器置 1 的时候才可以触发中断(由编程决定是否置 1),在 8255A 中有一个类似与门的装置,可以将 INTE 和 IBF 的信号相与,只有当 INTE = 1(允许中断)以及 IBF=1 (缓冲器满了)才可以输出 1,与门的输出会连接到 端口(对于 PB 端口而言)。 会将数据发送给 8259A,如果此时 IF = 1,8259A 就会向 cpu 发送中断请求,cpu 响应中断请求后会执行中断程序,将缓冲器的数据读取。

PA 端口的过程与上面一致,只不过 和 的端口分别是 和 ,如果使用中断信号则使用 。
剩下的两根 PC 线 和 仍然可以用作是 I/O 线,作为方式 0 输入或输出。
A 组和 B 组使用中断屏蔽器的时候使用的 PC 端口:

当 A 组作输入方式的时候,控制位为 ,当 A 组作输出方式的时候,控制位为 。
B 组无论工作在哪种方式下,都是用 作为输出端口。
方式 1 输出信号的具体过程:



在 PA 口工作在输出方式下时,由 端口传输数据给输出设备,当 cpu 将数据传输给 8255A 时,由 8255A 发出 (output buffer full)信号告诉输出设备“可以过来取数据了”,由设备的 端口进行接收。设备接收到 8255A 发来的信号后,会从 8255A 处将数据取走,并向 8255A 发送 (acknowledge input)信号,告诉 8255A “我已经取走信号了”,这时 cpu 便可以发送新的信号过来了。
由 和 充当端口 A 的联络线。
在作输出方式的时候,8255A 通过中断法与 cpu 进行联络,首先, 中断触发器会置 1,然后和信号 相与,当 为低电平时(因为 只有在低电平的时候表示满),才会向 cpu 发送高电平的 信号。
剩下的两根 和 的线也可以用作 I/O 口的输入或输出。
方式 2 输入输出信号的具体过程:

读取端口 C 状态

8255A 与系统总线的连接

8255A 的应用(例题)
例题 (例 10.1):
题目:

求解过程:

例题(例 10.3):
题目:

注意:题目中的端口地址 20H, 22H, 24H, 26H 分别对应的是 8255A 的 PA口,PB口, PC 口 和控制端口。
原因如下图所示:

8255A 将使用 cpu 的 和 端口作为选择端口。
求解过程:

老师的代码示例: