微机原理

微机原理问题汇总

1、8086在最小模式下,第28引脚M/IO。当该引脚输出高电平时,表明CPU要警醒存储器的读写操,这个时候是地址总线上出现访问存储器的地址;输出低电平时,进行IO端口读写操作,这时候是低位地址总线上出现的是I/O端口地址
???为啥一个直接是地址总线,另一个要强调低位地址总线呢

这个问题明白了
因为8086采用的是独立编址方式,存储器和I/O端口编址是分开进行的,8086采用低16位对I/O端口进行编址,最多有65535个8位的I/O端口,两个编号相邻的8位端口可以组合成一个16位端口。指令系统中既有访问8位地址端口的输入输出指令,也有访问16位端口的输入输出指令。

2、lock信号是由指令前缀lock产生,在有lock前缀的指令执行中lock信号有效,执行完毕后,便撤销lock信号。lock信号有效时,表示CPU不希望系统中其他总线部件占用系统总线。
???然后书上有这样一句话“当一条指令有多个总线周期,在执行时不希望这些总线周期要连续完成时使用前缀lock”并没有理解这句话是什么意思

虽然还是没明白但是有一个总线锁的文章,好像有一丝感觉
原文🔗:
原文:https://blog.csdn.net/qq_35642036/article/details/82801708
随着多核时代的到来,并发操作已经成了很正常的现象,操作系统必须要有一些机制和原语,以保证某些基本操作的原子性,比如处理器需要保证读一个字节或写一个字节是原子的,那么它是如何实现的呢?有两种机制:总线锁定和缓存一致性。

   我们知道,CPU和物理内存之间的通信速度远慢于CPU的处理速度,所以CPU有自己的内部缓存,根据一些规则将内存中的数据读取到内部缓存中来,以加快频繁读取的速度。我们假设在一台PC上只有一个CPU和一份内部缓存,那么所有进程和线程看到的数都是缓存里的数,不会存在问题;但现在服务器通常是多 CPU,更普遍的是,每块CPU里有多个内核,而每个内核都维护了自己的缓存,那么这时候多线程并发就会存在缓存不一致性,这会导致严重问题。

   以 i++为例,i的初始值是0.那么在开始每块缓存都存储了i的值0,当第一块内核做i++的时候,其缓存中的值变成了1,即使马上回写到主内存,那么在回写之后第二块内核缓存中的i值依然是0,其执行i++,回写到内存就会覆盖第一块内核的操作,使得最终的结果是1,而不是预期中的2.

   那么怎么解决整个问题呢?操作系统提供了总线锁定的机制。前端总线(也叫CPU总线)是所有CPU与芯片组连接的主干道,负责CPU与外界所有部件的通信,包括高速缓存、内存、北桥,其控制总线向各个部件发送控制信号、通过地址总线发送地址信号指定其要访问的部件、通过数据总线双向传输。在CPU1要做 i++操作的时候,其在总线上发出一个LOCK#信号,其他处理器就不能操作缓存了该共享变量内存地址的缓存,也就是阻塞了其他CPU,使该处理器可以独享此共享内存。

    但我们只需要对此共享变量的操作是原子就可以了,而总线锁定把CPU和内存的通信给锁住了,使得在锁定期间,其他处理器不能操作其他内存地址的数据,从而开销较大,所以后来的CPU都提供了缓存一致性机制,Intel的奔腾486之后就提供了这种优化。

缓存一致性:缓存一致性机制就整体来说,是当某块CPU对缓存中的数据进行操作了之后,就通知其他CPU放弃储存在它们内部的缓存,或者从主内存中重新读取,用MESI阐述原理如下:

