C 程序如何在引擎盖下传输参数?



这是混合C和汇编的PDP-11代码。在下面,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(堆栈指针)在汇编代码跳回到调用点之前不会恢复到原始值。它仍然指向参数在堆栈中的存储位置。

在C语言中,尤其是任何PDP-11编译器都可能使用的K&R C,被调用的函数无法知道调用函数在堆栈上放置了多少个参数。这就是 var args 函数过去的工作方式。例如,printf将在stdio.h中声明,如下所示:

int printf();

定义将像这样开始:

int printf(fmt)
char *fmt;
{
/* function body */
}

然后调用者可以只做(例如)

printf("%d %dn", a, b);

因此,必须由调用函数负责从堆栈中删除参数,而不是被调用函数

为了使事情更清楚,并且它不仅仅是可变参数函数,在K&R C中,以下内容是完全合法的,并且会打印3。

int add();
int main()
{
int sum;
sum = add(1, 2, 3, 4);
printf("%dn", sum);
return 0;
}
int add(a, b)
int a;
int b;
{
return a + b;
}

它不是 C,而是应用程序二进制接口约定(您通常有多个语言实现或编译器遵循相同的ABI,并且您过去确实在同一系统上使用具有不同ABI 约定的各种编译器)。它是特定于体系结构和操作系统的。顺便说一句,调用约定是 ABI 的一部分。

有关示例,请参阅与 x86 相关的示例

您可以找到考古 PDP11 计算机(以及编译器和操作系统)的 ABI 约定,例如请参阅 PDP11 常见问题解答和 C 调用约定。一些 ABI 使用堆栈,在寄存器上具有各种调用方安全/被调用方安全约定。

我的难题是sp(堆栈指针)在汇编代码跳回到调用点之前不会恢复到原始值。

某些 ABI 或调用约定要求被调用函数还原堆栈指针。其他人希望调用函数这样做。

相关内容

  • 没有找到相关文章

最新更新