【问题标题】:Confusion between memory size/width and register width内存大小/宽度和寄存器宽度之间的混淆
【发布时间】:2021-05-29 18:28:18
【问题描述】:

我正在学习汇编语言,我们遵循 IA-32 架构。我对“寄存器宽度”和内存大小这两个术语有些混淆。在第一讲中,我们被告知在学习过程中,我们将考虑“寄存器的宽度为 32 位(4 字节)”。然后,在下一课中,我们将学习数据类型,作为一个例子,我们被告知如果要存储一个整数 5(4 个字节),那么每个字节将进入一个内存地址空间,所以按照这个逻辑, int 5 的存储将跨越四个内存地址(可以说是 0-3)。我的想法正确吗?还是我在某个地方弄错了概念?纠正我,因为区分“寄存器宽度”和“内存地址”这两个术语让我困惑了一段时间。谢谢!!

【问题讨论】:

  • 你是对的,如果一个 32 位的寄存器,例如EAX 保存值为 5 的整数,它的四个字节将被存储到内存中的四个字节。当您保留内存并给它一个标签时,例如MyMem DD 0,数字 5 将由指令 MOV [MyMem], EAX 存储在寻址为 MyMem+0MyMem+1MyMem+2MyMem+3 的字节中。内存中的最后三个字节将为零,因为 IA-32 是 little endian

标签: assembly x86


【解决方案1】:

大多数处理器内存是“字节可寻址”的,这意味着我们谈论并用作指针等的地址指定内存中的特定字节(不会进入虚拟与物理,只是滚动)。这绝不意味着内存是按字节构造和寻址的。通常,当然在 32 位 x86 处理器中,可以承载内存的总线至少为 32 位,但可能更大。从 sram 的角度来看,用于缓存的 sram 肯定不会是字节可寻址的。

如果您选择进行字节访问,它的工作原理是读取,假设所有内容都是 32 位宽(总线、缓存 sram、dram 接口等)并且您想读取某个地址,例如 0x1001 ,将会发生的是从地址 0x1000 开始的 32 位(从字节可寻址的角度来看 0x1000、0x1001、0x1002 和 0x1003),并且通常在处理器而不是在内存端提取最低有效字节(0x0000XX00)的下一个的东西。

对于写操作,本例中的总线是 32 位的,因此您几乎必须在其中放置一些东西(或者让它变高,但我对此表示怀疑),因此总线上会流出一些垃圾,这可能是可以预见的如果你知道处理器(来自总线接口某处某个锁存器的陈旧数据),那么我想写 0x1001,所以根据总线规则,总线上至少会有一个字节是字节写入,以及总线上的一些控制信号指示这是单字节写入以及哪个字节和地址。

然后,当您点击这些 32 位(对于本示例)宽的 SRAM 和 DRAM 模块时,会发生读取-修改-写入(希望在缓存中)因此读取完整的 32 位值,修改一个字节并且 32 位值被写回(理想情况下写入缓存中的 SRAM)。理想情况下,当缓存刷新包含该字节的缓存行时,这些写入发生在我们选择的这个宽度的倍数中,32 位。

假设您了解这一点,现实情况是您可以购买多个总线、多个缓存和许多 dram 模块以及几代 32 位 x86 处理器(如果您添加所有其他 arm、mips 等,只是乘以不同的实现)。没有理由假设同一系统上有任何两条总线 是相同的宽度,很好的理由假设它们至少是 32 位宽,但可能是 32 或 64 的倍数。如果不是 64,每个 SRAM 都可能是 32 位的倍数。所以对于每个访问小于该 sram 的宽度必须发生读取-修改-写入。即使说你有一个 32 位 x86 处理器,但总线是 64 位,sram 是 64 位,32 位传输,16 位以及 8 会在某处产生读取-修改-写入。

DRAM 如果您查看可以购买的模块,您可能会看到一些在一侧或每侧有 9 个部件。或 4 部分或 5 部分等。随着时间的推移,您经常会看到 8 位宽的 DRAM 部分,根据是否支持 ECC(如果是双列,则为 16 或 18),您会放下 8 或 9 个, 两侧的零件)。但随后可能会看到 4 个 16 位宽的部分或 2 个 32 位宽的部分。即使您在 dram 总线上可能有 8 位宽的部分,它们也不太可能一次访问一个字节,即使它们可能可以。

DRAM 相对较慢,您希望在前面有一个缓存,并且希望与 DRAM 之间的传输达到每次传输总线宽度的倍数。因此,您希望缓存行本身和 sram 的大小以某种方式匹配以使该端表现良好。并根据需要使用缓存/SRAM 进行读取-修改-写入。尽管字节写入很可能会导致从 DRAM 获取完整的缓存行,然后缓存中的读取-修改-写入,并且该读取可能会导致其他缓存行的刷新。它发生了。

注意没有提到寄存器。因为就内存方面而言,这两件事并没有太大的关系。寄存器是寄存器。记忆系统就是记忆系统。指令就是指令并将两者联系起来。通常,架构(arm、mips、x86 等)决定了您如何使用寄存器来定义地址,它定义了可寻址范围等(地址空间大于通用寄存器中的位数并不罕见,早期 x86 天的分段/偏移量)。

然后根据指令集的规则,而不是寄存器,确定您是否以及如何创建字节、16 位、32 位、64 位等与寄存器之间的传输。处理器发挥其魔力来处理处理器核心的东西,然后芯片人员处理芯片上的东西(如果有的话),然后有人处理处理器核心和最远的 DRAM 或外围设备之间的总线/芯片层。此处涵盖了字节顺序和其他主题。

因此,在地址 0x1000 对内存的 32 位写入被认为是在 0x1000 处的 32 位写入,但从字节寻址的角度来看,这四个字节位于 0x1000、0x1001、0x1002、0x1003。它们共存,但与读/写传输有关,而不是寄存器而不是内存,而是每个指令集的地址空间和数据的规则/定义。在当前的处理器中,它不需要您的 32 位写入并将其转换为四个地址的 4 个 8 位写入。它是在一个地址上写一次。

如果稍后您在 0x1000 处读取 16 位,那么这就是在 0x1000 处读取的 16 位。如果然后在 0x1000 和 0x1001 进行两次 8 位读取,则它与 16 位读取的两个字节相同,而 32 位写入的字节的一半,这只是根据指令集规则寻址的问题。总线上发生的事情以及实际存储器中发生的事情可能对指令集或传输大小有任何线索,也可能没有任何线索,它遵循总线和逻辑规则。内存系统不知道指令是什么,更不关心哪种架构,它旨在进行各种大小的传输。

16 位视图或 32 位视图的哪个字节位于地址 0x1000 是根据指令集的规则,并且某些指令集具有动态或全局更改的能力(可以在大端和小端之间切换,并且请注意,大端有多个定义)。一般说的不是x86。 X86 是小端,所以定义是众所周知的。将 0x11223344 写入 0x1000,如果你在 0x1001 读回一个字节,那么你会得到 0x33。

【讨论】:

    猜你喜欢
    • 2019-12-29
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多