我对汇编语言有一些了解,知道计算机通常只有4或8个通用寄存器。那么在多线程等情况下,所有计算机程序都是如何仅凭这么少的寄存器运作的呢?
我对汇编语言有一些了解,知道计算机通常只有4或8个通用寄存器。那么在多线程等情况下,所有计算机程序都是如何仅凭这么少的寄存器运作的呢?
顺便说一下:我的梦想是有一天能写一本像这样从夸克层面到Emacs覆盖所有内容的书 :-)
你必须认识到,即使是简单的事情也需要执行数千到数百万条汇编指令。这些寄存器的值经常被交换。
计算机可以用非常少的寄存器完成所有操作,这实际上非常有趣。
在汇编语言层面上,通过巧妙的编译器实现了高效利用很少的寄存器,真的很聪明。
如果一个问题使用提供的寄存器无法完成,程序通常会将其寄存器“溢出”到主内存堆栈中。通过记住我们放置溢出寄存器的堆栈位置,我们可以轻松地检索它们。
当我们用尽所需的寄存器时,我们只需将它们存储在堆栈上,这比大多数人需要的程序要提供更多的空间。
在多线程的特定情况下,我们只需将所有寄存器保存到内存中,然后为其他线程提供一个干净的状态。
这是计算机的另一个存储器,特别是RAM所用的一种方式:将数据位保存和恢复到寄存器中。
当线程被切换以便运行另一个线程时,第一个线程的寄存器状态会被保存在某个地方(堆栈或其他数据结构上),并且第二个线程的寄存器状态会从之前保存的位置恢复。RAM足够快,可以在一秒钟内发生数千次这样的切换,但如果你不必要地交换线程,它可能会影响性能。
另一个非常常见的情况是局部变量 - 如果局部变量使用的时间足够短,它可能永远不存在于寄存器之外。然而,在许多情况下,局部变量可能需要从寄存器保存到内存位置,以便可以加载和操作其他值。实际上,对于几乎任何变量都是如此,不仅仅是局部变量(但局部变量更有可能从未存在于内存中)。
这是一个相当复杂的问题,答案取决于您的CPU架构。
在旧时代,你是正确的 - 确实只有一些通用寄存器。现在,CPU和编译器通过像寄存器重命名这样的技术来与你的通用寄存器玩 "三张牌蒙特卡罗" 的游戏。
虽然在简单的架构上,当发生上下文切换时,寄存器确实会被复制到[缓存]内存中,但SMT之类的技术可以“欺骗”操作系统,让它认为有更多的核心。
但是对于你的问题最普遍的答案是数据会频繁地被移入和移出寄存器。这就是为什么在任何给定的汇编程序中,你会看到大量的“MOV”指令。CPU和编译器设计师花费了大量时间和金钱来优化他们的设计,以便你不需要将数据从主内存(速度较慢)移动到寄存器中,他们尽可能地保持数据缓存。这种大量的“MOV”指令是为什么内存延迟和总线速度对整个计算机性能如此重要的原因。