实习成长之路:操作系统——CPU有哪些工作模式呢?

本博客极客时间-操作系统实战45讲笔记
感兴趣移步

引入

在这里插入图片描述

硬件中最重要的就是 CPU,它就是执行程序的核心部件。而我们常用的电脑就是 x86 平台,所以我们要对 x86 CPU 有一些基本的了解

按照 CPU 功能升级迭代的顺序,CPU 的工作模式有实模式、保护模式、长模式,这几种工作模式下 CPU 执行程序的方式截然不同,下面我们一起来探讨这几种工作模式。

从一段死循环的代码说起

int main()
{
    int* addr = (int*)0;
    cli(); //关中断
    while(1)
    {
        *addr = 0;
        addr++;
    }
    return 0;
}

上述代码首先关掉了 CPU 中断,让 CPU 停止响应中断信号然后进入死循环,最后从内存 0 地址开始写入 0。你马上就会想到,这段代码只做了两件事:一是锁住了 CPU,二是清空了内存,你也许会觉得如果这样的代码能正常运行,那简直太可怕了。

如果是在实模式下,这样的代码确实是能正常运行。因为在很久以前,计算机资源太少,内存太小,都是单道程序执行,程序大多是由专业人员编写调试好了,才能预约到一个时间去上机运行,没有现代操作系统的概念。

实模式

定义

实模式又称实地址模式,实,即真实,这个真实分为两个方面,一个方面是运行真实的指令,对指令的动作不作区分,直接执行指令的真实功能,另一方面是发往内存的地址是真实的,对任何地址不加限制地发往内存

想要搞懂实模式,就要先知道实模式寄存器

实模式寄存器

由于 CPU 是根据指令完成相应的功能,举个例子:ADD AX,CX;这条指令完成加法操作,AX、CX 为 ADD 指令的操作数,可以理解为 ADD 函数的两个参数,其功能就是把 AX、CX 中的数据相加。

指令的操作数,可以是寄存器、内存地址、常数,其实通常情况下是寄存器,AX、CX 就是 x86 CPU 中的寄存器。

下面我们就去看看 x86 CPU 在实模式下的寄存器。表中每个寄存器都是 16 位的。

在这里插入图片描述

实模式下访问内存

虽然有了寄存器,但是数据和指令都是存放在内存中的。通常情况下,需要把数据装载进寄存器中才能操作,还要有获取指令的动作,这些都要访问内存才行,而我们知道访问内存靠的是地址值

那问题来了,这个值(我理解的就是内存的地址值)是如何计算的呢?计算过程如下图。

在这里插入图片描述
结合上图可以发现,所有的内存地址都是由段寄存器左移 4 位(这样,16位寄存器可以访问20位的地址空间了),再加上一个通用寄存器中的值或者常数形成地址,然后由这个地址去访问内存。这就是大名鼎鼎的分段内存管理模型

只不过这里要特别注意的是,代码段是由 CS 和 IP 确定的,而栈段是由 SS 和 SP 段确定的

这意味着只要分配不同的值给这四个寄存器(CS IP SS SP),就可以分配不同的运行地址空间给不同的程序。

下面我们写一个 DOS 下的 Hello World 应用程序,这是一个工作在实模式下的汇编代码程序,一共 16 位,具体代码如下:

data SEGMENT ;定义一个数据段存放Hello World!
    hello  DB 'Hello World!$' ;注意要以$结束
data ENDS
code SEGMENT ;定义一个代码段存放程序指令
    ASSUME CS:CODE,DS:DATA ;告诉汇编程序,DS指向数据段,CS指向代码段
start:
    MOV AX,data  ;将data段首地址赋值给AX                
    MOV DS,AX    ;将AX赋值给DS,使DS指向data段
    LEA DX,hello ;使DX指向hello首地址
    MOV AH,09h   ;给AH设置参数09H,AH是AX高8位,AL是AX低8位,其它类似
    INT 21h      ;执行DOS中断输出DS指向的DX指向的字符串hello
    MOV AX,4C00h ;给AX设置参数4C00h
    INT 21h      ;调用4C00h号功能,结束程序
code ENDS
END start

上述代码中的结构模型,也是符合 CPU 实模式下分段内存管理模式的,它们被汇编器转换成二进制数据后,也是以段的形式存在的。

代码中的注释已经很明确了,你应该很容易就能理解,大多数是操作寄存器,其中 LEA 是取地址指令,MOV 是数据传输指令,就是 INT 中断你可能还不太明白,下面我们就来研究它。

实模式中断

中断即中止执行当前程序,转而跳转到另一个特定的地址上,去运行特定的代码。在实模式下它的实现过程是先保存 CS 和 IP 寄存器,然后装载新的 CS 和 IP 寄存器,那么中断是如何产生的呢?

注:IP 是指令指针寄存器,它只和CS一起使用,而且只有处理器才能直接改变它的内容。当一段代码开始执行时,CS指向代码段的起始地址,IP指向段内偏移。这样CS和IP形成了逻辑地址,由总线接口部件变换成物理地址来取得指令。处理器会自动根据当前指令的长度改变IP值,使它指向下一条指令。

第一种情况是,中断控制器给 CPU 发送了一个电子信号,CPU 会对这个信号作出应答。随后中断控制器会将中断号发送给 CPU,这是硬件中断

硬件中断,是通过两根信号线引入处理器的。一根是intr(interrupt require)负责可屏蔽中断,一根nmi(nonmaskable interrupt)负责不可屏蔽中断。对于不可屏蔽中断,处理器接收就放弃正常工作也不修复。对于可屏蔽中断,intel处理器允许有256个中断,中断号0~255。中断控制器由两个8259a芯片级联,可管理15个中断信号。对于如何屏蔽中断和不屏蔽,由8259a芯片和处理器共同作用。8259a芯片内部有一个8位中断屏蔽寄存器,对应芯片的8个输入引脚,0允许,1表示屏蔽。除了芯片还要看cpu内部标志寄存器中IF位,为0,所有来自intr中的中断都被忽略,为1正常接收和处理。

第二种情况就是 CPU 执行了 INT 指令,这个指令后面会跟随一个常数,这个常数即是软中断号。这种情况是软件中断。

你也可以这么理解:由外设,比如键盘,或者内部时钟产生的中断,被称为硬中断; 由 int 指令产生的中断,被称为软中断。

无论是硬件中断还是软件中断,都是 CPU 响应外部事件的一种方式。

为了实现中断,就需要在内存中放一个中断向量表,这个表的地址和长度由 CPU 的特定寄存器 IDTR 指向。实模式下,表中的一个条目由代码段地址和段内偏移组成,如下图所示。

在这里插入图片描述
有了中断号以后,CPU 就能根据 IDTR 寄存器中的信息,计算出中断向量中的条目,进而装载 CS(装入代码段基地址)、IP(装入代码段内偏移)寄存器,最终响应中断。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会写代码的花城

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值