在以下答案中:https : //softwareengineering.stackexchange.com/a/363379/370129
CPU 访问内存的方式解释得很清楚。假设我们创建了一个小于 CPU 数据总线的数据类型——as 是一个 c++ char;如何将 CPU 读取的数据总线大小的内存块修改为在寄存器中用作预期类型?指定的字节是否已移位,以便它占用寄存器中的最低有效字节(如果它已经不存在)?那么多余的(根据类型大小)最高有效字节是否设置为 0?
然后 CPU 是否可以将一个/多个修改的单个字节写入一个/多个内存地址,或者是否必须将整个总线大小的块写入/被占用的总线大小的内存插槽?使用的字节数?
关于发生什么,它是非常特定于处理器的。有些有多种选择。加载字节指令的常见选项是将高位清零或对高位进行符号扩展。因此,如果您的处理器拥有 0xAB 或 0xFFFFFFAB,则将 0xAB 加载到 32 位寄存器中。一些处理器以其他方式解决该问题。
cpu 总线如何工作是由 CPU 决定的。如果您没有加载/存储字节(加载/存储半字、加载/存储字)指令,您的处理器不会非常成功。但是可以通过 x86 和其他随着时间的推移而演变的方式来实现总线。出于性能方面的考虑,今天您通常需要 32 或 64 条或更宽的总线,平衡太大会带来很大的损失,太小则会限制性能。不是必需的,但通常我们有 L1 缓存,有时也有 L2,缓存有多种原因,但缓存是固定宽度的,例如 32 位或 64 位较大,因此较小的传输需要读取-修改-写入因为写入该 sram。这不是处理器的问题,也不是要在总线上解决的问题,
读取通常由 cpu 处理,如果您在 32 位或 64 位总线上进行 8 位读取,那么结果将返回到总线定义的字节通道上,然后处理器从指令中知道要从指令中取出多少数据总线,总线上的位置以及如何处理它(直接进入 alu,进入寄存器,符号或零扩展它等)。
由于目标端通常是为此总线设计的缓存或外设,因此读取不一定需要设计为指示子总线大小,它们的长度通常以总线宽度为单位,因此 128 位传输32 位总线的长度为 4,开销发生在总线之间,然后理想情况下,四个时钟的突发将移动数据(与四个 32 位传输以及每次传输的所有开销相比)。但是单个或子大小读取只会显示为单个宽度读取,处理器会隔离感兴趣的字节。
对于写入,通常有一个长度指示器或一个字节掩码,如果它是一个 32 位宽的总线,它被分成 4 个字节通道,那么将有一个 4 位掩码向另一侧指示写入的哪些字节是有效的,哪些字节是有效的。那些不使用/应用的,这将根据需要驱动读取-修改-写入。例如,如果在 arm 上做了一个带有三个寄存器的 stm 并且你的核心使用的是 64 位宽的总线,那么这将显示为两个传输,一个 32 位和一个 64 位,如果它使用 32 位宽的总线,那么它会可能是长度为 3 的单次传输。(虽然我见过手臂总线不做长度超过总线宽度的 2 的写入)。
较小的传输总是会受到惩罚,这取决于您是否可以在没有其他处理器/系统开销的情况下看到它。由于开销,您不一定会看到 x86 的损失,但有时您可以看到手臂,进行四字节大小的传输与一次 32 位传输,甚至两个 16 位传输与一个 32 位传输。但这取决于,这并不自动意味着你会看到它,这只是意味着你可能会看到。并且理解 arm 制造内核,而不是芯片,所以芯片的大部分与 arm 无关,但整体性能与芯片供应商有很大关系,而不是 arm。
第二次尝试。
对于写入,CPU 总线通常支持 Fuz 指示的各种大小。如今,CPU(处理器核心)不必处理发生在远端的读-修改-写。
对于读取 cpu 总线通常读取完整的总线宽度,处理器确实必须处理它。但是总线和处理器被设计成一个系统。根据指令的处理器将提取正确数量的位,并用零填充或符号扩展它们。
这完全取决于处理器/芯片。
我已经看到并且根据指令、总线、地址、大小,单个指令可以/可能变成多个总线事务是有道理的。