★PART1:32位的x86处理器执行方式和架构

1. 寄存器的拓展(IA-32)

从80386开始,处理器内的寄存器从16位拓展到32位,命名其实就是在前面加上e(Extend)就好了,8个通用寄存器被命名为EAX,EBX,ECX,EDX,ESI,EDI,ESP和EBP,同样的,操作的时候必须要和寄存器的长匹配,比如下面的操作就是错的。

   

32位通用寄存器的高16位不可以单独使用,但是他们的低16位依然可以按照8086的使用方法一样使用。处理器在32位保护模式下可以使用全部的32条地址线,访问4GB内存。同时,EIP变成了32位的,当然在实模式下也可以只使用实模式下的16位。标志寄存器FLAGS也拓展到16位,其前各个16位和16位模式下各个标志一样。

在32位模式下对内存的访问理论上是不需要分段的,但是IA-32也是基于分段模型的,当然也可以只分一个段,基地址是0x00000000,段的长度是4GB,在这种情况下,可以视为不分段,也就是平坦模式(Flat Mode)。

在32位模式下,处理器要求在加载程序的时候,先定义该程序拥有的段,然后允许使用这些段,定义段的时候,除了基地址(起始地址)外,还附加了段界限,特权级别,类型等属性。当程序访问一个段时候处理器将用固件实施各种检查工作,以防对内存的违规访问,如图,32位模式下,传统的段位寄存器,如CS,SS,DS,ES,保存的不再是16位的段基地址,而是段的选择子(选择要访问的段,段的定义在GDT或者LDT上),除了段选择子,每个段寄存器还包括了一个不可见的部分,称位描述符高速缓存器,里面有段的基地址和各种访问属性,这部分内容程序不可访问,由处理器自动使用,另外32位模式还多加了两个段位寄存器FS和GS。

  

2. x86的32位处理器的基本工作模式

       ①:16位保护模式(80286)

80286是一款16位的处理器,在实模式下和8086一样,只能使用最大为64KB的段,虽然他有24根地址线,理论上可以访问224的内存(16MB),但是还是只能分成多个段来访问。但是80286访问内存的时候,不需将段地址左移,因为在段寄存器的描述符高速缓存中有24位的段物理基地址,这样一来,段可以位于16MB内存空间中的任何位置,而不再限于1MB的范围内,也不必非得对齐16字节,但是80286的通用寄存器是16位的,只能提供16位的偏移地址,所以和8086一样,即使运行在16位保护模式下,段的长度也不能超过64KB。

②:32位保护模式(80836和以后的x86 32位处理器)

80386处理器的寄存器是32位的,而且拥有32根地址线,可以访问232,即4GB的内存,80386以及后续的所有32位处理器,都有兼容模式,可以运行实模式下的8086,且刚加电的时候,这些处理器都自动处于实模式下,可以运行8086的程序,这个时候它相当于一个非常快的8086处理器,在实模式下经过一定的设定就可以进入保护模式。32位保护模式下,段的基地址是32位的,偏移地址也是32位的。32位保护模式兼容80286的16位保护模式。

3. 线性地址(Liner Address)

       IA-32处理器编程,需要在程序中给出段地址和偏移地址,因为分段是IA-32的基本特征之一,传统上,段地址和偏移地址称为逻辑地址,偏移地址被叫做有效地址(Effective Address,EA),在指令中给出有效的地址叫做寻址方式(Addressing Mode),比如:

 

段的管理是由处理器的段部件负责产生的,段部件将段地址和偏移地址相加,得到访问内存的地址。一般来说,段部件产生的地址就是物理地址。IA-32处理器支持多任务,在多任务环境下,任务的创建需要分配内存,当任务终止后,还要回收他所占用的内存。在分段模型下,内存的分配是不定长的,所以IA-32处理器支分页功能,分页功能将物理内存空间划分成逻辑空间上的页,页的大小是固定的,一般为4KB,通过使用页,可以简化内存管理。(只有开启了页功能才能使用页),当页功能开启后,段部件产生的地址就不再是物理地址了,而是线性地址,线性地址还要经页部件转换后,才是物理地址。

线性地址的概念用来描述任务的地址空间,IA-32处理器上的每个任务都拥有4GB的虚拟内存空间,这是一段长4GB的平坦空间,就像一段平直的线段,因此叫线性地址空间,相应的,由段部件产生的地址,就对应着线性地址空间上的每一个点,这就是线性地址(也就是线性地址是段部件的一个对应,是物理地址的一个映射)。

