为什么即使是大端计算机也从低位内存读取到高位内存?对于 big-endianness 相反可能更优化

Why even big-endianness computers read from lower to higher memory? For big-endianness opposite could be more optimal

我在 wiki and tried to search for my question, found that post 中读到有关字节序的内容,其中解释了字节序不会影响 C 的内存中结构成员的顺序(从低到高)。

在 wiki 中:

The little-endian system has the property that the same value can be read from memory at different lengths without using different addresses

但这只是我们从小地址到大地址读取的情况。

我想知道在哪里(什么架构/语言)使用从高位(明确:大地址)到低位的内存序列?这将使 big-endianness 具有在上面引用的 wiki 中正确提到的相同好处。

也例如它可能意味着在类似于 C malloc return 最大地址的语言中,程序将通过执行 received_address-- 而不是 ++(希望我说清楚了).

我无法通过网络搜索找到为什么计算机开发没有走那条路(从大地址到小地址读取内存)(因为如果 wiki 中的那个短语是正确的,它确实没有走)。

据我所知,加法操作CPU比减法更容易完成,因此从低内存到高内存更efficient/optimal,而不是相反。

P.S。 减法通常是反转加法:Does a subtraction take longer than an Add in a CPU?

如果我把你的问题理解为"could CPUs and software be made to go from highest address down instead of lowest up?",答案是肯定的。它是根据人类从 0 开始的惯例完成的,但也有例外。

例如,在大多数系统(如 Unix)中,程序堆栈从上到下延伸,而在 Multics 中,它是从下到上。 Multics 的想法是,如果代码写入数组或结构的末尾,它将写入空堆栈 space,并且不会覆盖位于较低地址的堆栈值,而在 Unix 中,堆栈值在更高的地址被覆盖并且会在 return 上崩溃或允许安全漏洞利用。

对于没有内存映射的旧系统来说,从 0 开始似乎是合理的,因为您无法确定安装了多少内存,因此无法确定最高有效内存地址是多少。对于具有内存映射的系统,没有理由更改该约定。

通常情况下,单词中的字节顺序与您访问单词的顺序之间的联系为零。促使选择单词中的字节顺序的推理/好处等根本不适用于索引数组的方式。

例如Intel 发明(或至少使用)little-endian 使 8008 更像是一个 CPU 与它想要兼容的位串行 ALU 和移位寄存器存储。 (Why is x86 little endian? and see also https://retrocomputing.stackexchange.com/questions/2008/were-people-building-cpus-out-of-ttl-logic-prior-to-the-4004-8080-and-the-6800/8664#8664 显然 Datapoint 希望 Intel 构建一个位串行机器并以 LSB 优先顺序存储跳转目标是为了让他们高兴,即使 CPU 最终不是位-连载。)

当对单独的词进行单独访问时,这显然没有任何意义。

维基百科引用的"advantage"更像是一个"fun fact",不是什么真正值钱的东西。将 ISA 弯曲变形以得到它是没有意义的,因为它会使其他任何东西变得更糟或更昂贵,甚至让人类更难使用。仅当您正在构建一个 CPU 来一次解码一个字节的指令时,并且如果解码无论如何都将是多周期的,则可以将提取与解码重叠(因为进位从低位传播到高位) .

尽管您可能对构建第一个小端 CPU 提出了相同的论点,但当时人们认为大端 "natural" 是 "natural"。


您提出的设计将使一个字的地址成为其​​最低有效字节的地址。(我认为)。

这更像是 little-endian 关于内存寻址的一切 reversed/flipped/negated。

否则它只是一个软件约定 return 一个指向分配的最后一个指针的指针,这显然不太方便,因为它需要一个偏移量才能使用。但是如果你 return 一个指向分配的最后一个字的指针,你怎么知道调用者想把它当作字而不是字节来对待? malloc return 一个 void*。如果您 return 指向分配的最后一个字节的指针,则必须进行数学运算才能获得指向最后一个字的指针。

因此,除非您执行反向小端,否则 return 指向分配缓冲区的第一个(或唯一)byte/word/doubleword/float/whatever 指针以外的任何东西显然更糟,特别是考虑到像 malloc 这样的分配器不知道其调用者将用于访问内存的元素大小。


我认为C 的机器模型与反向小端系统勉强兼容。您希望 arr[i] 表示 *(arr - i) 而不是 arr + i,并且索引寻址模式可能支持 - 而不是 +。然后 arr[i] 可以透明地与 malloc 一起工作,return 是指向末尾的指针。但是 C 根据 *(x+y) 定义 x[y],并且有代码会注意到差异和中断。

否则,如果寻址仍然像正常一样工作,您是否希望将负索引向上计数为零以从低地址循环到高地址?

如果您的 "normal" 用例是 for(i=0; i<n ; i++) 并访问 arr[-i],则其工作方式与在普通计算机上的工作方式相同。但是你需要修改你的 C 源代码才能在这样的机器上工作。

或者,如果您想编写 for(i=0 ; i>=-n ; i--) 之类的循环,那么您的最大索引将变为负数,而您的大小仍为正数。这看起来更令人困惑。

(@Alexei Martianov 的回答提出了一个很好的观点:CPU 可能需要在地址生成单元和其他正常 CPU 使用加法器的地方使用二进制减法器。我 想想减法器通常比加法器需要更多的硬件。这在主 ALU 之外,当然必须能够同时支持有效的整数数学运算。)