您当前的位置:首页 > 指南 > 正文

寄存器是硬件还是软件,软件视角下的计算机组成

关于【寄存器是硬件还是软件】,今天涌涌小编给您分享一下,如果对您有所帮助别忘了关注本站哦。

内容导航:1、寄存器是硬件还是软件:技术文章:软件视角下的计算机组成:内存、寄存器、汇编语言2、寄存器是硬件还是软件,什么是寄存器

1、寄存器是硬件还是软件:技术文章:软件视角下的计算机组成:内存、寄存器、汇编语言

寄存器,是CPU里用来暂时存储数据的超高速存储单元。

写汇编语言时,大多数时间就是跟寄存器打交道。

编译器,就是个代替人类去写汇编语言的工具软件,所以编译器的大多数代码也是跟寄存器打交道。

寄存器、内存、汇编指令,是编译器后端绕不开的东西。

寄存器在不同的CPU平台上是不同的,叫的名字不一样,个数不一样,但是功能都差不多。

intel平台上,寄存器一开始是按功能来起名字的,例如:

32位的CPU只有8个寄存器,分别是:eax,ebx,ecx,edx,ebp,esp,esi,edi。

1,eax,

在16位机的时代叫ax。

到了32位机的时代给扩展到了32位,所以叫“扩展的ax”:extendedax,即eax。

其他前面带e的寄存器,也是这么来的。

它最初的目的是作为加法器,名字里的a指的是add(按英语语法该用名词)。

但实际上,eax就是个通用寄存器。

按照C语言的二进制接口(ABI),约定它同时作为函数的返回值使用。

也就是说:

int ret = write();

在汇编里如果指定ret使用eax的话,这行的赋值是不需要产生指令的(write()函数调用还是需要产生指令的)。

2,ebx,

如上面说的,它在16位时代叫bx,也是后来被扩展到32位的。

它的最初目的是作为基地址寄存器,b:base。

但实际上,eb也是个通用寄存器。

3,ecx,

它的最初目的是作为计数寄存器,c:count。

它可以作为通用寄存器,但在字符串传递、移位运算时,要作为计数器。

inta[10];

int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

for(int i = 0; i < 10; i++)

a[i] = b[i];

这种代码,如果让人去写汇编的话,可以这么写:

leaedi, 80(ebp)

leaesi, 120(rbp)

movecx, 40

rep movsb

复制10个整数,一共40字节,目的地址放在edi、源地址放在esi、字节数放在ecx。

ecx最初就是在这种指令里计量字节数用的,它现在依然保持着这个功能。

在移位运算时,如果移位的位数不是常数,也要用ecx作为计数。

例如,a <<= i,a可以放在eax里,i就要放在ecx里。

因为就算是64位机上,合理的移位数字也不超过63位,所以实际使用的只有ecx的最低8位:它有个特别的名字,cl

4,edx,

它最初的目的是作为除法的余数、或者乘法的高位。

整数除法,结果包括商和余数,商在eax里,余数在edx里。

整数乘法,结果的位数一般是乘数位数的2倍,所以低位在eax里,高位在edx里。

不是乘法除法这种场合的话,edx也可以作为通用寄存器。

在16位时代,它叫dx,跟其他的一样也是后来扩充到32位的。

除法,d:divide。

5,ebp,

凡是带p的寄存器,最初都是存储指针的寄存器。

ebp,栈底指针寄存器(栈帧寄存器),extendedbottompointer。

它属于特殊寄存器,在代码里的使用要特别小心,以防打乱了函数的调用链。

函数的汇编代码大多是这样的:

push ebp

mov ebp, esp

...

mov esp, ebp

pop ebp

ret

首先保存ebp到栈上,然后把栈顶esp保存到ebp里,作为新函数的栈底。

在整个新函数的调用期间,ebp最好不要有任何的修改,即它应该是只读的!

这样到了函数末尾,才可以用它回写esp,让函数正常返回。

6,esp,

它是栈顶寄存器,它存储的是函数栈的当前位置,即栈指针:extendedstackpointer。

esp和ebp互相配合,是CPU对函数栈的管理核心。

如果函数需要分配局部变量的话,就要把esp往低地址移动(减法),以扩大栈空间。

