计算机体系结构之指令体系结构


  • 💂 个人主页:风间琉璃
  • 🤟 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主
  • 💬 如果文章对你有帮助欢迎关注点赞收藏(一键三连)订阅专栏

前言

提示:这里可以添加本文要记录的大概内容:


一、指令系统结构的分类

指令集系统结构(Instruction Set Architecture ISA)最根本的区别: 在于处理器内部数据的存储类型不同。

存储类型:堆栈累加器或一组寄存器。操作数可以显式指定或者隐含指定。

​ (1)堆栈系统结构中操作数隐含地位于栈顶

​ (2)累加器系统结构中的一个隐含操作数就是累加器

​ (3)通用寄存器结构系统中只能明确地指定操作数,不是寄存器就是存储器地址

不同的指令集系统结构的示意图,箭头指示操作数是输入还是ALU运算的结果,或者既是输入也是结果。灰度较轻表示输入较重表示结果

image-20240921183454194

(a)中,栈顶寄存器(TOS)指向堆栈顶部的输入操作数,并与下面的操作数结合在一起。第一个操作数被从堆栈中删除,运算结果存放在第二个操作数的位置,同时栈顶寄存器指向运算结果。所有的操作数都是隐含的。

(b)中,累加器既是隐含的输入操作数也运算结果。

©中,其中一个操作数在寄存器中,另一个在存储器中,运算结果存放在寄存器中。

(d)中,所有的操作数都是寄存器,与堆栈结构类似,也只能通过一些单独的指令传输到存储器中:(a)中是push或pop, (d)中是load或store。

说明: 在堆栈结构和累加器结构中加法指令的操作数是隐含的,而在寄存器结构中操作数必须明确指定。

按照通用寄存器访问方式划分,有两种通用寄存器系统结构的计算机:

  • register-memory系统结构一般指令都可以访问存储器

  • register-register或 load-store系统结构只能通过load和store指令来访问内存

  • memory-memory系统结构,现实中不存在的结构,把所有的数据都保存在存储器中。

此外,有的ISA在累加器外扩展了其他寄存器,称为扩展累加器计算机

通用寄存器(GPR)出现的原因:

  • 寄存器比存储器快

  • 编译器使用寄存器很方便,比使用其他存储形式效率更高。

    例如:(AB) – (CD) –(E*F) 在寄存器系统结构的计算机上,可以按任意顺序来执行三个乘法,但是在堆栈计算机上则只有一种计算顺序,因为操作数隐含在堆栈中,且必须多次载入。

  • 寄存器用来存放变量,减少了数据流量,加速程序运行(寄存器比存储器快);改善代码密度(寄存器地址比存储器地址的位数少)。

通用寄存器ISA的两个特性:

  • ALU指令中包括两个还是三个操作数。在三个操作数格式中,指令包含一个结果(目的操作数)和两个源操作数。在两个操作数的格式中,有一个既是结果操作数也是源操作数

  • ALU指令中包括多少个存储器操作数典型的ALU指令中所支持的存储器操作数的数量可能是从0~3个不等。

    如下图所示:

    image-20240921191828061

三种常见通用寄存器计算机的优缺点

image-20240921192108094

二、存储器寻址

存储器地址表示,所有指令系统都是字节寻址的,都提供了字节(8位)、半字(16位)和字(32位)寻址,大多数的计算机还提供了双字(64位)寻址。

image-20240921193241281

小端模式&大端模式

  • 小端模式(Little-Endian):又称小端字节序,由于大多数计算机内部处理使用的是小端模式,所以也叫主机序在小端模式中,将高位字节放在高位地址,低位字节放在低位地址。

  • 大端模式(Big-Endian):又称大端字节序,由于在网络传输中一般使用的是大端模式,所以也叫网络字节序在大端模式中,将高位字节放在低位地址,低位字节放在高位地址。

数值 0x12345678,其中 0x12 这一端是高位字节,0x78 这一端是低位字节

image-20240921194349060

大端模式符合我们阅读和书写的方式,都是从左到右的。比如 12345678,我们只需要按照从左到右的顺序进行阅读和书写就是大端模式的存储顺序了。小端模式比较符合我们人类的思维模式,大的放大的那一边,小的放小的那一边。但是在计算机中存储的顺序与我们看到的顺序是相反的。

内存对齐:假设一个s字节数据的地址是A, 如果A mod s=0,访问该地址就是对齐的

为什么要有对齐限制?

  • 字或双字整数倍对齐访问存储器:简化硬件实现的复杂性

  • 一次不对齐的存储器访问:导致多次对齐存储器访问。因此,即使是在没有对齐限制的计算机里面,对齐访问的程序也会运行得比较快。

