外部结构就是封装出来的输入输出引脚。8086/8088有40个引脚。
- 8086片内片外的数据总线都是16位
- 8088片内16位,而片外8位

如此前绪论所说,部分引脚专用,部分引脚复用,复用部分需要掌握其时序。
CPU的这些引脚功能:
举个例子讲解一下这些引脚:
当CPU向外部(存储器/IO接口)写数据时,上图的WR引脚应为有效(低电平)
RD是读信号。
而区分操作存储器和I/O接口的是M/IO引脚
在此基础上可以设计逻辑电路来控制更具体的事情,比如WR和M/IO连接一个或门,就能产生IOW信号等。
8086CPU有20条地址线A19A<sub>16</sub>、A<sub>15</sub>A0,可以寻址\(2^{20}\)字节的空间,也就是1M空间,地址空间大小为1MB。

总线竞争:多个设备端口同时激活。
端口如下图右下角部分所示:

具体而言,外设芯片是有手册的,当我们操作显卡,就要查VGA相关的手册,鼠标和键盘就有另一个芯片来管理。
手册上会详细说明端口的作用,在程序中用指令向端口赋值即可。
上面提到,一个IO端口至少占用一个IO地址----IO端口地址。根据端口地址和存储器是否一起编址,有:
统一编址
独立编制
举个例子
某个I/O端口的地址为2000H,则访问如果要输出数据到该端口,汇编语言应该这样写:
mov AL,01H
;这里是要输出的数据量,仅是一个参考
;该课程中这里要点一个灯
mov DX,2000H
mov DX,AL
;注意这里跟存储器的并不同,没有中括号

不论CPU型号如何,其内部基本都有以下结构:

ALU:必须,算术逻辑运算
地址寄存器可以充当数据寄存器
数据寄存器不能充当地址寄存器
控制器:负责取指令,放在指令寄存器中,译码
I/O控制逻辑:与外部I/O打交道,使得CPU可以响应I/O设备发出的中断请求。
这部分要与其实跟计组没多大差别了,要结合CPU"取指执行"的思想来理解。
学到这里突然想复习 流水线 Verilog 什么的了。
因为上面的图还是很笼统,怎么判断、怎么控制时序都还没有涉及。先忍住,把接口部分学完。
上图并不完整,如果从存储器中取出的是数据data而不是指令 instructions ,则直接放入数据寄存器或者指定寄存器(也不属于控制器的范畴了)
来自计操的补充:
- 说 堆 特指 堆
- 说 堆栈 指的是 栈
堆栈在存储器空间中,大小和位置都是编程自定义的。
8086中堆栈必须按字操作
堆栈操作的代表性指令是
push ax
pop ax
;如果是8086的按字操作规定,目的寄存器就不能是AL
堆栈基址寄存器:sp,初始置向栈底+1(也就是栈底再向下的一个存储单元),这个位置是程序设定的。
假如执行以下操作:
push ax;第1步
push bx;第2步
第1步中,sp先-2空出一个字,然后AX分高低八位分别存入这个空字的高低存储单元。
第2步重复第1步操作。
如果要pop堆栈中的值,则是上述逆过程,先取出栈顶的值,再sp+2。
堆栈溢出:
2.3节讲解的是处理器的工作思路,或是说 “取指执行”的计算机思想。下面介绍8086CPU的内部结构(仍然符合2.3节的大致思路)。

有一个问题,地址总线20位,意味着可以寻址1MB地址空间;而CPU内部寄存器只有16位。
如何用16位寄存器存放20位的地址信息呢?
8086的设计是:讲存储器分为逻辑段,一个寄存器负责寻址段,一个寄存器负责寻址段内空间,也就是一个段内最多64KB(\(2^{16}\)byte)空间。
各种段基址寄存器以及指令寄存器就在上图BIU右上角
这里的转化的具体过程就是在上图的地址产生与总线控制单元进行的。
转化公式为:
CS:IP(CS左移4位+IP),也就是
(CS << 4) + IP
BIU右下角的指令队列充当的是2.3节的IR指令寄存器的角色,8086中有6个字节,8088中4个字节。
这是两个CPU内部结构唯一的区别。
总结,BIU负责外部存储器取出指令、取出数据,并将取出的指令放入指令队列,对应 “取指”。数据通过ALU总线直接送入EU。
总结放在前面:负责从指令队列中获取指令,对该指令译码并执行,对应“执行”。
这里可以看出,指令队列的存在,可以使得两个部分的性能都得到提升。