4. 流水线(Pipe-Line)

在8086时期,处理器已经有了指令预取队列,当指令执行时,如果总线总是空闲的(没有访问内存的操作),就可以在指令执行的同时预取指令并提前译码,这种做法可以大大地提升程序的执行速度。(原理就是利用处理器的不同指令大多不会再一个时钟周期内完成)。可以把一个指令分解成若干个细小的步骤,并分配给相应的段元来完成。每个单元的执行时独立的,并行的。这么做以后,每个步骤的执行就会在时间上重叠起来,这种执行指令的方法就是流水线技术。根据贪婪算法,流水线的执行效率受执行时间最长的那一级的限制,要缩短各级的执行时间。如果要缩短各级的执行时间,那么就要让每一级的任务减少,与此同时,就需要把一些复杂的任务再进行分解,如此,在2000年的时候Intel推出的Pentium处理器(采用NetBurst微结构,进一步分解指令的执行过程,采用31级超深流水线)。

5. 高速缓存(Cache)

因为与处理器的寄存器相比,内存的访问速度(几十ns)和硬盘的访问速度(几十ms)都非常低慢,所以人们就弄了一个高速缓存的机制,高速缓存说白了就是一个存储器(也是一个静态存储器,容量较小,但速度可以与处理器匹配。),当然这只是简单来说的,事实上高速缓存的实现是很复杂的,里面有很多计算的原理,不同CPU的实现还可能不一样,高速缓存利用了程序运行的时候,总是局部性的(比如访问刚刚访问过的指令或者数据,这被称为程序运行的局部性规律。)每当处理器要访问内存,首先检索高速缓存。如果要访问的内容已经在高速缓存中了,那么直接从高速缓存中获得,这被称为命中(Hit);否则,称为不中(Miss),在不中的情况下,处理器灾区的需要的内容前必须重新装载高速缓存,而不只是直接到内存中去哪个内容,高速缓存的装载是以块为单位的,包括那个所需数据的邻近的内容,为此需要额外的时间来等待块从内存载入高速缓存,在这个过程中损失的时间称为不中惩罚(miss penalty)。

6. 乱序执行(Out-Of-Order Executive)

为了执行流水线技术,需要降至零拆分成更小的可独立执行部分,即拆分成微操作(micro operations),简写为μops。

有些简单指令只用一个微操作,比如:

有些指令可以拆分成两个微操作,一个从内存中读取数据并保存到临时寄存器,另一个用于将EAX寄存器和临时寄存器的数值相加。

再比如:

这个可以拆分成三个微操作一个从内存中读数据,一个执行相加的动作,第三个用于将相加的结果写回到内存中。一旦将指令拆分成为操作,处理器就可以在必要的时候乱序执行,比如:

这里,指令mov [mem2],eax可以拆分成两个微操作,如此,在执行逻辑左移指令的同时,处理器可以提前从内存中读取mem2的内容,典型的,如果数据不在高速缓存中,那么处理器在获取mem1的内容之后,会立即开始获取mem2的内容,于是同时,shl指令已经开始执行了。同理,乱序执行可以大大加快如push,call等指令的执行速度。

7. 寄存器重命名

书上有一个例子:

代码上做了两件事情,一个是将mem1的内容进行左移3个单位,另一个是将mem3的内容+2,如果将后面三个操作所用的寄存器名名称不同的名字,那么这个操作也不会被影响,所以处理器为最后三条指令使用了另一个不同的临时寄存器,因此左移和加法可以并行地进行。再比如:

假定现在mem1的内容在高速缓存中,可以立即取得,但mem2的内容不在高速缓存中,也就是说,算术左移可以在add之前就进行了,所以我们为左移设定一个新的临时寄存器,那么这样eax的内容认识以前的,他将一直保存着这个值,直到ebx的内容就绪,然后和它一同做加法运算。如果没有寄存器重命名机制,左移操作将不得不等待从内从中读取mem2的内容到EBX寄存器中以及加法操作。

在所有操作都完成后,那个代表EAX寄存器的最终结果的临时寄存器的内容被写入真实的EAX寄存中,该处理过程被称为引退(Retirement)。所有通用寄存器,栈指针,标志,浮点寄存器,甚至段寄存器都有可能被重命名。

8. 分支目标预测

