热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

CPU工作模式:执行程序的三种模式

1)CPU的工作模式有哪三种?实模式、保护模式、长模式2)如果下面这段应用程序代码能够成功运行,会有什么后果? ​ intmain() {   int*addr(i

1)CPU 的工作模式有哪三种?



  • 实模式、保护模式、长模式



2)如果下面这段应用程序代码能够成功运行,会有什么后果?

 
 int main()
 {
     int* addr = (int*)0;
     cli(); //关中断,什么信号来都不能终止CPU
     while(1)
    {
         *addr = 0;
         addr++;
    }
     return 0;
 }


  • 在实模式下,这段代码确实能运行。



3)什么是实模式?



  • 实模式又称实地址模式,实,即真实,这个真实分为两个方面



  • 一是运行真实的指令,对指令的动作不作区分,指令让干什么就老老实实干什么。另一方面是发往内存的地址是真实的,对任何地址不加限制地发往内存。



4)实模式下的寄存器有哪些?

 

 

 

5)实模式下访问内存需要获取地址值,这个值是如何计算的呢?

 

 

 

 

6)分段内存管理模型是什么样的?



  • 所有的内存地址都是由段寄存器左移 4 位,再加上一个通用寄存器中的值或者常数形成地址,然后由这个地址去访问内存



7)代码段由哪两个寄存器确定?



  • CS 和 IP



8)栈段由哪两个寄存器确定?



  • SS 和 SP



9)分析下面代码?

 
 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


  • LEA 是取地址指令,MOV 是数据传输指令



10)什么是中断?



  • 停下当前手头上干的事,转而跳转到另一个特定的地址上,去运行特定的代码。



11)在实模式下中断是如何实现的?



  • 先保存 CS 和 IP 寄存器,然后装载新的 CS 和 IP 寄存器。



12)中断是如何产生的呢?



  • 第一种情况:中断控制器问CPU在吗,CPU回答在的。随后中断控制器会将中断号发送给 CPU,这是硬件中断。



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



13)内存对我们的中断提供了哪些支持?



  • 内存中有中断向量表。地址和长度由 CPU 的特定寄存器 IDTR 指向。



  • 实模式下,表中的一个条目由代码段地址和段内偏移组成。

     

     



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

14)什么是保护模式?



  • 因为CPU在实模式下容易出错,所以有了保护模式。



15)保护模式相比于实模式有哪些变化?



  • 增加了一些控制寄存器和段寄存器,扩展通用寄存器的位宽,所有的通用寄存器都是 32 位的,还可以单独使用低 16 位,这个低 16 位又可以拆分成两个 8 位寄存器,如下表。

     

     



16)R0到R3谁大?



  • R0 拥有最大权力,可以访问低特权级的资源,反之则不行。



 

 



  • 上面的圆环图,从外到内,既能体现权力的大小,又能体现各特权级对资源控制访问的多少,还能体现各特权级之间的包含关系。R0 拥有最大权力,可以访问低特权级的资源,反之则不行。



17)什么是保护模式段描述符?



  • 由于 CPU 的扩展导致了 32 位的段基地址和段内偏移,还有一些其它信息,所以 16 位的段寄存器肯定放不下。多出来的这部分就放内存,打包成段描述符。

     

     



18)内存中多个段描述符叫什么?



  • 全局段描述符表



  • 该表的基地址和长度由 CPU 和 GDTR 寄存器指示。

     

     

     



19)有了段描述符之后是怎么访问内存的?



  • 段寄存器中不再存放段基地址,而是具体段描述符的索引,访问一个内存地址时,段寄存器中的索引首先会结合 GDTR 寄存器找到内存中的段描述符,再根据其中的段信息判断能不能访问成功。



20)CS、DS、ES、SS、FS、GS 这些段寄存器,里面存放的就是一个内存段的描述符索引吗?



  • 由影子寄存器、段描述符索引、描述符表索引、权限级别组成

     

     



20.1)影子寄存器是什么?



  • 靠硬件来操作的,对系统程序员不可见,是硬件为了减少性能损耗而设计的一个段描述符的高速缓存,不然每次内存访问都要去内存中查表,那性能损失是巨大的,影子寄存器也正好是 64 位,里面存放了 8 字节段描述符数据。



21)什么是保护模式平坦模型?



  • 内存分段的话有很多缺点,现代操作系统都是用分页。但是X86CPU并不能直接使用分页模型,而是在分段模型的基础上,根据需要决定是否要开启分页,这是硬件的规定,我们无法改变。但是我们可以通过设计来把分段变为一种虚设。这个就叫保护模式的平坦模型。