7,esi,edi,

这两个也是互相对应,一个做源地址寄存器,一个做目的地址寄存器,用于字符串的传递。

esi,extendedsourceindex,

edi,extendeddestinationindex。

它们两个在不是字符串传递的场合,也可以当作通用寄存器。

到了64位时代,这些寄存器全部从32位又扩展到了64位,名字改叫rax, rbx, rcx, ..., etc.

8,intel的寄存器,

0-7位(最低8位)以l结尾,al, bl, cl, dl.

8-15位以h结尾,ah, bh, ch, dh。

16位时代的寄存器只有16位,所以0-7位就是低位,lowbits;8-15位就是高位,highbits。

整个16位寄存器,以x结尾:ax, bx, cx, dx。

那4个特殊寄存器:bp, sp, si, di。

到了32位时代,又都把名字前面加上了e。

到了64位时代,又把名字前面的e改成了r。

所以,rax是64位寄存器,在汇编里:它的0-7位是al,8-15位是ah,0-15位是ax,0-31位是eax,0-63位是rax。

其他寄存器,也是这么起名字的。

所以,修改al是会影响ax, eax, rax的,但不会影响ah。

寄存器是硬件还是软件,软件视角下的计算机组成

rax的位数分布

到了64位时代,intel又添加了8个通用寄存器,r8-r15。

这次因为寄存器太多了,intel就采取了ARM的叫法,直接按数字编号了。

intel搞了好几十年的CISC,最后还是学了RISC[捂脸]

9,最后说说内存,

内存,从软件的角度看,是个巨大的一维数组。

32位的进程有0-4G的虚拟内存空间,这个数组就是:uint8_tmemory[1 << 31];

64位的进程,虚拟内存空间可以有4Gx4G的空间:uint8_t memory[1 << 63];

内存的地址(索引)是个无符号整数,它可以做加减运算。

例如,知道数组a[10]的内存地址,要找它的元素a[1]的内存地址,那么加上4个字节就行。

CPU要读写内存,就必须知道内存的地址。

这个地址在CPU读写时,该放在哪里?

只能是寄存器里,这就是汇编语言里常说的寻址方式

为什么CPU要有寻址方式?

因为它在读写内存的时候,必须得把内存地址以某个方式、放在某个位置。

A,如果内存地址直接放在寄存器里,那就是直接基地址寻址,也就是指针。

读:a = *p;

写:*p =a;

翻译成汇编,p在rdx,a在rax,就是:

读:mov rax, (rdx)

写:mov (rdx), rax

B,如果内存地址是某个已知位置的偏移量的话,就是基地址+偏移量寻址。

例如结构体里有个成员变量y,它离结构体的"首地址"有4个字节,那么:

p->y = 1 翻译成汇编就是mov 4(rdx), 1,

其中指针p放在rdx里,4是偏移量的字节数。

C,如果内存地址是数组的一个元素,因为数组元素的大小是一样的,用数组地址+元素个数*元素大小进行寻址最为方便,

这就是SIB寻址:scale, index, base。

base:数组的“首地址”。

index:元素的索引,即它是数组的第几个元素,从0开始计数。

scale:放大系数,对应着数组每个元素的大小,用C语言表示就是sizeof(array[0])。

例如:

给int型数组a的第i号元素,赋值为1,C代码就是 a[i] = 1,

如果a放在rbx里,i放在rcx里,那么汇编就是:mov (rbx, rcx, 4), 1,

其中,4是每个元素的大小。

D,

当然,要是给第i个int型元素的第2号字节赋值,还可以这么写:mov 2(rbx, rcx, 4), 1。

这种一般没有实际意义,因为它对应的C代码是:

a[i] &= ~0xff0000; // 保留其他3个字节,把第2号字节清零,

a[i] |= 0x010000; // 把清零之后的第2号字节设置为1。

要想判断出这2行代码的目的是给a[i]的第2号字节赋值为1,也太考验编译器了!

汇编的内存寻址方式,总的概括就是:

写内存:mov disp(base, index, scale), src

读内存:mov dst, disp(base, index, scale)

其中:

disp是相对于基地址的偏移量,

base是基地址,

index是位置索引,

scale是放大系数,

