我想在函数调用/返回期间使用下面的代码片段分析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