所有GP寄存器都是通用的。
只有当执行特定的,通常是遗留的指令时,它们才有特殊的含义。
例如四联rsi
,rdi
,rbp
,rsp
只有后者有一个特殊的目的,这是由于像call
,ret
,push
等指令。
如果你不使用它们,即使是隐含的(一种不可能的情况),你可以用它作为累加器。
这个原则是普遍的,编译器利用它。
考虑这个人为例子[1]:
void maxArray(int* x, int* y, int*z, short* w) {
for (int i = 0; i < 65536; i++)
{
int a = y[i]*z[i];
int b = z[i]*z[i];
int c = y[i]*x[i]-w[i];
int d = w[i]+x[i]-y[i];
int e = y[i+1]*w[i+2];
int f = w[i]*w[i];
x[i] = a*a-b+d;
y[i] = b-c*d/f+e;
z[i] = (e+f)*2-4*a*d;
w[i] = a*b-c*d+e*f;
}
}
它是由GCC编译成此房源
maxArray(int*, int*, int*, short*):
push r13
push r12
xor r8d, r8d
push rbp
push rbx
mov r12, rdx
.L2:
mov edx, DWORD PTR [rsi+r8*2]
mov ebp, DWORD PTR [r12+r8*2]
movsx r11d, WORD PTR [rcx+r8]
mov eax, DWORD PTR [rdi+r8*2]
movsx ebx, WORD PTR [rcx+4+r8]
mov r9d, edx
mov r13d, edx
imul r9d, ebp
imul r13d, eax
lea r10d, [rax+r11]
imul ebx, DWORD PTR [rsi+4+r8*2]
mov eax, r9d
sub r10d, edx
imul ebp, ebp
sub r13d, r11d
imul eax, r9d
imul r11d, r11d
sub eax, ebp
add eax, r10d
mov DWORD PTR [rdi+r8*2], eax
mov eax, r13d
imul eax, r10d
cdq
idiv r11d
mov edx, ebp
sub edx, eax
mov eax, edx
lea edx, [0+r9*4]
add eax, ebx
mov DWORD PTR [rsi+r8*2], eax
lea eax, [rbx+r11]
imul r9d, ebp
imul r11d, ebx
add eax, eax
imul edx, r10d
add r9d, r11d
imul r10d, r13d
sub eax, edx
sub r9d, r10d
mov DWORD PTR [r12+r8*2], eax
mov WORD PTR [rcx+r8], r9w
add r8, 2
cmp r8, 131072
jne .L2
pop rbx
pop rbp
pop r12
pop r13
ret
你可以看到,大多数GP的寄存器用于(我的天堂不包括它们),包括rbp
,rsi
和rdi
。
寄存器的使用都不限于其规范形式。
注意在这个例子中rsi
和rdi
用于加载和读取(都为每个寄存器)的阵列,这是巧合。
这些寄存器用于传递前两个整数/指针参数。
int sum(int a, int b, int c, int d)
{
return a+b+c+d;
}
sum(int, int, int, int):
lea eax, [rdi+rsi]
add eax, edx
add eax, ecx
ret
所有GP寄存器都是通用的。只有当执行特定的,通常是遗留的指令时,它们才有特殊的含义。例如四元组'rsi','rdi','rbp','rsp'只有后者具有特殊用途,并且由于“call/ret/push/pop”等等。如果你不使用它们(甚至是隐含的),你可以用它作为累加器。这个原则是普遍的,编译器利用它。 –
@MargaretBloom不是像movsb这样的指令用于数组/字符串复制之类的指令所使用的rsi/rdi寄存器吗?另外,变量在通话/回复/推送/弹出指令之间的时间间隔内是否仅为“活动”是常见的情况?看起来这些指令会很普遍,以至于在这些指令之间没有足够的“空间”来适应变量的整个生命周期。 –
我用一些示例发布了一个答案,以说服编译器使用GP尽可能自由地注册:)像'rbp'这样的寄存器和'gtr'类似 - 现在后者确实是一个特定的目的寄存器 –