如果遇到转移指令,那么后面那些进入流水线的指令将会无效,所以我们要清空流水线,那么为了解决这个问题,Intel引入了分支预测技术,因为程序中可能出现大量的循环,所以遇到转移指令(条件转移指令,loop等),处理器将会预测他下一次还会转移到某个标号处而不是往下执行,在处理器内部,有一个小容量的高速缓存器,叫做分支目标缓存器(Branch Target Buffer,BTB)。当处理器执行了一条分支语句后,它会在BTB中记录当前指令的地址,分支目标的地址,以及本次分支预测的结果,下一次,在转移指令实际执行前,处理器会查看BTB,看看有没有最近转移的记录,如果能找到对应的条目,则推测和上一次相同的分支,把改分支的指令送入流水线。如果预测失败,再清空流水线,刷新BTB。

★PART2:32位的x86系统的指令系统

1. 32位处理器的寻址方式

如果处理器在16位模式下,没有指令前缀0x66,则认为指令是传统的16位寻址方式,如果有指令前缀0x66,则是32位寻址方式,在32位模式下,没有指令前缀0x66,则认为指令是传统的32位寻址方式,如果有指令前缀0x66,则是16位寻址方式。指令默认使用32位宽度的寄存器和32位的立即数,如果存在内存寻址,则偏移量也是32位的。

32位模式下,内存寻址可以使用全部的32位通用寄存器作为基址寄存器,还可以加上一个除了ESP的32位通用寄存器作为变址寄存器,变址寄存器还可以允许乘以1,2,4和8作为比例因子。最后还可以在加上一个8位或者32位的偏移量。比如

2. 操纵数大小的指令前缀

每一条指令都可以拥有前缀,比如重复前缀(rep/repe/repne)、超越前缀指令(如ES:),总线封锁前缀(LOCK)等。前缀是可选得,每个前缀的长度是1个字节,每个指令都可以拥有0-4个前缀。

16位模式下的编码格式和32位的编码格式是一样的,但是解释是不同的,所以编写的时候就要考虑指令的运行环境,为了指明程序的默认运行环境,编译器提供了伪指令bits,用于指明其后的指令应该被编译成16位的,还是32位的(16位模式是默认的编译模式,如果没头指定指令的编译模式,则默认是16bits的)。

3. 一般指令的拓展

32位处理器拥有32位寄存器和算术逻辑部件。而且系统内存芯片之间的数据通路至少是32位的,所有寄存器或者内存单元为操作数的指令都被扩充,这些拓展操作即使是在16位模式下(实模式或者保护模式)都是可以用的,比如最简单的加法指令。

压栈出栈的操作比较特殊。

压入一个字节立即数,则无论是在16位模式下或者是32位模式下,一定要使用byte,关键字byte在push和pop操作上是不会给机器码加上指令前缀的,但是执行的时候,无论什么时候,push(pop)都不会压入(弹出)一个字节的数据,在16为模式下,这两个指令使用SP指针,按照有符号数的规则填充到字节的高八位,然后压栈(弹出),32位使用ESP,按照有符号数的规则填充到高24位再压栈(弹出)。

如果要压入一个字立即数,则无论是在16位模式下或者是32位模式下,一定要使用前缀word,在16位模式下,执行push操作,SP先-2,然后直接压入该字;在32位模式下,会填充字的高16位(按照有符号数的规则),ESP相应-4,然后压入双字,pop操作类似。

如果要压入一个双字立即数,则无论是在16位模式下或者是32位模式下,一定要使用dword,而且栈指针寄存器(SP或者ESP)都要-4。pop类似。

(压入(弹出)通用寄存器可以不用关键字byte,word,dword修饰,内存单元一定要关键字byte,word,dword修饰,处理器压入内存操作行为和压入立即数的行为是一样的)。

压入段寄存器的时候,在16位模式下,先将SP的内容-2,然后直接压入;如果是在32位模式下,则会先将段寄存器的内容用0拓展到32位(高16位全是0),然后,将ESP的内容减去4,然后再压入拓展后的32位的值。(段寄存器能用的只有16位)。

转载于:https://www.cnblogs.com/Philip-Tell-Truth/p/5204154.html

