我試圖了解函式呼叫在機器級別是如何作業的。為此,我創建了一個像這樣的虛擬 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 的倍數的陣列。我缺少一些基本的東西。
這是作為參考的鏈接。
uj5u.com熱心網友回復:
x86-64 的 System V psABI 要求足夠大的陣列和可變長度陣列至少對齊 16 個位元組,以便它們正確對齊以進行 SSE 操作。
正如@PeterCordes 在此答案下解釋的那樣,還有其他理由將堆疊保持為 16,盡管這對于您作為示例給出的特定函式無關緊要。
但是請注意,可變長度陣列首先在 C 中作為特定于編譯器的擴展才受支持。它們在標準 ISO C 中是不允許的,但自 C99 起在 C 中受支持。
作為參考,您可以在此處找到 ABI 規范(草案)的鏈接。該要求在第 3.1.2 節的“聚合和聯合”標題下給出。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/450180.html
