02计算机组成原理-计算机硬件的操作及操作数
以下是我们这一章大概要学的内容:
通过之前的学习,我们大概知道,指令就是用来控制计算机大致做什么操作的计算机能做的操作大部分都是一些运算的操作比如说一些加减乘除,一些逻辑运算。那既然要进行运算操作,那就得有一些数据参与进来进行操作,所以在我们讲指令格式之前,先把指令能够操作的操作数先给大家讲一下,比如说指令参与某一个操作的一些数据哪来的,逻辑运算用哪些运算,算术运算用哪些,小数怎么表示,正负数怎么表示,"指令格式"前面就是指令中的操作数的有关内容怎么处理字符。这一章除了理解指令还要理解存储程序的思想。
1.指令
机器指令(简称指令):指示计算机执行某种操作的命令,计算机语言中的基本单词。
一台计算机的所有指令的集合构成该机的指令系统,也称指令集。
指令集系统总的来说可以分为两类,一部分是复杂指令集系统一部分是精简指令集系统。先简单介绍一下这两种。后面会详细讲
复杂指令集系统:类似打补丁,来一个新功能就给它专门写一个指令这样指令就越来越多,越来越复杂。
精简指令集系统:相比于复杂指令集系统,会觉得它太多了,就通过一些简单的指令来代替复杂的指令,比如乘法操作,就用简单的加法操作代替。
指令集的两种形式: 一种是人们编程书写的形式(汇编语言-助记符),另一种是计算机所能识别的形式(机器语言-二进制位) 。
指令集有很多种:MIPS;Intel x86;ARM系统:ARMv7,ARMv8; RISC-V...
本课程以 MIPS架构的指令集为例。
2.存储程序的思想
存储程序:必须将事先编好的程序和原始数据送入主存后才能执行程序,一旦程序被启动执行,计算机能在不需操作人员干预下自动完成逐条取出指令并执行的任务。
存储程序是1945年 冯. 诺伊曼提出的,"存储程序(stored-program)通用电子计算机方案",宣告了现代计算机结构思想的诞生。
硬件设计的三条基本原则:
1.简单源于规整:这意味着设计应该尽可能地简单,以便于理解和维护。这通常通过保持设计的规整性来实现,例如通过保持指令长度的统一,可以简化处理器的设计和编程。
2.越小越快:在硬件设计中,减小组件的尺寸可以提高其运行速度。这是因为当信号传输的距离变短时,传输时间也会减少,从而提高了整体性能。
3.优秀的设计需要折中的方案:在实际的硬件设计中,往往需要在不同的设计要求之间做出权衡。例如,为了提高性能,可能需要增加功耗或牺牲一部分能效。因此,设计师需要找到一个能够满足所有关键要求的最佳折中方案。
这些不用背,后面遇到类似的设计思想会给大家提到。
3.计算机硬件的操作
刚刚讲了我们是通过指令去控制计算机进行操作的,计算机最基本的操作就是要能够执行算术运算,算术运算的操作就是加减乘除,而算术运算中最基本的操作就是加法。
以加法为例,MIPS 汇编语言的下述记法:
add a . b. c
表示将两个变量 b和c相加,并将它们的和放入变量a中。
**这种表达的方式是固定的,每一条指令只用来执行一个操作。**与加法类似的指令一般都有三个操作数:两个进行运算的数和一个保存结果的数。要求每条指令有且仅有三个操作数。体现了:简单源于规整。
思考四个数相加怎么算?例如b+c+d+e放到a中?
->调用三次add指令:
add a b c
add a a d
add a d e
要完成这样的加法操作,b和c这样的数据是从哪来的呢?我们编程的时候是定义变量来进行计算的,那这些变量我们在计组里称为操作数。
操作数:与高级语言程序不同, MIPS 算术运算指令的操作数是很严格的,它们必须来自寄存器。
寄存器:集成在CPU上由硬件直接构建且数量有限,是计算机硬件设计的基本元素。MIPS 体系结构中寄存器大小为 32 位,称其为字。它所存储的数据都是32位的数据,即4个字节。(1个字节是8位,即8个0或1)
字:计算机中的基本访问单位,通常是 32 位为一组,在 MIPS 体系结构中与寄存器大小相同。MIPS按字节编址,一个字对应4个字节。
寄存器的数量是有限的。越小越快。大量的寄存器可能会使时钟周期变长,因为电信号传输更远的距离必然花费更长的时间。对于这32个寄存器,我们用0~~31来表示。尽管可以简单使用序号0~31 表示相应的寄存器,但MIPS 约定书写指令时用一个符""后面跟两个字符来代表一个寄存器:S0。
思考:复杂数据结构中的数据元素可能远多于计算机中寄存器的个数,计算机怎样来表示和访问这样大的结构呢?
-->只能将少量数据保存在寄存器中,但存储器可以存储数十亿的数据元素。因此,数据结构是存放在存储器中的。
寄存器组里面只能存放少量的数据,大多数数据是存放在存储器中的,当来了一个运算指令,需要算术逻辑单元去运算,那这个算术逻辑单元就需要一些操作数,他就回去寄存器组里去找操作数,,如果寄存器组里面没有算术逻辑单元要的操作数,比如说需要x,y,但是这个x,y是存放在存储器里面的并没有存放在寄存器组里面,我们就需要把x和y从存储器中都存放到寄存器中。然后算术逻辑单元就去寄存器中去取相应的数据,运算完后把数据返给寄存器中。结合下图理解。

