【计算机组成原理】2.2.6 数据的存储和排列

2.2.6 数据的存储和排列

00:01

各位同学大家好,在这个小节中我们要探讨的是数据的存储和排列的问题。好,首先来看一个之前提到过的问题,叫做大小端模式。我们在内存里经常会存储某一些多字节的数据,比如说C语言里的int型变量,在很多时候是占四个字节,这儿我们用16进制的方式把四个字节的内容给描述出来,最左边这个部分我们可以把分为最高有效字节,然后最右边67我们可以把它称为最低有效字节。英文缩写也要注意,分别是MSB和LSB。

00:40

好,如果把这个四字节的int型变量大家可以试一下,把它翻译为十进制的话,应该对应的是这样的一个数,这样的一个正整数。而如果把这个16进制数翻译成二进制的形式,那么就应该是下面这样的内容。总共有32个比特,四个字节。好,之前我们说过对于这种多字节的数据,它在内存里边一定是占据连续的几个字节的,那根据这些字节在内存里的排列方式不同,我们可以有两种存储这种多字节数据的方式,一种叫大端,一种叫小端方式。那大端方式的存储会更符合我们人类阅读的习惯。

01:23

这儿我们上面给的0800H0801H这些指的是内存地址,所以左边是内存的低地址部分到右边是内存的高地址部分,因此所谓的大端模式就是把最高的有效字节把它存到更低地址的部分,然后最低有效字节是存在了最高的这个地址部分。整个int型变量占据连续的四个字节,那这是大端存储的方式。那小端方式就是把它逆过来,就是在低地址的部分存储最低有效字节,在高地址的部分存储最高有效字节,是逆过来存储的那小端方式显然不太符合我们阅读的习惯,我们要阅读这个四字节数据的时候,得把它逆过来拼凑。

02:13

虽然小段方式不方便让我们阅读,但是它更方便让机器进行处理。因为我们的机器在处理这种多字节数据的时候,通常也是按照这种内存地址递增的次序,来读取这个多字节数据里边的这些每一个字节或者每一个字。是的,也就是说机器在读取这四个字节的int型变量的时候,如果它每次只能读取一个字节的话,那么它先读入的一定是低地址部分的这一个字节。那如果用大端方式的话,就相当于先把最高有效字节给读入,然后一直往后到最后才读入最低有效字节。而如果是小端模式,就意味着它会先读入这个最低有效字节,然后慢慢地读入最高有效字节。

这么做是有好处的,比如如果我们的CPU它每一次只能处理八位二进制的一个加法运算。那么当CPU对两个int型变量进行加法操作的时候,显然应该先从它的最低有效字节先进行加法,然后再加次低位的这个字节。所以如果使用小端方式来存储的话,那计算机首先从内存里读入的就是最初最应该先被处理的这个字节。所以小端存储的方式会更便于机器的处理。好,这是大端方式和小端方式的一个区别。

03:40

好,接下来再探讨一个问题,叫做边界对齐的存储方式。现代的计算机通常是按照字节编址,所谓按字节编址就是指每一个字节会对应一个地址。如果结合下面这个图的话,第一个字节我们可以把它编制内存地址,对应的是零。然后第二个字节对应的内存地址是一,第三个对应的是2,然后第四个对应的是三。在这个图里边除了字节之外,大家还会发现半字和字这样的一种描述方式。假设这个计算机它的存储字长为32位,那么一个字就是32个比特位,然后一个半字就是16个比特。

04:22

现代计算机虽然是按照字节编制,但是通常来说也可以支持按字或者按半字来进行寻址的操作。什么意思呢?比如说一条指令,它可以指明我要访问的是内存里地址编号为四的这个字节,那么由于我要寻找的是一个字节,所以最终找到的应该是这儿我们画出的这个字节,这个字节的编号刚好为4。好,那这是按字节寻址。

04:53

那什么叫按半字寻址?比如我同样可以指定我这次要访问的是编号为三的那个半字。那么由于一个半字是16个比特,所以最开始的两个字节组成了零号半字。然后接下来的这两个字节组成了一号半字,然后再往后的这两个字节组成了二号半字,接下来的两个字节又组成了编号为三的半字。所以如果我要按半字寻址,我指明了我要访问的是三号字,那么就意味着接下来我要读入的,我要访问的就是这两个字节的内容,这是按半字寻址。