字节、字对齐对低位的特殊要求

(1)一个字节对齐(1 字节):没有对齐要求。任何地址都是对齐的,因为 1 mod 1 = 0 对所有地址都成立。低位不需要特殊要求

(2)两个字节对齐(2 字节,通常用于 short 类型):地址必须是 2 的倍数,即 A mod 2 = 0。低位需要是 0(即地址的二进制表示的最后一位必须是 0)。

(3)四个字节对齐(4 字节,通常用于 intfloat 类型):地址必须是 4 的倍数,即 A mod 4 = 0低位需要满足地址的最后两位为 0(即地址的二进制表示的末尾两位必须是 00)

(4)双字对齐(8 字节,通常用于 doublelong long 类型):地址必须是 8 的倍数,即 A mod 8 = 0低位需要满足地址的最后三位为 0(即地址的二进制表示的末尾三位必须是 000)。

寻址方式:指令中如何指定所要访问操作数的地址。寻址方式要指定常量寄存器存储器操作数的位置。

计算机中使用的所有数据寻址方式:

  • 立即数通常也被认为是一种存储器寻址方式(尽管它们要访问的数值在指令流里)。

  • 寄存器不属于存储器寻址。

  • 把依赖于程序计数器的PC相对寻址也分离出来。

image-20240921203020141

立即数寻址位移量寻址是用得最多的寻址方式。

位移量寻址方式:主要问题是位移的范围,即多长的位移量。选择位移量的长度:直接影响到指令的长度。由于变量的存储位置和存取变量方式的不同以及编译器使用的整个寻址方式的原因,位移量分布范围很广。8位~16位位移量是有必要的,如MIPS采用16位位移量

立即数寻址方式,对于立即数的取值范围与位移量相同,立即数的数值大小会影响指令的长度。8~16位立即数是有必要的。如MIPS和ALPHA采用16位立即数

立即数寻址常用于算术运算指令载入常数到寄存器指令比较指令(主要是条件转移指令)立即数寻址是支持所有操作还是只支持一部分操作对设计指令系统很重要

三、常用操作数类型

操作数的类型如何指定:

  • 操作数类型可以通过操作码的编码来指定,是最常用的方法;
  • 操作数中用硬件解释的字段表示数据类型。

常见数据类型:

image-20240921213521169

定点通常用二进制补码表示,字符通常是ASCII编码格式。

大多数指令集系统结构支持的操作:

image-20240921213850175

四、指令系统

指令系统有一条共同的规律:使用最多的是一些简单指令。一般所有的计算机都提供前三类指令。指令集对后四类指令的支持数量可能为0,也可能包含大量特殊指令。

4.1 控制流指令

控制流指令分类条件转移跳转过程调用,过程返回

控制流指令的寻址方式:==一般要指明转移的目标地址。==过程返回是例外,因为编译时不知道返回地址。PC相对寻址,即使用基于程序计数器(PC)的位移量来指定目标地址

PC相对寻址指令的优点:目标与当前指令离得不远;使用相对偏移地址可以缩减指令长度。使用相对寻址的程序可以载入到主存任何位置,称为位置无关,对在执行时才链接的程序可以减少工作量。

寄存器间接跳转:编译时不知道目标位置,为了实现返回和间接跳转,需要使用寄存器间接跳转:给出包含目标地址的寄存器名称。
寄存器间接跳转还支持:

  • 分支选择语句case或者switch
  • 面向对象语言中的虚拟函数或者方法
  • 高阶函数或者函数指针
  • 动态共享库

以上四种情况,编译时都不知道目标地址,因此通常在寄存器间接跳转之前,才把地址从存储器载入到寄存器中。

PC相对寻址转移距离:转移指令与目标之间的指令数。定点相对寻址转移位移量:至少8位。

条件转移的可选方案:

image-20240921215011650

过程调用的可选方案:有两种基本、传统的方法用来保存寄存器:调用者保存和被调用者保存。

  • 调用者保存:调用者调用其他过程时,必须保存在调用过程后还要使用的寄存器,被调用者则无须维护这些寄存器。

  • 被调用者保存:被调用的过程必须保存它要使用的寄存器,调用者则不受这种限制。

    有时候,如果两个不同的过程都要访问相同的全局变量,则必须使用调用者保存方法。大多数实际使用的编译器会结合这两种方法。

4.2 指令系统的编码

指令编码包括:操作寄存器地址寻址方式编码。指令编码将会影响编译后程序大小和处理器实现。

