【发布时间】:2020-10-11 06:32:40
【问题描述】:
我正在尝试了解可变大小的静态数组如何在内部工作:
以下是 C 中固定大小的静态数组及其对应的汇编;
int main()
{
int arr[2] = {3};
}
================
main:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], 0
mov DWORD PTR [rbp-8], 2
mov eax, 0
pop rbp
ret
然而,一个可变大小的数组如下所示
int main()
{
int varSize ;
int Arr[varSize];
}
=================
main:
push rbp
mov rbp, rsp
sub rsp, 32
mov rax, rsp
mov rcx, rax
mov eax, DWORD PTR [rbp-4]
movsx rdx, eax
sub rdx, 1
mov QWORD PTR [rbp-16], rdx
movsx rdx, eax
mov r8, rdx
mov r9d, 0
movsx rdx, eax
mov rsi, rdx
mov edi, 0
cdqe
lea rdx, [0+rax*4]
mov eax, 16
sub rax, 1
add rax, rdx
mov edi, 16
mov edx, 0
div rdi
imul rax, rax, 16
sub rsp, rax
mov rax, rsp
add rax, 3
shr rax, 2
sal rax, 2
mov QWORD PTR [rbp-24], rax
mov rsp, rcx
mov eax, 0
leave
ret
如果我声明一个可变大小的数组,我会看到大量的汇编指令。谁能解释一下这种可变大小的灵活性是如何实现的?
【问题讨论】:
-
战术错误:您无法确定这些说明的用途。将 varSize 设置为某个非常量值,例如 varSize = f();。在数组中存储一些东西,比如 Arr[20] = 3;这样您就可以了解说明的作用。
-
你显然没有优化编译,所以代码是不必要的复杂。无论如何,变量版本所做的是将数组大小四舍五入为 16 字节的倍数以保持堆栈对齐,然后通过调整堆栈指针来分配它。静态版本使用 128 字节的红色区域。使用更大但仍然是静态的数组,它也可以调整堆栈指针,但具有编译时间常数。
-
目前的代码是荒谬的,因为数组的大小取自一个未初始化的变量。
-
Here 是一个更好的例子,它也可以在启用优化中幸存下来。您应该会发现这更容易理解发生了什么。
标签: arrays assembly gcc variable-length-array compiler-specific