05:35

按字寻址也是类似的原理。由于每个字占32个比特,也就是四个字节,所以这儿我们画的一整行四个字节组成了一个字,因此我可以指明我这次要访问的是二号字。那么这是零号字,这是一号字,这是二号字,所以要访问二号字就意味着我要把这四个字节的内容给读入。好,所以这就是所谓按字按半字和按字节寻址的意思。

06:05

大家会发现这儿我们一个半字对应两个字节,一个字对应四个字节。所以当我们给出我们要访问的字地址的时候,要怎么把它转换成与之对应的字节地址呢?很简单,我们只需要把字地址逻辑左移两位就可以。因为逻辑左移一位意味着乘以2,逻辑左移两位意味着乘以4对吧?所以像刚才这个例子当中,第一个字节我们把编号设为0,然后接下来第二行的第一个字节编号应该是4,然后再往后的这个字节编号应该是8,接下来这个字节编号应该是12,这是每一行的第一个字节的一个字节地址。

06:48

好,现在我要访问编号为二的那个字,也就是要访问第三行的这一整个字。那我们要把这个字地址转换成用字节描述的地址,很简单,二号字它用二进制表示的话应该是10,对吧?我们把它逻辑左移两位,就相当于在末尾又添了两个零,那这个二进制翻译过来就应该是8。所以二号字的起始地址就是八号字节这个位置从八号字节开始读出连续的四个字节,这就是二号字的内容。

07:24

半字的原理也是一样,我们给出半字地址之后,想把它转换成字节的地址,只需要逻辑左移一位,也就是在末尾添一个零就可以。好,那这是按字、按半字,还有按字节寻址的意思,现代计算机都是按字节编址的,也就是说无论我们要访问的是字半字还是字节,最终肯定需要转换成相对应的字节地址。转换方法就是逻辑左移。这我们还需要强调一个事情,我们每次访存只能读写一个字的内容,并且这儿所谓的一个字就是我们这儿的一整行,不能跨行读取。所以基于这种特性,有的计算机会采取数据边界对齐的方式,也就是我们上边这个图的这种方式。也有的计算机会采用边界不对齐的方式,也就是下面这种方式。

08:19

来举个例子,在C语言里边char型变量刚好占一个字节,然后short型的变量刚好占两个字节,int型的变量占四个字节。如果我定义了一个结构体,这个结构体里边包含了三个char型的变量,然后三个short型的变量,还有一个int型的变量。那如果按边界对齐的方式,我们在存储了刚开始的三个char型变量之后,最开始的这一个字还会剩下一个字节的空间,但是接下来我们要存储的short型变量,它必须占一个半字,也就是两个字节。所以如果采用的是边界不对齐的方式,那么我们可以把这个short型的变量第一个字节就放在这一个字的末尾这个地方,然后short型变量的第二个字节把它放到第二个字最开始的这个地方。

好,基于之前我们提到的读写,就是访存相关的那个特性。我们可以知道如果按照这种边界不对齐的方式来存储的话,那就意味着当我们要读出这个short型变量的时候,下边这种方案我们必须进行两次访存。因为第一次访存我们读入的是最上面这一整个字的内容,而第二次访存我们才读入第二个字的内容。只有把这两个字的内容都读入,然后把最末尾的这字节和最开头的这个字节进行一个拼接,我们才可以得到short型变量的一个完整的表示。

09:52

而如果采用上边这种边界对齐的方式来存储的话,最后这儿我们只剩一个字节,存不下这个半字的数据,那我们就会干脆把这一个字节给浪费掉。虽然说空间上能会有一些浪费,但是当我们要读入这个short型变量的时候,只需要进行一次访存就可以。因为这个变量的所有数据都是存放在这一整个字里边的。好,所以这就是边界对齐方式和边界不对齐方式的一个对比。

显然边界对齐方式它是一种空间换时间的一种策略,虽然我们会浪费某一些空间,但是浪费这些存储空间可以换来更快的这种访存的效率。所以边界对齐的这种存储策略也是值得的。好的,由于这个小节只有两页PPT,我们就不再进行专门的总结了。那以上就是这个小节的全部内容。

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值