如何将寻址方式和操作通过编码结合到一起:

  • 每个操作数需要一个独立寻址标识符字段(显式)
  • load/store结构,一个存储器操作数,1-2种寻址方式,则寻址方式由操作编码隐含表示。

对指令编码,需要在以下因素之间找到一个最佳平衡点
1、尽可能多的寄存器和寻址方式。
2、寄存器字段、寻址方式字段尽量少,以缩短指令长度。
3、指令长度易于流水线处理。

三种常见编码方式:

image-20240921220231887

变长编码:允许所有的操作使用所有的寻址方式,适合寻址方式和操作比较多的情形。最少的位数表示程序,译码复杂,不适合流水线

定长编码把操作和寻址方式组合在操作码里,通常所有的指令长度都相同。这种方式适合于寻址方式和操作比较少的情况。译码简单,适合流水线,代码量大。

混合编码:减少过多的指令,以减轻多种结构的指令带来的工作负担,但仍提供多种指令长度以减少代码长度。

关注代码量大小,选择变长编码;关注程序的执行性能,选择定长编码;折中可以选择混合编码。

五、MIPS系统结构

image-20241206150603661

5.1 MIPS系统结构概括

  • 一种简单64位load-store系统结构

  • 固定长度指令编码,译码简单,有利于实现高效率流水线。

  • 使编译器更容易产生高效的目标代码。

5.2 MIPS64的寄存器

  • 32个64位通用寄存器(GPR),名称为R0,R1,…,R31,也称为寄存器。

  • 32个浮点寄存器(FPR),名称为F0,F1, …,F31,即可以作为32个32位单精度寄存器来使用,也可以作为32个64位双精度寄存器来使用。

  • R0的值永远是0

5.3 MIPS64的数据类型

  • 定点数据类型有8位字节、16位半字、32位字和64位双字。

  • 浮点数有32位单精度和64位双精度浮点数。

    操作面向64位定点以及32位或64位浮点数的。字节、半字或者字在调入64位寄存器中时,用零或者符号填充64位寄存器的剩余部分。

5.4 MIPS64数据传输的寻址方式

  • 16位立即数

  • 16位位移量方式(基址寻址),即操作数地址是一个存放在寄存器中的基地址与相对该基址的一个16位移量相加获得。

例如,载入字指令LW的具体使用形式如下:

LW R2, 128(R3);((R3)+128)→ R2

位移量为0—寄存器间接寻址;R0作为基址寄存器—16位绝对寻址。MIPS64存储器是用64位地址字节寻址的。

5.5 MIPS64的指令格式

由于MIPS64只有两种寻址方式,所以它们编码到操作码中。为了使机器更容易进行流水线操作和译码,所有指令都是32位的,其中6位是基本操作码。MIPS64 的指令可以分为三种主要格式:R型(Register-type)I型(Immediate-type)J型(Jump-type),每种类型都有其特定的用途指令的格式如下图。这些指令格式很简单,同时还为位移量寻址、立即数或PC相对分支地址提供了16位字段。

  • R 型指令格式(寄存器类型)

    R 型指令用于寄存器间的操作(例如加法、减法等),操作数和结果都存放在寄存器中。

image-20240922154717126

操作码:决定这是哪类指令(例如加法、减法等)。

rs 和 rt:源寄存器,提供操作数。

rd:目标寄存器,存放计算结果。

shamt:移位量,用于移位指令,其他指令时为 0。

funct:功能码,进一步指定操作类型。

  • I 型指令格式(立即数类型)

    I 型指令用于操作数中包含一个立即数,即常数值。这类指令包括加载/存储指令和条件分支指令

image-20240922155003208

操作码:指定指令类型。

rs:源寄存器,提供操作数。

rt:目标寄存器,存放结果或加载数据的目标寄存器。

offset:16 位立即数,通常用作立即数值或内存地址的偏移量(对于加载/存储指令)。需要进行符号扩展

注意和立即数进行加法运算时,需要对16位的立即数进行符号扩展为32位。

  • J 型指令格式(跳转类型)

    J 型指令用于跳转操作,即程序控制的转移。常见的 J 型指令有 J(跳转)和 JAL(跳转并链接)。

image-20240922155347015

操作码:指定这是跳转类指令。

address:目标地址的低 26 位,表示跳转到的地址,左移两位 后加到PC的高四位偏移量。 PC高4位 + (26<< 2) = 32位

5.6 MIPS操作

大致可以分为四类:载入和存储、ALU操作、分支与跳转、浮点操作。所有通用寄存器与浮点数寄存器都可以被载入或存储,唯一的例外是载入R0无效。

5.6.1 载入和存储指令