ASM:《X86汇编语言-从实模式到保护模式》第10章:32位x86处理器的编程架构相关推荐

  1. 10、32位 x86处理器编程架构

    10.1.IA-32架构的基本执行环境 10.1.1.寄存器的扩展 8个通用寄存器的扩展:(AX.BX.CX.DX) 16位 -> 32位 (EAX.EBX.ECX.EDX)(SI.DI.BP. ...

  2. 李忠 X86汇编语言 从实模式到保护模式-初学

    学习资料: 教学视频 网易云课堂 哔哩哔哩 原书网站 原书相关源码附件下载 网友帖子 除了后面没有图片之外很不错的笔记总结,写者很用心 留存待看,一片文章写了特点 很有特色总结的笔记 学习目标: 15 ...

  3. x86汇编语言从实模式百度云_x86汇编语言:从实模式到保护模式

    x86汇编语言:从实模式到保护模式2013年1月由电子工业出版社出版发行,总共6000行的源代码,全方位地向读者展现汇编语言程序设计之美.尽管汇编语言也是一种计算机语言,但却是与众不同的,与它的同类们 ...

  4. 硬盘和显卡的访问与控制(一)——《x86汇编语言:从实模式到保护模式》读书笔记01

    本文是<x86汇编语言:从实模式到保护模式>(电子工业出版社)的读书实验笔记. 这篇文章我们先不分析代码,而是说一下在Bochs环境下如何看到实验结果. 需要的源码文件 第一个文件是加载程 ...

  5. 16位模式/32位模式下PUSH指令探究——《x86汇编语言:从实模式到保护模式》读书笔记16...

    一.Intel 32 位处理器的工作模式 如上图所示,Intel 32 位处理器有3种工作模式. (1)实模式:工作方式相当于一个8086 (2)保护模式:提供支持多任务环境的工作方式,建立保护机制 ...

  6. 任务切换——《x86汇编语言:从实模式到保护模式》读书笔记38

    任务切换--<x86汇编语言:从实模式到保护模式>读书笔记38 本文及后面的几篇博文是原书第15章的学习笔记. 本章依然使用第13章的主引导程序. 1. 协同式多任务与抢占式多任务 有两种 ...

  7. 任务和特权级保护(五)——《x86汇编语言:从实模式到保护模式》读书笔记36

    任务和特权级保护(五)--<x86汇编语言:从实模式到保护模式>读书笔记36 修改后的代码,有需要的朋友可以去下载(c14_new文件夹).下载地址是: GitHub: https://g ...

  8. 任务和特权级保护(四)——《x86汇编语言:从实模式到保护模式》读书笔记35

    任务和特权级保护(四)--<x86汇编语言:从实模式到保护模式>读书笔记35 7. 正式进入用户程序的局部空间 67 mov ebx,message_1 68 call far [fs:P ...

  9. 程序的加载和执行(六)——《x86汇编语言:从实模式到保护模式》读书笔记26

    程序的加载和执行(六)--<x86汇编语言:从实模式到保护模式>读书笔记26 通过本文能学到什么? NASM的条件汇编 用NASM编译的时候,通过命令行选项定义宏 Makefile的条件语 ...

最新文章

  1. Android新版NDK环境配置(免Cygwin)
  2. springboot整合mybatis和mybatis-plus
  3. SystemCenter2012SP1实践(16)私有云的第一个模板
  4. 专科 java转go 翱翔之路(二)基础语法:匿名组合,方法,接口,map,json,异常处理,channel管道,select用法
  5. 计算机程序的思维逻辑 (12) - 函数调用的基本原理
  6. Windows下搭建Scala开发环境
  7. coredump gdb 调试_Linux下如何使用gdb调试core文件
  8. PostgreSQL 数据库检测到 ShareLock 死锁的处理方法
  9. 【NIPS 2017】基于深度强化学习的想象力增强智能体
  10. WPF 重定向DLL stdout
  11. ORACLE中如何查找定位表最后DML操作的时间小结
  12. 计算机技能高考带什么文具,高考必备——21条考场抓分细节
  13. c语言车牌识别原理,解析车牌识别技术,融合多种算法的原理和过程
  14. wifi打印服务器方案USB共享打印机模块参考设计
  15. linux 汇编 preserve8,ARM汇编伪指令
  16. 百度语音合成模型Deep Voice3
  17. 史上最详细的ConcurrentHashMap详解--源码分析
  18. 如何找到3DMax消失的命令面板?
  19. GHNN调试运行部分报错解决
  20. 使用 UI Flow 从O365管理界面下载报告时遇到的问题和解决办法

热门文章

  1. [翻译] WPAttributedMarkup
  2. How To Open An URL In Android’s Web Browser
  3. 使用Windows命令行启动服务
  4. 如何准确估算并发数?
  5. linux cp使用注意事项
  6. C中printf函数的实现原理
  7. leetcode算法题--最长公共前缀
  8. c语言对空指针memcpy,C语言memcpy 断错误
  9. mysql如何查看事务日记_MySQL日志查看详解
  10. 1.7. FreeBSD 初始化设置