通过上述描述,显然我们还需要知道从存储器中取出数据放到寄存器组中的指令,也就是我们所说的取数指令。
MIPS 的算术运算指令只对寄存器进行操作,因此,MIPS 必须包含在存储器和寄存器之间传送数据的指令。数据传输时传输的一个数据就是一个32位的字,这些指令叫作数据传送指令。
为了访问存储器中的一个字,指令必须给出存储器地址。将数据从存储器复制到寄存器的数据传送指令通常叫取数 (load) 指令 。MIPS取数指令助记符是lw。也就是load word的缩写:
基本语法:lw **目标寄存器, 偏移量(基址寄存器)**基址寄存器是用存放基础地址是在哪的,MIPS给出地址的方式是给出基址寄存器和偏移量的方式给出的。
lw t0, 100(s1):把s1寄存器中的数据取出来后往后增加100个字节的位置得到要取出的数据在存储器中的位置,然后把这个位置的数据取出来后送到$这个寄存器中
如果我们给一个寄存器外面加上了一个(),那么就代表这个这个寄存器中的数据。
和取数相对应的就是存数(sw) (store word):
基本语法:sw 源寄存器,偏移量(目的寄存器)
sw s1, 4(s2):s2寄存器里面存的内存字节地址取出来,往跳4个字节得到目标内存起始地址,然后把是s1里的32位字数据写到这个目标地址开始的连续 4 个字节的内存空间里。这个4我们在汇编里叫立即数,即不需要去寄存器或某个存储器里面去找。指令集如何去处理这些立即数的,我们等会再给大家讲

两者对比:

3.地址
我们C语言常说的指针指向的地址,这个地址其实就是内存地址,在内存中我们怎样找到我们想要的某一份数据呢,和我们进入小区看门牌号确定朋友的家庭住址一样,我们给内存也遍一个身份信息,我们就叫它地址,那怎么遍地址呢?一般我们是按照字节编址,这样的话是1 个字节(8 位)对应 1 个唯一的地址(地址是编号,比如 0、1、2、3,不是位数;字节是存储单位,8 位,是地址对应的 "存储格子");通俗说:地址是门牌号(数字),字节是门牌号对应的房间(8 位空间),不是 "8 位的门牌号"。有的可能是字编址,这样的话就是32位一个地址(按字编址时,字是存储单位,32 位,1 个地址对应这个 32 位的 "大格子");补充:408 中,字长默认 32 位(MIPS32),所以按字编址就是 1 地址 = 32 位,若考 64 位机则是 1 地址 = 64 位,题目会明确说明。地址其实也是一个数据,也可以做操作数参与指令的操作
按字节编址:0(1111 1110),1(1001 1000)...像0地址里面的8位就是属于0地址的,0过了就是1,按相同的道理编址,这种就叫按字节编址。
问地址1GB,按字节编址,内存应该是从0到几?
->1G是210M,1M是210K,1K是210B(字节),所以共有230个字节,所以是0到210-1,为了方便表示,我们一般用十六进制来表示书写地址,即0x...,这就是所谓的编址。
MIPS按字节编址,一个地址空间存放一个字节。
例如,一个字的起始地址是0x1000(但字的地址跟这个起始地址不一定一样,后面讲),那这个字包含的四个字节的地址分别是:
第一个字节:0x1000
第二个字节:0x1001
第三个字节:0x1002
第四个字节:0x1003
每个字都占据4个连续的字节位置。连续两个字在内存中的地址会相差4,字 的起始地址必须是 4 的倍数。
这叫对齐限制 。这种对齐方式确保了CPU能够有效地从内存中读取和写入数据,且能加快数据传输。
小注:
寄存器的数量相对于程序可能需要存储的变量数量而言通常是非常有限的。
将最常用的变量保存在寄存器中可以显著提高程序执行效率。
寄存器的数量相对于程序可能需要存储的变量数量而言通常是非常有限的。
将最常用的变量保存在寄存器中可以显著提高程序执行效率。-->加速大概率事件
当一个变量不再频繁使用或者当前需要用到的变量太多,而寄存器资源不足时,编译器会选择将某个寄存器中的变量"溢出"到内存中存储,这个过程称为寄存器溢出。
现代编译器还会采用各种优化技术,如寄存器重用、局部优化、全局优化等策略,以最大程度地利用有限的寄存器资源,提高程序性能。
4.寻址
有了编址,编写地址,也就要有寻址。也就是寻找地址。首先,既然编址按字来,那么寻址也是按字来。有两种类型的字节寻址的计算机:大端和小端。
大端(big end) 字节的地址作为字地址;小端 (little end) 字节的地址作为字地址。

以上图为例大端小端的区别在于,字的起始地址一定是0x1000,关键在于,你从里面取出来的地址如果是0x12就说明是大端存储,如果是0x78就说明是小端存储。
5.特殊操作数
程序中经常会在某个操作中使用到常数------例如,将数组的下标加 1 。这个常数是在编译成汇编语言的时候就确定的。从已介绍过的指令看,如果要使用常数必须先将其从存储器中取出。为了提高性能并减少能耗,我们会有专门设计的指令来处理常数操作数:MIPS 架构的 addi 指令(加立即数)。
基本语法:addi 目标寄存器 源寄存器 立即数
addi s3, s3, 4:大白话就是把s3原寄存器里的数据加上4放回s3
注:MIPS 架构中有一个特殊的寄存器,名为 zero (编号为 0),它在硬件层面被永久设置为 0。这个寄存器的存在使得程序员在需要将某个寄存器清零或者将 0 赋值给其他寄存器时,可以直接使用zero 寄存器作为源操作数,从而简化指令和提高代码效率。
将寄存器 t1 清零:addi t1, zero, zero
给t1赋值成15: addi t1, zero, 15
常数操作数出现频率高,而且相对于从存储器中取常数,包含常数的算术运算指令执行速度快很多,并且能耗较低。 根据使用频率来确定要定义的常数是加速大概率事件的一个例子。
大概先写这些吧,今天的博客就先写到这,谢谢您的观看。