内存寄存器如何用于保存不同类型?

时间:2012-02-15 02:47:29

标签: memory assembly memory-management cpu-registers

我的印象是,如果程序为变量类型整数(大小为8字节)保留内存,则保留的内存将是8个不同的寄存器,这些寄存器按顺序出现在内存中。

我的问题如下:

1)假设答案会有所不同,我的陈述是一个很好的概括,即不同类型的变量所需的每个字节在内存中使用1个寄存器等于该变量? (即1个字节需要内存中的一个寄存器)

2)如果这是真的,每个寄存器在内存中保持多少位?或者如果我买了一台32位计算机,那是否意味着内存中的每个寄存器都有32位?

3)如果整数类型需要8个不同的寄存器,其大小为8个字节,那么每个不同的寄存器中包含什么?

4)我也试图理解类型的概念。我知道如果你有32位可以使用,你可以表示从0到4294967295的无符号整数值。但是如果我将无符号整数 4294967295存储在32的存储单元格中-bits如何知道CPU需要将此存储单元中的二进制表示解码为无符号整数格式?也就是说,为特定类型预留的内存是指定某种类型还是指针指定类型或者可能是完全不同的东西?

我通常对二进制算术,汇编语言,引用,指针以及变量和数组如何存储在内存堆中的知识有所了解(所以我将理解使用这些上下文的任何答案)。我可以用C,C ++和Java编程。感谢您提供任何帮助。

2 个答案:

答案 0 :(得分:2)

1,2,3:不要将存储器称为寄存器;虽然我已经看到它在混乱之前完成了。 64位处理器有8字节宽的寄存器,32位处理器有4字节宽的寄存器,但是当这些寄存器被复制到RAM中时,它只是内存中的字节。整数的哪一部分存储在哪个字节取决于处理器的字节顺序:little-endian系统将1字节存储在0x1中,位于8字节的第一个(最低)地址中,而big-endian系统将存储它在最后。

4:CPU不知道也不关心; “types”是一种高级语言结构,对CPU来说一切都是数字:“abcd”是一个数字,因为0xf0f0f0f0是一个数字。你必须根据你的意愿给它指示,例如对于x86,如果您希望将数字视为已签名,则使用IDIV而不是DIV。

答案 1 :(得分:2)

为了编程语言的利益,类型在很大程度上是虚构的。对于处理器位是位,除了在执行单个指令期间有时短暂地没有意义,在该指令结束时失去其含义。

Dijkstra:“计算机科学不再是关于计算机而是天文学与望远镜有关。”

您需要指定您对问题感兴趣的处理器,或者您是否对处理器感兴趣。今天常见的处理器组合从8位寄存器到64位或更大的处理器不等,所有处理器都有8位,16位,32位,64位寄存器。

也不要对寄存器中的所有内容感到困惑,有些处理器有很多寄存器,高级代码中的很多项都会在寄存器中停留一段时间,而其他处理器没有很多寄存器和大多数变量住在公羊而不是登记册。更常见的是,即使寄存器长时间保存该数据,也会有一些变量用于变量。优化器确实很糟糕,但很难做出一般性陈述。

你说你知道汇编语言,以这种汇编语言伪代码为例:

mov r1,#0x20000000
shl r2,r0,5
add r1,r2
ldr r0,[r1]

这类似于你可能会看到的如果你有一个32字节大小的结构数组,并且你想得到第一个元素,比如它是一个单精度浮点数。并且你想要从寄存器r0中保存的数组中的元素编号中浮动,我们不关心该元素编号是什么,代码可以根据它进行操作。

struct 
{
  float f;
  stuff...32 bits total
} mystruct[MYSTRUCTSIZE];
...
unsigned int i;
...
something=mystruct[i].f
...

上面的程序集伪代码计算mystruct [i] .f地址并从内存加载它以放入或使用某些代码。

我们可能碰巧知道的0x20000000位是内存中存在这个结构数组的地址,但是现在,对于mov指令,它只是位,我们正在加载到寄存器中的立即值。通常mov指令不会影响标志,因此除了进入寄存器的一些位之外,它对cpu没有任何有符号或无符号或任何含义。假设该伪代码的32位寄存器和地址空间

如上所述,r0将索引保存到结构数组中,所以我们乘以32,左移指令并不关心这是一个索引,或者5的移位与结构有关,它只是位进入alu导致位移出一侧,零移位到另一侧。有些cpus将最后一位移入进位位,而不是作为进位位,而是作为级联移位的占位符,同样可以计算zflag和n标志(符号位)以防万一你认为这是一个二进制补码(转移后),或者想要编程中的一些快捷方式。但那些只是cpu的位,没有任何意义。

此时我们人们认为r2为结构数组中的索引保留了内存的偏移量,但是对于cpu只是位。我们执行添加。我们认为一个操作数是一个地址,另一个操作数是一个偏移量,但对于cpu,它们只是被操作的位。添加通常不关心有符号和无符号,二进制补码的美妙之处在于你可以输入无符号并签名到相同的加法器逻辑,它经常计算进位标志(无符号溢出)和v标志(有符号溢出)加上z标志,零和n标志否定结果,全部在一个镜头中,没有,如果对add有任何意义,只是计算结果,如果你想使用标志的东西。在这种情况下,cpu无法知道我们正在计算地址。

现在我们将寄存器中的位定义为地址并执行加载。但是只被cpu认为是那条指令的地址,那个时刻之前的那个寄存器就是一些由加法操作产生的位。

我们从记忆中读到了什么?更多位,不是浮点值,只有32位。现在有些cpus可能有直接的方法从内存直接加载到浮点寄存器,有些cpus没有浮点,它都是用通用寄存器合成的。即使是浮点数也可能使用gprs作为浮点值,例如上面的代码是这样做的:

mystruct[j].f=mystruct[i].f;

如果可能,你可能不想刻录fpu寄存器,你可能会使用gpr,如下所示。如果在这段代码附近没有实际的浮点数学,那么只是将位从一个位置移动到另一个位置,没有理由让fpu参与其中。

上述所有代码完成后,上面的代码行可能如下所示:

ldr r1,mystruct_base
shl r2,r0,#5
add r2,r2,r1
ldr r0,[r2]
shl r2,r3,#5
add r2,r2,r1
str r0,[r2]

当输入此代码且r3为j时,r0为i。除了一些例外,cpu不知道或关心这些位是什么。对于ldr和str r2,指令时间段被认为是内存中的某个地址。除此之外,没有结构或浮点或有符号或无符号整数。没有。只是位。

是的,通常当有人说32位计算机时,他们指的是32位寄存器。这是一个很好的概括,通常位大小也是内存总线的地址大小,32位意味着理论上可以解决32位内存,4GBytes。尽管你可能从x86或其他人那里知道,但这有点模糊。通常情况下,使用x86,您会看到64位处理器以32位模式运行,基本上运行的代码/指令需要32位寄存器而不是64位,而x86则是#34;寄存器"有不同的方式来访问它们8,16,32或63位,所以你可以玩这些游戏。

您要求的所有这些问题以及更多问题都以处理器的汇编语言回答。不幸的是现在mips会让你感到困惑,而x86也是如此,所以请避免使用它们,在拇指模式下选择像msp430或ARM或ARM这样简单的东西来学习。