该指令只使用一种寻址方式,并且要求存储器的值必须对齐。当然,载入和存储指令对所有的数据类型都是有效的。

image-20240921222032868

符合含义:当被传送的数据长度不确切时,在符号←上附加一个下标,表示传送n位。下标用于标识字段中特定的位, 位从以0开始的最高位开始标注变量Mem用来表示主存储器(内存),按字节编址,可以传输任意字节的数据。上标用来表示对字段进行复制符号##用来链接两个字段并且可以出现在数据传送的任何一边

对于第三条指令:LW R1,60(R2),指令 LW(Load Word)从地址 60 + Regs[R2] 开始,读取 32 位数据(即 4 字节),但是R1 是一个 64 位寄存器,因此需要进行数据扩展。## 通常是表示将 32 位数据扩展到 64 位的一种符号拼接操作。

有两种常见的方式来将 32 位数据扩展到 64 位寄存器:

  • 符号扩展(Sign extension)将32位数的最高位(符号位)复制到高32位。
  • 零扩展(Zero extension)将32位数的高32位全部填充为0。
  • 如果内存中存储的32位数是 0xFFFF_FFFF,这个值的符号位为1(负数),那么符号扩展为64位后就是 0xFFFF_FFFF_FFFF_FFFF。而如果32位数是 0x0000_0001,符号扩展后就是 0x0000_0000_0000_0001

通常情况下,MIPS 指令集中的 LW 指令会进行符号扩展(Sign Extension),即如果读取的32位数是负数,扩展后的64位数也将保持负数。让我们来看看源数据的组成: ( M e m [ 60 + R e g s [ R 2 ] ] 0 ) 32 (Mem[60+Regs[R2]]_0)^{32} (Mem[60+Regs[R2]]0)32## M e m [ 60 + R e g s [ R 2 ] ] Mem[60+Regs[R2]] Mem[60+Regs[R2]]。该数据是64位的,由32位扩展数据(##前部分)和读取的内存中32数据组成(##后部分),符号位扩展的数据中下标0标识读取的32位内存数据的最高位(下标用于标识字段中特定的位, 位从以0开始的最高位开始标注),而上标用来表示对该字段进行复制,因此需要进行扩展32次最高位。然后##将两个字符进行拼接成64位数据即可。

5.6.2 ALU指令

所有的ALU指令都是寄存器-寄存器指令,包括算术和逻辑操作:加、减、与、或、异或和移位。下图给出了一些算术和逻辑指令的例子。所有这些指令都支持立即寻址方式,它带一个16位的符号扩展立即数。

image-20240921222301367

5.6.3 MIPS控制流指令

  • 比较指令,比较两个寄存器的值。如果第一个寄存器的值小于第二个的值,则比较指令将置目标寄存器为1(代表真),否则将置为0(代表假)。由于这些操作都设置寄存器,因此它们称为置等于、置不等于和置小于,等等。同时这些比较指令也具有立即数的形式。

  • 控制由一组跳转与一组分支来处理。下图给出了几个典型的分支和跳转指令。

image-20240921222347215

分支地址的计算公式(重点必考)分支的目标地址=16位带符号位移量左移2位 +(PC+4)

对应16的正数,二进制后面添两个0即可;对应负数需要扩展为32位,然后变为二进制后面补0。正数也可以先扩展。

对于BEQZ R1, name 条件分支指令,它表示如果寄存器R1 的值等于 0,则跳转到标签 name 所指示的目标地址。

分支指令的工作机制:

  • PC(程序计数器):PC是指向当前正在执行指令的地址。在执行完当前指令后,PC会指向下一条指令(PC + 4,因为 MIPS 指令是 4 字节对齐的)。

  • 16 位位移量:在 BEQZ 指令中,使用的是一个 16 位带符号的位移量,该位移量需要左移 2 位针对二进制左移),因为 MIPS 指令是 4 字节对齐的,所以分支指令的位移量单位为 4 字节(相当于乘以 4)。

  • 目标地址:分支目标地址通过当前 PC + 4 加上左移后的位移量来计算。

假设当前指令地址PC为0xF020 7200,指令中的16位带符号位移量为0x10E0(16 位带符号的位移量),计算目的地址:

(1)计算 PC + 4

MIPS64 指令是 4 字节对齐的,所以指令执行完后,PC + 4 指向下一条指令:

PC + 4 = 0 x F 0207200 + 0 x 4 = 0 x F 0207204 \text{PC} + 4 = \mathbf{0xF020 7200} + \mathbf{0x4} = \mathbf{0xF020 7204} PC+4=0xF0207200+0x4=0xF0207204

(2)位移量左移 2 位

