這個問題在這里已經有了答案: 為什么引數分配在幀指標下方而不是上方? (1 個回答) 為什么生成的程式集將 edi 移動到堆疊上的變數? (1 個回答) GCC 將暫存器 args 放置在堆疊上,區域變數下方有間隙? (1 個回答) 為什么額外的指標引數在匯編中消失了? (2 個回答) 為什么堆疊中元素的地址在 ubuntu64 中顛倒了? (2 個回答) 7 小時前關閉。
我試圖通過一些實際示例來了解函式的呼叫堆疊。在解釋這一點的所有圖表中,它的布局類似于 [Local variables][Return Address][Arguments](左側的低記憶體)。但是當我在 gdb 和函式內的斷點時,我以不同的順序得到它們:
(gdb) info args
arg1 = 0
arg2 = 0
arg3 = 32767
(gdb) p &arg1
0x7ffff3a4697ec
(gdb) p &arg2
0x7ffff3a4697e8
(gdb) p &arg3
0x7ffff3a4697e4
(gdb) info locals
local1 = 0
local2 = 0
local3 = 0
(gdb) p &local1
0x7ffff3a4697fc
(gdb) p &local2
0x7ffff3a4697f8
(gdb) p &local3
0x7ffff3a4697f4
(gdb) info frame
Stack level 0, frame at 0x7ffff3a469810:
...
Arglist at 0x7ffff3a469800, args: arg1=0, arg2=0, arg3=32767
Locals at 0x7ffff3a469800, Previous frame's sp is 0x7ffff3a469810
Saved registers:
rbp at 0x7ffff3a469800, rip at 0x7ffff3a469808
為什么函式的引數在比區域變數和回傳指標都低的記憶體地址?關于該主題的所有文獻(例如像這樣的圖表https://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Call_stack_layout.svg/342px-Call_stack_layout.svg.png)暗示引數應該更高記憶體地址比回傳地址?并且回傳地址應該在 locals 和 arguments 之間,而我在一個連續的塊中有 locals 和 arguments,最后是回傳地址。非常感謝 - 如果我完全誤解了,請道歉!
編輯:示例 C 程式來生成這個:
#include <stdio.h>
void func1(int arg1, int arg2, int arg3) {
int local1;
int local2;
int local3;
local1 = 2;
local2 = 3;
local3 = 4;
}
int main(){
int a;
int b;
int c;
func1(a, b, c);
}
gcc code.c -o code在 CentOS x86_64 上編譯此代碼。使用 gdb 運行并在 func1 中放置一個斷點。查看arg變數的地址、區域變數和回傳地址。
uj5u.com熱心網友回復:
為什么函式的引數在比區域變數和回傳指標都低的記憶體地址?關于該主題的所有文獻 (...) 都暗示引數應該位于比回傳地址更高的記憶體地址?
由于您使用的是 x86_64 ABI,前 6 個引數通常會在暫存器中傳遞。這是System V 應用程式二進制介面 AMD64 架構處理器補充的相關參考(第 20 頁,重點是我的,感謝 @KamilCuk 提供鏈接):
傳遞 一旦引數被分類,暫存器將被分配(按從左到右的順序)傳遞,如下所示:
- 如果類是 MEMORY,則在堆疊上傳遞引數。
- 如果類是整數,則使用序列 %rdi、%rsi、%rdx、%rcx、%r8 和 %r9 的下一個可用暫存器。
因此,最有可能發生的是您在func1和之間混合堆疊幀main。看看這段代碼:
https://godbolt.org/z/88rPebqYj
引數arg1, arg2andarg3被傳遞到func1暫存器rdi, rsiand rdx。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/384825.html