MESI协议:是以缓存行(缓存的基本数据单位,在Intel的CPU上一般是64字节)的几个状态来命名的(全名是Modified、Exclusive、 Share or Invalid)。该协议要求在每个缓存行上维护两个状态位,使得每个数据单位可能处于M、E、S和I这四种状态之一,各种状态含义如下:

   M:被修改的。处于这一状态的数据,只在本CPU中有缓存数据,而其他CPU中没有。同时其状态相对于内存中的值来说,是已经被修改的,且没有更新到内存中。
    E:独占的。处于这一状态的数据,只有在本CPU中有缓存,且其数据没有修改,即与内存中一致。
    S:共享的。处于这一状态的数据在多个CPU中都有缓存,且与内存一致。
    I:无效的。本CPU中的这份缓存已经无效。

 一个处于M状态的缓存行,必须时刻监听所有试图读取该缓存行对应的主存地址的操作,如果监听到,则必须在此操作执行前把其缓存行中的数据写回CPU。
    一个处于S状态的缓存行,必须时刻监听使该缓存行无效或者独享该缓存行的请求,如果监听到,则必须把其缓存行状态设置为I。
    一个处于E状态的缓存行,必须时刻监听其他试图读取该缓存行对应的主存地址的操作,如果监听到,则必须把其缓存行状态设置为S。

   当CPU需要读取数据时,如果其缓存行的状态是I的,则需要从内存中读取,并把自己状态变成S,如果不是I,则可以直接读取缓存中的值,但在此之前,必须要等待其他CPU的监听结果,如其他CPU也有该数据的缓存且状态是M,则需要等待其把缓存更新到内存之后,再读取。

   当CPU需要写数据时,只有在其缓存行是M或者E的时候才能执行,否则需要发出特殊的RFO指令(Read Or Ownership,这是一种总线事务),通知其他CPU置缓存无效(I),这种情况下性能开销是相对较大的。在写入完成后,修改其缓存状态为M。

   所以如果一个变量在某段时间只被一个线程频繁地修改,则使用其内部缓存就完全可以办到,不涉及到总线事务,如果缓存一会被这个CPU独占、一会被那个CPU 独占,这时才会不断产生RFO指令影响到并发性能。这里说的缓存频繁被独占并不是指线程越多越容易触发,而是这里的CPU协调机制,这有点类似于有时多线程并不一定提高效率,原因是线程挂起、调度的开销比执行任务的开销还要大,这里的多CPU也是一样,如果在CPU间调度不合理,也会形成RFO指令的开销比任务开销还要大。当然,这不是编程者需要考虑的事,操作系统会有相应的内存地址的相关判断

   并非所有情况都会使用缓存一致性的,如被操作的数据不能被缓存在CPU内部或操作数据跨越多个缓存行(状态无法标识),则处理器会调用总线锁定;另外当CPU不支持缓存锁定时,自然也只能用总线锁定了,比如说奔腾486以及更老的CPU。

???另外,在8086的两个中断响应脉冲之间,lock信号也自动变为有效,以防止其他总线部件在中断响应过程中占有总线。那整个过程结束之后lock信号也是自动成无效的嘛?

关于指令前缀的问题

(1)指令编码(硬编码)的结构
在这里插入图片描述

怎么判断是不是前缀指令呢? 前缀指令就几个,很好确定,根据指令的内容来确定

(2)前缀指令是分组的:

前缀指令最多是4个,每组一个

<1>LOCK 和REPEAT前缀指令:
LOCK F0
//锁地址总线的 在同一时刻只能有一个核的CPU来读取那条指令,这个指令在多核下才有意义
REPNE/REPNZ F2 //重复执行 当zf是0的时候执行
REP/REPZ F3 //重复执行 当zf是1的时候执行
<2>段前缀指令:
CS(2E)、SS(36)、DS(3E)、ES(26)、FS(64)、GS(65)
//存在的意义是可以改变寻址时候的段寄存器
<3>操作数宽度前缀指令:
66 //改变操作数的宽度的,如果是32位+66->16位,如果是16位+66->32位
<4>地址宽度前缀指令:
67 //改变寻址方式的 ,这个前缀指令也是双向的
(3)前缀指令最多占4个字节,最少占0个字节

每组最多一个,可以组合使用,没有顺序问题

3、最小模式的总线读周期和写周期的地址输出和数据输出中间读数据的时候有一个高阻态为下一步做准备,写周期却没有,难道和cpu与外设的数据传输方向有关?

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值