gpt4 book ai didi

assembly - 编译器通常使用寄存器来实现 "intended"的目的吗?

转载 作者:行者123 更新时间:2023-12-02 22:14:09 25 4
gpt4 key购买 nike

我一直在学习汇编,并且我了解到四个主要的 x86 通用寄存器(eax、ebx、ecx 和 edx)每个都有一个预期或建议的用途。例如,eax是累加器寄存器,ecx用作循环的计数器,等等。大多数编译器是否尝试将寄存器用于建议的目的,或者它们是否忽略寄存器“应该”的用途,而只是将值分配给下一个可用寄存器?

此外,在查看 x64 寄存器时,我注意到添加了额外的 8 个通用寄存器,如果忽略 rbp、rsp、rsi 和 rdi(因为它们具有非通用用途),如果您确实包含它们,则为十六个。在普通用户程序(即浏览器、文字处理器等,而不是需要大量寄存器的加密程序)中,在任何给定时间通常使用多少个寄存器?对于像 Firefox 这样的程序来说,同时使用所有 12/16 个普通寄存器是否很常见,或者它们只使用一个子集,因为它们没有足够的变量来填充所有寄存器?我将通过反汇编二进制文件来亲自研究这个问题,看看一般情况是什么,但我希望得到比我更有知识的人的回答。

此外,如果半 gp 寄存器(rsi、rdi、rsp 和 rbp)当前未用于非通用应用程序,编译器通常是否将其用于通用用途?我很好奇,因为我看到这些寄存器被列为“通用”,但即使我也能想到这些寄存器不能用于通用存储的实例(例如,您不想存储变量到 rbp 和 rsp,然后将值压入堆栈!)。那么编译器会在可能的情况下尝试使用这些寄存器吗? x86 和 x64 编译之间有区别吗?因为 x64 处理器有更多可用寄存器,因此不需要将变量填充到任何可用寄存器中?

最佳答案

所有 GP 寄存器都是通用的。
仅当执行特定的(通常是遗留的)指令时,它们才具有特殊含义。

例如四元组rsirdirbprsp,只有后者有特殊用途,这是由于 callretpush 等指令造成的。
如果您不使用它们,即使是隐式使用(诚然,这是一种不太可能的情况),您也可以将其用作累加器。

这个原则是通用的,编译器会利用它。

考虑这个人为的例子[ 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寄存器都被使用了(我没有统计过),包括rbprsirdi .
寄存器的用途均不限于其规范形式。

注意 在此示例中,rsirdi 用于加载和读取(均针对每个寄存器)数组,这是巧合。
这些寄存器用于传递前两个整数/指针参数。

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

关于assembly - 编译器通常使用寄存器来实现 "intended"的目的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43260983/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com