我知道Roots是:
现在让我们谈谈寄存器。
他们可以包含的代码如下:
mov bx, 0034h ; bx = 52 (stored in 16 bits)
mov cl, bl ; cl = lower 8-bits of bx
mov eax, ecx
call print_int
但等待!
如果我没弄错的话,这是实际的代码持有那些static
,local
和parameters
- 从第一位开始!
那么为什么要写这个 TWICE ? (或从另一个方向?)
为什么要写(例如)
Foo f = new Foo();
**and also**
mov bx, 0034h //<-------- represents the `f` address or something like that
关于寄存器的问题来自这里:
答案 0 :(得分:2)
寄存器只临时保存变量的值。
例如,当您创建对象并将引用存储在变量中时:
Foo f = new Foo();
发生的事情是调用构造函数,并返回对象的引用。在此阶段,引用仅存在于寄存器中。然后寄存器的内容被复制到变量中,所以现在引用存在于寄存器和变量中。然后寄存器继续并用于其他内容,因此引用仅存在于变量中。
另请注意,不仅寄存器中当前的值是根。每个线程都有自己的一组寄存器,当线程没有运行时,这些寄存器会切换到内存,所有这些寄存器值集也都是根。
答案 1 :(得分:2)
因为JIT编译器可能会优化某些部分而不使用堆栈但直接转到寄存器。
让我们进行方法调用,例如:
object a = new object(), b = new object(), c = new object();
DoSomething(a, b, c);
JIT编译器会尝试将尽可能多的参数放入寄存器rahter,而不是将它们推入堆栈。在X86上本地构建的示例显示:
00000082 push dword ptr [ebp-10h]
00000085 mov ecx,dword ptr [ebp-8]
00000088 mov edx,dword ptr [ebp-0Ch]
0000008b call dword ptr ds:[00742078h]
现在有更复杂的角落情况,考虑数组/对象访问。
答案 2 :(得分:2)
考虑
string sentence = ...
int wordCount = sentence.Split(' ').Length;
String.Split()生成一个数组,必须保持对该语句的(部分)可达。但是没有指向它的变量或参数,优化器很可能将引用保留在寄存器中。
因此必须将CPU(地址)寄存器视为根的一部分。