src是源操作数,它可以是寄存器,也可以是常数,但不能是另一个内存地址。

dst是目的操作数,它必须是寄存器。

表示内存地址的那4项(disp, base, index, scale),可以酌情省略一部分[呲牙]

最后,在windows和Linux上的汇编有点不同:

1,汇编的源操作数和目的操作数的位置是反的,

2,而且Linux上的寄存器前要加%,

3,内存寻址,windows上用中括号[],Linux上用小括号(),

我这种写法是把它们两个的风格混合的写法,属于伪代码。

你要是真写能用的汇编的话,最好查一下标准写法,免得汇编器报语法错误。

2、寄存器是硬件还是软件,什么是寄存器

与java相关的

Java编译器输出的指令流,基本上是一种基于栈的指令集架构,而与之相对的另外一套常用的指令集架构是基于寄存器的指令集。早期的android,即android4.4之前使用的JVM是Dalvik VM,就是基于寄存器架构的。基于栈的指令集主要的优点是可移植,寄存器由硬件直接提供,程序直接依赖这些硬件寄存器则不可避免地受到硬件的约束。栈架构指令集的主要缺点是执行速度相对来说会稍慢一些。所有主流物理机的指令集都是寄存器架构。

看示例找感觉

以上是一些结论,本文的重点是讨论上文中所提的寄存器,那寄存器是什么呢?其实这些计算机的原理知识之前上学的时候都学过,很遗憾当时听的也很头大,现在都还给老师了。

进入正题,先来看下维基百科的解释:

寄存器是硬件还是软件,软件视角下的计算机组成

嗯,反正我看完是没什么感觉

再来看网上的一个例子:

“现代计算机,虽然性能很高,但是和上世纪7、8十年代的计算机比,其实结构都差不多。现在讲存储,一般讲有内存和外存,内存一般有寄存器(register),缓存(cache)和内存(memory),有些小型应用例如MCU没有cache,甚至没有memory——直接从flash/ROM到register。寄存器是CPU基础单元,CPU直接处理的内存就它了,好比医院,医生对面的椅子就是寄存器,要看病的病人(data)就坐这个椅子(register);已经挂号的(data)进入诊室(cache)排队,其他的就在医院里(memory)。医生可以操作的就是面对面的病人,其他人要看病(如急病)也需先坐上这个位置,这是最快的。诊室里的座位相对于cache,一般cache都是sram存储器,速度很快,但一般cpu不会直接访问,而是要把数据挪到register后才可直接操作,而一般的内存为DRAM,速度比SRAM慢多了,而且通过总线访问,速度就更慢了。”

再看下图:计算机的存储层次(memory hierarchy)之中,寄存器(register)最快,内存其次,最慢的是硬盘。

寄存器是硬件还是软件,软件视角下的计算机组成

最后再看一个计算机的存储体系:

寄存器是硬件还是软件,软件视角下的计算机组成

图中Registers就是寄存器,怎么样,有点感觉了吗?

从头来说

假设我们做一个回向电路,把输出连回到输入,我们用OR门举例:

寄存器是硬件还是软件,软件视角下的计算机组成

首先都输入0,那么输出将会是0

寄存器是硬件还是软件,软件视角下的计算机组成

如果将A变成1,那么输出将会是1

寄存器是硬件还是软件,软件视角下的计算机组成

一转眼的功夫输出回到B,那么B为1,OR门看到的结果是输入A、B都为1,

1 OR 1 仍然为1,所以输出不变

寄存器是硬件还是软件,软件视角下的计算机组成

如果将A变成0,0 OR 1 输出仍然是 1

寄存器是硬件还是软件,软件视角下的计算机组成

现在我们有个电路能记录1,然而却有个小问题,就是无论怎么试,都无法从1变回0(如下两图)

寄存器是硬件还是软件,软件视角下的计算机组成

寄存器是硬件还是软件,软件视角下的计算机组成

现在看一个相同电路,不过这次用AND 门

寄存器是硬件还是软件,软件视角下的计算机组成

A、B均为1, 1 AND 1 为 1

寄存器是硬件还是软件,软件视角下的计算机组成

如果之后A设置为0,由于是AND门,所以输出为0,B为0