22)回过头去看看我们前面的Hello OS中段描述符表长什么样?

 
 GDT_START:
 knull_dsc: dq 0
 ;第一个段描述符CPU硬件规定必须为0
 kcode_dsc: dq 0x00cf9e000000ffff
 ;段基地址=0,段长度=0xfffff
 ;G=1,D/B=1,L=0,AVL=0
 ;P=1,DPL=0,S=1
 ;T=1,C=1,R=1,A=0
 kdata_dsc: dq 0x00cf92000000ffff
 ;段基地址=0,段长度=0xfffff
 ;G=1,D/B=1,L=0,AVL=0
 ;P=1,DPL=0,S=1
 ;T=0,C=0,R=1,A=0
 GDT_END:
 
 GDT_PTR:
 GDTLEN  dw GDT_END-GDT_START-1
 GDTBASE  dd GDT_START


  • 上面代码中注释已经很明白了,段长度需要和 G 位配合,若 G 位为 1 则段长度等于 0xfffff 个 4KB。上面段描述符的 DPL=0,这说明需要最高权限即 CPL=0 才能访问。



 

23)保护模式下中断是怎样处理的?



  • 保护模式下的中断要权限检查,还有特权级的切换,所以就需要扩展中断向量表的信息,即每个中断用一个中断门描述符来表示,也可以简称为中断门,中断门描述符依然有自己的格式,如下图所示。

     

     



  • 同样的,保护模式要实现中断,也必须在内存中有一个中断向量表,同样是由 IDTR 寄存器指向,只不过中断向量表中的条目变成了中断门描述符

     

     



24)保护模式下cpu收到中断后,会采取哪些措施?



  • 检查中断号是否大于最后一个中断门描述符(0-255),然后检查描述符类型(是否是中断门或者陷阱门),是否为系统描述符,是不是存在于内存中。



  • 接着,检查中断门描述符中的段选择子指向的段描述符。



  • 最后做权限检查,如果 CPL 小于等于中断门的 DPL,并且 CPL 大于等于中断门中的段选择子所指向的段描述符的 DPL,就指向段描述符的 DPL。



25)我们的CPU默认是实模式的,那怎样进入保护模式?



  • 第一步,准备全局段描述符表,代码如下。

     
     GDT_START:
     knull_dsc: dq 0
     kcode_dsc: dq 0x00cf9e000000ffff
     kdata_dsc: dq 0x00cf92000000ffff
     GDT_END:
     GDT_PTR:
     GDTLEN dw GDT_END-GDT_START-1
     GDTBASE dd GDT_START


  • 第二步,加载设置 GDTR 寄存器,使之指向全局段描述符表。

     
     lgdt [GDT_PTR]


  • 第三步,设置 CR0 寄存器,开启保护模式。

     
     ;开启 PE
     mov eax, cr0
     bts eax, 0                     ; CR0.PE =1
     mov cr0, eax        


  • 第四步,进行长跳转,加载 CS 段寄存器,即段选择子。

     
     jmp dword 0x8 :_32bits_mode ;_32bits_mode为32位代码标号即段偏移


26)为什么要进行长跳转?



  • 我们无法直接或间接 mov 一个数据到 CS 寄存器中,因为刚刚开启保护模式时,CS 的影子寄存器还是实模式下的值,所以需要告诉 CPU 加载新的段信息。



27)什么是长模式?



  • 使 CPU 在现有的基础上有了 64 位的处理能力



28)长模式相比于保护模式有什么变化?



  • 增加了一些通用寄存器,并扩展通用寄存器的位宽,所有的通用寄存器都是 64 位,还可以单独使用低 32 位。



  • 这个低 32 位可以拆分成一个低 16 位寄存器,低 16 位又可以拆分成两个 8 位寄存器

     

     



29)长模式下段描述的格式是什么样的?

 

 

 

 

 
 ex64_GDT:
 null_dsc: dq 0
 ;第一个段描述符CPU硬件规定必须为0
 c64_dsc:dq 0x0020980000000000 ;64位代码段
 ;无效位填0
 ;D/B=0,L=1,AVL=0
 ;P=1,DPL=0,S=1
 ;T=1,C=0,R=0,A=0
 d64_dsc:dq 0x0000920000000000 ;64位数据段
 ;无效位填0
 ;P=1,DPL=0,S=1
 ;T=0,C/E=0,R/W=1,A=0
 eGdtLen   equ $ - null_dsc ;GDT长度
 eGdtPtr:dw eGdtLen - 1 ;GDT界限
      dq ex64_GDT

 



推荐阅读
  • 本文为Codeforces 1294A题目的解析,主要讨论了Collecting Coins整除+不整除问题。文章详细介绍了题目的背景和要求,并给出了解题思路和代码实现。同时提供了在线测评地址和相关参考链接。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • Commit1ced2a7433ea8937a1b260ea65d708f32ca7c95eintroduceda+Clonetraitboundtom ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • Python如何调用类里面的方法
    本文介绍了在Python中调用同一个类中的方法需要加上self参数,并且规范写法要求每个函数的第一个参数都为self。同时还介绍了如何调用另一个类中的方法。详细内容请阅读剩余部分。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
author-avatar
liyanyl_499
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有