将 16 位偏移量 0x10E0 左移 2 位得到

位移量 < < 2 = 0 x 10 E 0 < < 2 = 0 x 4380 \text{位移量} << 2 = \mathbf{0x10E0} << 2 = \mathbf{0x4380} 位移量<<2=0x10E0<<2=0x4380
0x0001_0000_1110_0000 << 2 = 0100_0011_1000_0000将偏移量转换为二进制后再进行移位操作。

(3)计算分支目标地址

PC + 4 和左移后的偏移量相加,得到分支目标地址:

分支目标地址 = ( PC + 4 ) + ( 位移量 < < 2 ) \text{分支目标地址} = (\text{PC} + 4) + (\text{位移量} << 2) 分支目标地址=(PC+4)+(位移量<<2)

分支目标地址 = 0 x F 0207204 + 0 x 4380 = 0 x F 020 B 584 \text{分支目标地址} = \mathbf{0xF020 7204} + \mathbf{0x4380} = \mathbf{0xF020 B584} 分支目标地址=0xF0207204+0x4380=0xF020B584

假设当前指令地址PC为0x00FF120C,指令中的16位带符号位移量为0x8011

(1)计算 PC + 4

PC + 4 = 0 x 00 F F 120 C + 0 x 4 = 0 x 00 F F 1210 \text{PC} + 4 = \mathbf{0x00FF120C} + \mathbf{0x4} = \mathbf{0x00FF1210} PC+4=0x00FF120C+0x4=0x00FF1210

(2)符号扩展位移量并左移 2 位

偏移量 0x8011是一个带符号的 16 位数。因为它的最高位(符号位)是 1,所以它是一个负数。我们需要先将它符号扩展为 32 位,再左移 2 位。

  • 0x8011 二进制:1000 0000 0001 0001。符号扩展为 32 位后变成:0xFFFF 8011

  • 然后左移 2 位: 1111 1111 1111 1111 1000 0000 0001 0001 << 2= 1111 1111 1111 1110 0000 0000 0100 0100 = 0xFFFE 0044

(3)计算分支目标地址

分支目标地址 = ( PC + 4 ) + ( 位移量 < < 2 ) \text{分支目标地址} = (\text{PC} + 4) + (\text{位移量} << 2) 分支目标地址=(PC+4)+(位移量<<2)
分支目标地址 = 0 x 00 F 1210 + 0 x F F F E 0044 = 0 x 00 F D 1254 \text{分支目标地址} = \mathbf{0x00F1210} + \mathbf{0xFFFE0044} = \mathbf{0x00FD1254} 分支目标地址=0x00F1210+0xFFFE0044=0x00FD1254

==这个计算时需要扩展为32位后才进行计算:==存储指令,意思是s2存储的值是0x032F 4032,存放的地址为 0x0F02 3010 + 0xFFFF 80F0=0x0F01 B100地址

image-20241011204051182

正位移量:位移量为正数时,分支目标地址位于当前指令之后。

负位移量:位移量为负数时,分支目标地址位于当前指令之前。

image-20240922130907744

5.6.4 MIPS的浮点操作

浮点指令对浮点数寄存器进行操作,并指出将被使用的操作数是单精度(SP)还是双精度(DP)。

  • MOV.S和MOV.D分别把一个单/双精度浮点数寄存器的值复制到另一个同类型的寄存器中。

  • MFC1,MTC1,DMFC1和DMTC1在一个单精度或双精度浮点数寄存器和一个定点寄存器之间传送数据。

浮点操作:加、减、乘、除。后缀S表示单精度浮点数,而后缀D表示双精度浮点数。为提高图形处理性能,MIPS64提供了在一个64位浮点数寄存器两半部分中分别进行两个32位浮点数的操作。

谬误和易犯的错误

  • 设计一种“高级”指令系统特性就意味着要支持一种高级语言结构。

  • 存在一种典型的程序, 可以用它来设计一个理想的指令系统。

  • 可以不考虑编译器而改进指令系统以缩减代码大小。

  • 有缺陷的系统结构不可能是一种成功的系统结构。

  • 可以设计一个没有缺陷的系统结构。

结束语

感谢阅读吾之文章,今已至此次旅程之终站 🛬。

吾望斯文献能供尔以宝贵之信息与知识也 🎉。

学习者之途,若藏于天际之星辰🍥,吾等皆当努力熠熠生辉,持续前行。

然而,如若斯文献有益于尔,何不以三连为礼?点赞、留言、收藏 - 此等皆以证尔对作者之支持与鼓励也 💞。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Super.Bear

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

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

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

打赏作者

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

抵扣说明:

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

余额充值