我想在函數調用/返回期間使用下面的代碼片段分析Linux程序集堆棧初始化/清除。未初始化的變量是有意的。有關Linux函數堆棧初始化的問題
#define MAX 16
typedef struct _CONTEXT {
int arr[MAX];
int a;
int b;
int c;
};
void init(CONTEXT* ctx)
{
memset(ctx->arr, 0, sizeof(ctx->arr[0]));
ctx->a = 1;
}
void process(CONTEXT* ctx)
{
int trash;
int i;
for (i = 0; i < MAX; i++)
{
trash = ctx->arr[i];
}
}
int main(int argc, char *argv[])
{
CONTEXT ctx;
init(&ctx);
process(&ctx);
return 0;
}
當我從學校瞭解到,從本次講座slide,
函數的堆棧初始化(風格-1)的組裝應該是這樣的:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movq %rdi, -8(%rbp)
...
leave
ret
但是,當我使用gcc編譯上面的代碼片段,函數main
和init
具有相同的堆棧初始化例程style-1包括subq
指令來分配堆棧變量的內存空間,
但函數process
沒有這種堆棧初始化。
我得到這個彙編代碼(風格-2):
pushq %rbp
movq %rsp, %rbp
movq %rdi, -24(%rbp)
...
popq %rbp
ret
所以問題是:
什麼是在編譯時產生不同的功能堆棧初始化的編譯器決定的政策?我沒有在這個代碼中放入任何
__cdecl
等,但是找到了2個不同的堆棧初始化。如何初始化函數初始化時分配的堆棧內存地址和大小?
movq %rdi, -8(%rbp)
的用途是什麼?是否有旁更多的堆棧初始化款式風格-1和風格-2在Linux呢?
(沒有明確提到__cdecl
或__stdcall
東西)
你是如何編譯它的?你使用優化設置嗎?如果是,那麼輸出可能會有所不同,具體取決於函數中真正使用的內容。尤其是像這樣的例子,這些例子大部分都被刪除了。 – Devolus
我剛剛gcc-ed沒有優化,所以默認優化(-O2?)是我的設置我猜。 – LocustSpectre
我用-O0生成另一個程序集文件,但在兩個程序集文件(默認和-O0)之間使用差異僅發現一個區別(-O0的存在)。 – LocustSpectre