寄存器是硬件还是软件,软件视角下的计算机组成

寄存器是硬件还是软件,软件视角下的计算机组成

这个电路能记录0,和之前那个相反,无论A设置什么值,电路始终输出0

寄存器是硬件还是软件,软件视角下的计算机组成

寄存器是硬件还是软件,软件视角下的计算机组成

现在我们有了能记录0和1的电路

寄存器是硬件还是软件,软件视角下的计算机组成

为了做出有用的存储,我们将两个电路合起来,变成:AND-OR LATCH

寄存器是硬件还是软件,软件视角下的计算机组成

它有两个输入:

设置(set) 输入,将输出变成1复位(reset)输入,将输出变成0

寄存器是硬件还是软件,软件视角下的计算机组成

寄存器是硬件还是软件,软件视角下的计算机组成

如果“设置”和“复位”都是0,电路会输出最后放入的内容,也就是说它存住了1bit的信息!这就是存储。

之所以叫“LATCH(闩锁)”,是因为它“锁定”一个特定值并保持状态。将数据放入叫“写入”,将数据输出叫“读取”。好了,现在我们终于有办法存一个bit了。

麻烦的是用两条线来输入,也就是SET和RESET,有点儿麻烦,为了更易用,我们希望只有一条输入线,将它设为0或1来存储值。还需要一根线来“启用”。“启用”时允许写入,没“启用”时锁定。这条线叫“允许写入线”。加一些额外逻辑门,可以做出以下电路 :

寄存器是硬件还是软件,软件视角下的计算机组成

这个电路称为“门锁”,因为门可以打开或关上。这个电路稍微有些复杂了。

寄存器是硬件还是软件,软件视角下的计算机组成

我们不想关心单独的逻辑门,我们封装一下,把“门锁”放到盒子里(一个能存单个bit的盒子)。来看下这个新组件:

寄存器是硬件还是软件,软件视角下的计算机组成

我们来测试一下这个新组件,一切都从0开始,如果将输入从0变成1,或从1变成0,什么也不会发生,输出仍然是0 。因为WRITE ENABLE 是关闭的(0),来防止内容变化

寄存器是硬件还是软件,软件视角下的计算机组成

寄存器是硬件还是软件,软件视角下的计算机组成

所以当WRITE ENABLE输入1,打开门后可以输入1,并将1存起来,这样输出也是1了。

寄存器是硬件还是软件,软件视角下的计算机组成

我们可以关掉门(WRITE ENABLE =0),输出会保持1,此时输入随便是什么,输出都不会变(保持1)。

寄存器是硬件还是软件,软件视角下的计算机组成

如果再次打开门(WRITE ENABLE =1),如果输入为0,输出也将是0:

寄存器是硬件还是软件,软件视角下的计算机组成

最后关上门,输出会保持0

寄存器是硬件还是软件,软件视角下的计算机组成

当然存1bit没什么大用,但我们没限制只能用一个组件,如果我们并排放8个,可以存8位,比如一个8bit数字。一组这样的组件叫寄存器。寄存器能存多少个Bit,叫“位宽”。早期电脑用8位寄存器,然后是16位,32位,如今很多计算机都有64位宽的寄存器了。

CPU中寄存器又分为指令寄存器(IR)、程序计数器(PC)、地址寄存器(AR)、数据寄存器(DR)、累加寄存器(AC)、程序状态字寄存器(PSW),这里就不深入讨论了。

参考 :

http://www.ruanyifeng.com/blog/2013/10/register.html

https://www.youtube.com/watch?v=fpnE6UAfbtU

https://www.youtube.com/watch?v=cNN_tTXABUA

https://www.youtube.com/watch?time_continue=132&v=TBADs7knuWM&feature=emb_logo

本文关键词:寄存器属于内存吗,寄存器属于cpu吗,寄存器是硬件还是软件的,寄存器是储存器吗,寄存器属于什么设备。这就是关于《寄存器是硬件还是软件,软件视角下的计算机组成》的所有内容,希望对您能有所帮助!


声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,谢谢。

上一篇: 榆林滨化绿能有限公司招聘 榆林市云化绿能招聘

下一篇: 魔兽世界5.4单机(魔兽世界最完美的单机版



推荐阅读