Clang 填充数组
Clang padding array
我正在尝试了解函数调用在机器级别的工作原理。为此,我创建了一个像这样的虚拟 C++ 函数:
int func(int a[], int n) {
char arr[n];
arr[n - 99] = 100; //to prevent compiler from optimizing my function to noop
return arr[12]; //to prevent compiler from optimizing my function to noop
}
而且,我在使用 x86-64 clang 13.0.1 编译时得到了以下程序集
push rbp
mov rbp, rsp
mov eax, esi
mov rcx, rsp
add rax, 15 // Instruction 1
and rax, -16 // Instruction. 2
mov rdx, rcx
sub rdx, rax
mov rsp, rdx
movsxd rsi, esi
mov byte ptr [rsi + rdx - 99], 100
neg rax
movsx eax, byte ptr [rcx + rax + 12]
mov rsp, rbp
pop rbp
ret
指令 1 和 2 正在根据变量 n 计算数组 arr 的大小。计算出的大小是 16 的下一个最大倍数,而不是 n。例如,即使 n = 1,clang 也会分配 16 字节的内存。我很困惑为什么 clang 会尝试将数组大小设置为 16 字节的倍数?
我检查了 arr 的不同数据类型,但它们都有相同的行为。所以,我不认为这是为了对齐目的,因为不同的数据类型会有不同的对齐大小。
我也检查了不同的编译器。所有人都在分配大小为 16 的倍数的数组。我缺少一些基本的东西。
Here是link作为参考。
x86-64 的 System V psABI 需要足够大的数组,并且 variable-length 数组至少要对齐到 16 个字节,以便它们正确对齐以进行 SSE 操作。
正如@PeterCordes 在此答案下解释的那样,还有其他原因使堆栈对齐到 16,尽管这对于您作为示例给出的特定函数并不重要。
但是请注意,variable-length 数组首先仅在 C++ 中作为 compiler-specific 扩展受支持。它们在标准 ISO C++ 中是不允许的,但在 C99 之后的 C 中受支持。
作为参考,您可以找到 ABI 规范(草案)here 的链接。该要求在第 3.1.2 节的“聚合和联合”标题下给出。
我正在尝试了解函数调用在机器级别的工作原理。为此,我创建了一个像这样的虚拟 C++ 函数:
int func(int a[], int n) {
char arr[n];
arr[n - 99] = 100; //to prevent compiler from optimizing my function to noop
return arr[12]; //to prevent compiler from optimizing my function to noop
}
而且,我在使用 x86-64 clang 13.0.1 编译时得到了以下程序集
push rbp
mov rbp, rsp
mov eax, esi
mov rcx, rsp
add rax, 15 // Instruction 1
and rax, -16 // Instruction. 2
mov rdx, rcx
sub rdx, rax
mov rsp, rdx
movsxd rsi, esi
mov byte ptr [rsi + rdx - 99], 100
neg rax
movsx eax, byte ptr [rcx + rax + 12]
mov rsp, rbp
pop rbp
ret
指令 1 和 2 正在根据变量 n 计算数组 arr 的大小。计算出的大小是 16 的下一个最大倍数,而不是 n。例如,即使 n = 1,clang 也会分配 16 字节的内存。我很困惑为什么 clang 会尝试将数组大小设置为 16 字节的倍数?
我检查了 arr 的不同数据类型,但它们都有相同的行为。所以,我不认为这是为了对齐目的,因为不同的数据类型会有不同的对齐大小。
我也检查了不同的编译器。所有人都在分配大小为 16 的倍数的数组。我缺少一些基本的东西。
Here是link作为参考。
x86-64 的 System V psABI 需要足够大的数组,并且 variable-length 数组至少要对齐到 16 个字节,以便它们正确对齐以进行 SSE 操作。
正如@PeterCordes 在此答案下解释的那样,还有其他原因使堆栈对齐到 16,尽管这对于您作为示例给出的特定函数并不重要。
但是请注意,variable-length 数组首先仅在 C++ 中作为 compiler-specific 扩展受支持。它们在标准 ISO C++ 中是不允许的,但在 C99 之后的 C 中受支持。
作为参考,您可以找到 ABI 规范(草案)here 的链接。该要求在第 3.1.2 节的“聚合和联合”标题下给出。