【发布时间】:2013-12-07 03:42:41
【问题描述】:
我正在尝试使用下面的代码 sn-p 在函数调用/返回期间分析 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,
函数堆栈初始化(style-1) 的程序集应如下所示:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movq %rdi, -8(%rbp)
...
leave
ret
但是当我用gcc编译上面的代码sn-p时,函数main和init具有相同的堆栈初始化例程style-1包括subq指令,用于分配堆栈变量的内存空间,
但是函数process 没有那种堆栈初始化。
我得到了这个汇编代码(style-2):
pushq %rbp
movq %rsp, %rbp
movq %rdi, -24(%rbp)
...
popq %rbp
ret
所以问题是:
在编译期间创建不同函数堆栈初始化的编译器决策策略是什么?我没有在这段代码中放任何
__cdecl或类似的东西,但是发现了2个不同的堆栈初始化。style-2函数初始化时如何知道分配的栈内存地址和大小?
movq %rdi, -8(%rbp)的目的是什么?Linux中除了style-1和style-2还有更多的栈初始化样式吗?
(没有明确提及__cdecl或__stdcall的事情)
【问题讨论】:
-
你是怎么编译的?您是否使用了优化设置?如果是,则输出可能会有所不同,具体取决于函数中实际使用的内容。尤其是像这样的例子,大部分都被优化掉了。
-
我只是 gcc-ed 没有优化,所以我猜默认优化(-O2?)是我的设置。
-
我使用 -O0 生成了另一个程序集文件,但使用两个程序集文件(默认和 -O0)之间的差异发现只有一个差异(存在 -O0)。
-
我找到了这个link,发现style-2用在leaf函数中,是没有其他函数调用的函数。
标签: c linux assembly x86-64 callstack