我最近注意到 Windows 发出长哔声,这应该是 BSOD 错误代码中的 1a 内存问题,我运行 memtest 并发现如下所示的错误地址。
2024-01-24 14:20:11 - [Data Error] Test: 13, CPU: 0, Address: 293B98920, Expected: 5F0DF0A5, Actual: 5F8DF0A5
2024-01-24 14:18:53 - [Data Error] Test: 13, CPU: 0, Address: 293B98920, Expected: D70BA8A2, Actual: D78BA8A2
2024-01-24 14:17:20 - [Data Error] Test: 13, CPU: 0, Address: 293B98920, Expected: 1F1F39AC, Actual: 1F9F39AC
2024-01-24 14:17:05 - [Data Error] Test: 13, CPU: 0, Address: 293B98920, Expected: 50039BF9, Actual: 50839BF9
我有 ~12gb 的 RAM,所以地址上升到 31F000000,也就是 12784MB,但它还显示另外 4 个字节,这些字节是存储在这些地址中的信息,这是如何工作的?有 13.404.995.584 个地址,每个地址存储 4 个字节?
答案1
尽管内存是按字节寻址的,但程序(甚至 CPU)通常以 16 位(2 字节)、32 位(4 字节)甚至 64 位(8 字节)为单位来处理它。例如,程序可以跨字节存储 32 位值0xABC0...0xABC3
,并且据说该值存储在“0xABC0”(暗示范围的其余部分)。这就是 memtest 在这里所做的。
(即使在机器代码级别,也有指令将例如 32 位宽的整数从内存中加载为单个指令,且仅指定“起始”地址,这通常比四个一次一个字节的指令更快。)
答案2
内存读写不是“按字节”发生的,而是按“字边界”对齐的。
这意味着,如果您的内存以 32 位传输方式运行,那么要从0x000F0000
(so 0x000F0002
) 开始读取第三个字节,您必须向下移动到最近的 32 位边界0x000F0000
,然后传输所有四个字节以读取第三个字节。对于大多数现代系统使用的 64 位内存,您必须从内存中传输完整的 8 字节 (64 位)“字”才能读取该内存区域内的单个字节。
Memtest 刚刚选择了一种默认视图,每次显示 4 个字节,而不是 8 个字节或系统内存传输大小。
软件显示的内容通常是基于人们最习惯的内容而任意选择的,并且是在简洁和过于冗长之间做出的选择。两块内容293B98920 51F22EAB
对于人们来说比293B9892051f22eab
无论如何,您实际上无法传递0x000F0002
到物理内存芯片。由于现代内存使用跨内存芯片组的并行数据总线,因此允许字节寻址的最低地址线实际上被隐藏了。通过使用 8 个芯片(或 4 个芯片,每个芯片有两个内存组),您基本上不再“看到”任何地址的最低 3 位。
这 8 个芯片都将被赋予相同的地址,然后发送到内存控制器的将是一个长的 64 位字,即排列在一起的每个内存芯片的内容。
然后,该 64 位字被放入处理器的寄存器中。
然后,处理器看到您要求输入特定字节,就会检查0x000F0002
收到的 8 个字节,并给出第三个字节。其他字节由处理器内存控制器接收,并可能进入各种 CPU 缓存,软件根本不会费心显示收到的其余数据。