而外部总线在上图过程中始终处于忙状态,总线的使用率也上升。
8086内部共有14个16位寄存器:
通用寄存器 (EU左上角)
地址指针寄存器与变址寄存器
地址指针寄存器
SP:堆栈指针寄存器
BP:地址指针寄存器
2023-02-20!!!注意SP和BP的区别:ss栈段寄存器,sp栈顶指针寄存器sp会随着带有堆栈操作的指令(比如PUSH、CALL、INT、RETF)产生变化,而BP不会,所以在带参数的子过程中用BP来获取参数和访问设在堆栈里面的临时变量。
BP与BX在做地址指针时的区别:
mov BX,002H mov BP,002H mov AL,34H mov [BX],AL;1 mov [BP],AL;21处AL值默认放到了数据段的BX偏移处,2处AL值默认放到了堆栈段的BP偏移处。
如果要使它们不默认,可以将上面代码表示地址的中括号内加上它们的目的段基址寄存器如:
mov SS:[BX],AL ;此时BX表示堆栈偏移 mov DS:[BP],AL ;此时BP表示数据段偏移
变址寄存器
SI:源变址寄存器
DI:目的变址寄存器
找到的都是DS段的地址
变址寄存器中“变”的概念来自于8086对字符串的处理。
具体涉及8086指令系统中的字符串操作指令。
如将字符串搬运到存储器另一个位置,源字符串的位置需要定义在DS:SI,目的字符串的位置定义在DS:DI。
DS:SI==(DS<<4)+SI
当使用movsb或movsw(无操作数指令),自动从源字符串搬运到目的字符串。(两者的区别是按字节搬运和按字搬运)
在这个字符串操作过程中,DI和SI是在自动增加的,所以其名字中的“变”不言而喻。
当DI和SI像BP一样进行普通数据段操作时,不会自己增加。
段寄存器
8086汇编程序结构分为若干逻辑段,汇编后放到存储器的不同段。
CS:代码段基址寄存器
DS:数据段基址寄存器
ES:附加数据段基址寄存器
SS:堆栈段基址寄存器
在代码段开始时,赋值DS ES SS,使其符合自己安排的位置,而CS由操作系统安排。
所以不会出现mov CS,AX
突然感觉这个原理有点古董。
控制寄存器
IP:指令指针寄存器,相当于2.3节的程序计数器PC
代码段的偏移地址
PSW:处理器状态字寄存器,设置9个状态位。
6个状态位表达ALU运算后的程序状态。
控制标志:控制CPU的运行状态
DF方向控制,在字符串操作中,DF0,变址寄存器SI DI自增;DF1,SI DI自减
即控制SI DI的变化方向
IF中断允许标志,IF=1时,CPU可以响应可屏蔽中断请求(也就是外部中断);IF=0时,CPU不响应中断请求。
中断是操作系统中很重要的概念,开中断和闭中断的指令为
sti cli
TF陷阱标志/单步标志:TF=1时,CPU处于单步执行方式,每次执行一条指令自动执行一次特定的内部中断,具体应用就是Debug。
汇编语言中的pushF表示将PSW标志寄存器压栈,popF表示将栈顶出给PSW
地址线:A19-A16,A15-A10,A9-A0
8086给存储器编址20根地址线,IO16根地址线(A0~A15)
在早期IBM pc机中,给IO分配A9-A0地址线来寻址1KB空间,
三种格式:字节型、字型、双字型
字节型数据:
一个字节型数据对应一个地址单元。
汇编语言设计中,字节型数据定义在存储器中的DS段,具体用DB这个伪指令来定义
伪指令用于汇编器如何来翻译汇编代码。
字型数据:
对应两个相邻的地址单元。
定义伪指令为DW,如将字型数据5678H放入存储器0003H和0004H位置,则78H放在字的低地址0003H,56放在字的高地址0004H。
这里有一个对准和不对准的问题。如果字数据地址为奇地址,则称为未对准,偶地址则对准(比如上面的例子就是未对准)
对准的数据 进行 访存指令花费时间更短。未对准会多花费一个时间周期,这与数据总线的传输机制有关。
为了防止自己脑袋忘记,提示:对准情况下,高字节对应高地址,地址单元为奇,走高八位数据线(一个是线,一个是字节)
双字型数据:
对应两个字,也就是4个存储单元。
定义伪指令为DD。
在汇编语言中使用[BX /BP/ SI/ DI],是指寄存器所存的内容,也就是地址;使用BX BP SI DI—指的是寄存器本身。
为什么要分段
如何分段:
一个逻辑段最大64K,每个逻辑段的起始地址必须可以被16整除
因此理论上讲,1MB的地址空间,可以分64K(\(2^{16}\))个逻辑段,正好是16位寄存器可以描述的。
物理地址
这个上面3.1部分也提到过,要从段基址(段的起始地址)+段偏移的形式重新得到真实的物理地址。
物理地址的唯一性:
由于段相互有叠加(按照被16整除的判断标准),所以一个单元的逻辑地址只是可能不同。但是物理地址一定不同,物理地址是站在存储器全局为每个单元分配的门牌号。
虽然段在理论上(按16整除)会重叠,但实际上,汇编源程序是自己定义的各个段,操作系统分别将其装入内存,不会发生段覆盖的情况。
编程、调试都是逻辑地址
物理地址(PA)的形成
也就是上面3.1节的转化公式。
物理地址=段基址X16(16进制左移一位)+段内偏移地址(段内有效地址)。
取指令
CPU如何实现取指令?
CS:IP
即 CS(段基地址)X16+IP(段内偏移地址),取指令所存储的物理地址
接着8086按照计算后的物理地址去存储器找指令取出。
课程这里(11讲21分钟时)提到了无条件跳转,老师讲的是代码段间的无条件跳转。
据我所知,这部分比较复杂,老师估计是想强调一下cs:ip的存储器取指特性,所以具体的后续再提。
特性:CS和IP是用户不可写入的,CS是操作系统将代码从磁盘放入内存后初始化的,IP不可写入但是会改变,除了自增外还会跳转。
为了更明确说明物理地址的形成,再举一个例子,存储器写操作:
mov [bx],ax
这就是将ax中的值写入ds:bx中去,如果硬要扯一下第3部分EU BIU的知识,那就是EU先将16位地址BX沿内部数据总线传送到BIU,BIU停下取指操作,配合EU去进行写存储器的操作,BIU将BX放到加法器中产生物理地址,输出20位物理地址后放到地址线,AX值放到数据线。
如果对齐,一个时间周期完成;如果不对齐,两个时间周期。
堆栈操作(SS:SP),跟上述过程相似。
这部分跟指令系统中的寻址方式是分不开的,指令系统会在下一部分整理。
关于各种逻辑段偏移寄存器指定与不可指定的灵活性,下面是一个小总结:

这个表里总结了操作中的默认寄存器以及可以替代的寄存器,比如取指令CS必须与IP搭配,不得自己指定寄存器寻址或者段地址。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
只是想确保我理解了事情。据我目前收集到的信息,Cucumber只是一个“包装器”,或者是一种通过将事物分类为功能和步骤来组织测试的好方法,其中实际的单元测试处于步骤阶段。它允许您根据事物的工作方式组织您的测试。对吗? 最佳答案 有点。它是一种组织测试的方式,但不仅如此。它的行为就像最初的Rails集成测试一样,但更易于使用。这里最大的好处是您的session在整个Scenario中保持透明。关于Cucumber的另一件事是您(应该)从使用您的代码的浏览器或客户端的角度进行测试。如果您愿意,您可以使用步骤来构建对象和设置状态,但通常您
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc