我有一个关于 assembly 的基本问题。
如果算术运算也可以在内存上运行,为什么我们还要费心只在寄存器上进行算术运算呢?
例如,以下两种情况都会(本质上)导致计算出相同的值作为答案:
片段1
.data
var dd 00000400h
.code
Start:
add var,0000000Bh
mov eax,var
;breakpoint: var = 00000B04
End Start
片段2
.code
Start:
mov eax,00000400h
add eax,0000000bh
;breakpoint: eax = 0000040B
End Start
据我所知,大多数文本和教程主要在寄存器上进行算术运算。使用寄存器是不是更快?
最佳答案
如果您查看计算机体系结构,您会发现一系列内存级别。靠近 CPU 的设备速度快、成本高(每比特),因此体积小,而另一端则有大、慢且便宜的内存设备。在现代计算机中,这些通常类似于:
CPU registers (slightly complicated, but in the order of 1KB per a core - there
are different types of registers. You might have 16 64 bit
general purpose registers plus a bunch of registers for special
purposes)
L1 cache (64KB per core)
L2 cache (256KB per core)
L3 cache (8MB)
Main memory (8GB)
HDD (1TB)
The internet (big)
随着时间的推移,越来越多级别的缓存被添加 - 我还记得 CPU 没有任何板载缓存的时候,而我还没有老!如今,HDD 配备了板载缓存,并且互联网可以在任意位置进行缓存:内存中、HDD 上,也可能在缓存代理服务器上。
离开 CPU 的每一步,带宽都会急剧下降(通常是数量级),延迟也会增加。例如,HDD 可能能够以 100MB/s 的速度读取,延迟为 5ms(这些数字可能并不完全正确),而主内存可以以 6.4GB/s 的速度读取,延迟为 9ns(六阶)震级!)。延迟是一个非常重要的因素,因为您不想让 CPU 等待的时间超过其必须的时间(对于具有深层管道的架构尤其如此,但这是另一天的讨论)。
这个想法是,您经常会一遍又一遍地重复使用相同的数据,因此将其放入小型快速缓存中以供后续操作是有意义的。这称为时间局部性。局部性的另一个重要原则是空间局部性,它表示彼此靠近的内存位置可能会在大约同一时间被读取。正是由于这个原因,从 RAM 读取将导致读取更大的 RAM block 并将其放入 CPU 缓存中。如果没有这些局部性原则,那么内存中的任何位置在任何时候都有相同的机会被读取,因此无法预测接下来将访问什么,以及所有级别的缓存世界上的速度不会提高。您不妨只使用硬盘驱动器,但我确信您知道计算机在分页时突然停止的感觉(这基本上是使用 HDD 作为 RAM 的扩展)。从概念上讲,除了硬盘之外没有内存是可能的(许多小型设备只有一个内存),但这与我们熟悉的相比会慢得令人痛苦。
拥有寄存器(并且只有少量寄存器)的另一个优点是它可以让您拥有更短的指令。如果您的指令包含两个(或更多)64 位地址,那么您将拥有一些很长的指令!
关于performance - 为什么我们要在汇编中使用 CPU 寄存器,而不是直接使用内存呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45581423/