这是PDP-11代码混合C和汇编。在下面,u.u_rsav是一个数组指针,
savu(u.u_rsav);
此功能的汇编代码是
_savu: bis $340,PS
mov (sp)+,r1
mov (sp),r0
mov sp,(r0)+
mov r5,(r0)+
bic $340,PS
jmp (r1)
似乎在它进入程序之前,它首先推送参数,然后按下返回点PC值。因此,r1存储PC,r0存储参数。我的谜题是sp(堆栈指针)在汇编代码跳回调用点之前不会恢复到原始值。它仍然指向参数存储在堆栈中的位置。
答案 0 :(得分:6)
在C中,特别是任何PDP-11编译器可能使用的K& R C,被调用的函数不能知道调用函数在堆栈上放置了多少个参数。这就是var args函数用于工作的方式。例如,printf
将在stdio.h
中声明,如下所示:
int printf();
定义将从这样开始:
int printf(fmt)
char *fmt;
{
/* function body */
}
然后调用者就可以(例如)
printf("%d %d\n", a, b);
因此,必须由调用函数负责从堆栈中删除参数,而不是被调用的函数。
为了使事情更加清晰,并且不仅仅是可变函数,在K& R C中,以下内容完全合法,并且会打印3。
int add();
int main()
{
int sum;
sum = add(1, 2, 3, 4);
printf("%d\n", sum);
return 0;
}
int add(a, b)
int a;
int b;
{
return a + b;
}
答案 1 :(得分:0)
它不是C,而是Application Binary Interface约定(你经常有几个语言实现或编译器跟在相同的 ABI之后,你确实在过去在同一系统上使用不同的 ABI约定的各种编译器。它是特定于体系结构和操作系统的。 BTW,calling conventions是ABI的一部分。
例如,请参阅related to x86
您可以自行查找考古PDP11计算机(以及编译器和操作系统)的ABI约定,例如:见PDP11 FAQ和C calling conventions。一些ABI使用堆栈,在寄存器上有各种调用者安全/被调用者安全约定。
我的谜题是sp(堆栈指针)在汇编代码跳回到调用点之前没有恢复到原始值。
某些ABI或调用约定要求被调用函数恢复堆栈指针。其他人希望调用函数能够做到这一点。