这取决于您平台的调用约定以及标准库的实现方式。
以下面的程序为例:
#include <stdio.h>
int main(void)
{
printf("Hello, World\n");
return 0;
}
和下面的命令行来编译它:
gcc -S -std=c99 -pedantic -Wall -Werror syscall.c
在使用 gcc 2.96 的 32 位 Red Hat box (i686) 上,我们得到以下机器码:
1 .文件“系统调用.c”
2.版本“01.01”
3 gcc2_compiled.:
4 .section .rodata
5 .LC0:
6 .string "你好,世界\n"
7.文本
8 .对齐 4
9 .globl 主要
10 .type main,@function
11 主要:
12 推升 %ebp
13 移动 %esp, %ebp
14 美元 8 美元,%esp
15 美元 12 美元,%esp
16 推力 $.LC0
17 调用 printf
18 加 16 美元,%esp
19 移动 $0, %eax
20 离开
21 退休
22.Lfe1:
23 .size main,.Lfe1-main
24 .ident“GCC:(GNU)2.96 20000731(红帽 Linux 7.2 2.96-112.7.2)”
第 16 行将字符串文字的地址压入堆栈,然后调用 printf。
这是相同的代码,以相同的方式编译,在 64 位 SLES 10 机器 (x86_64) 上使用 gcc 4.1.2:
1 .文件“系统调用.c”
2 .section .rodata
3 .LC0:
4 .string "你好,世界"
5.文本
6 .globl 主要
7 .type main, @function
8个主要:
9.LFB2:
10 pushq %rbp
11 .LCFI0:
12 movq %rsp, %rbp
13.LCFI1:
14 movl $.LC0, %edi
15个看涨期权
16 移动 $0, %eax
17 离开
18 点
;;
;;不包括附加内容
;;
在这种情况下,第 14 行将字符串文字的地址写入 寄存器 (%edi),而不是将其压入堆栈。还要注意,这个版本的 gcc 足够聪明,可以意识到由于我传递了一个 char * 类型的参数,它可以替代对 puts 的调用。
无论哪种情况,您在调用时都会创建一个新的堆栈帧;不同之处在于堆栈帧中的内容。在 Red Hat 盒子上,它将包含字符串文字的地址;在 SLES 10 盒子上,它不会。