从编译器到汇编程序

时间:2016-01-27 08:34:46

标签: c assembly compiler-construction

我对汇编程序有疑问。我在想如何将多个参数作为参数的C函数转换为汇编。所以我的问题是,汇编中是否有一个子程序将参数作为参数进行操作? 代码可能如下所示:

调用label1,R16。 其中R16是子程序输入参数。

如果情况并非如此,那么这意味着每次调用C函数时,它都会被组装成一个子程序,其中与特定调用相关的参数会自动替换。这基本上意味着无论何时调用C函数,编译器都会将其转换为内联函数,但事实并非如此:D

哪个是对的? 非常感谢! :)

2 个答案:

答案 0 :(得分:2)

编译器使用“调用约定”,该约定可以特定于该一个目标体系结构的一个编译器(x86,arm,mips,pdp-11等)。对于具有“大量”通用寄存器的体系结构,调用约定通常从在寄存器中传递参数开始,然后使用堆栈,对于没有大量寄存器的体系结构,堆栈主要是否主要用于参数传递和返回。

调用约定是一组规则,如果每个人都遵循规则,你可以将函数编译成对象并将它们与其他对象链接,并且他们将能够调用彼此的函数或自己调用。

所以它与你所假设的有点混合。为该函数构建的代码在某些方面是自定义的,因为参数的数量和类型决定了什么寄存器或消耗了多少堆栈以及如何使用。同时,所有功能都符合相同的公式,因此它们看起来比不同的更相似。

例如,在一个手臂上你可能有三个整数被传递给一个函数,它们会用于我所见过的所有手臂调用约定(通常你会发现即使它可能因编译器而异,但它通常不会或在这种情况下arm和mips以及其他一些他们试图为每个人指定约定,而不是编译器人试图这样做)C函数中的第一个参数将在r0中出现,第二个在r1中,第三个在r2中。如果第一个参数是64位整数,那么r0和r1用于第一个参数,r2得到第二个,r3得到第三个,在r3之后使用堆栈,堆栈上的参数排序也由约定决定。因此,当使用相同的C原型编译调用者或被调用者的代码时,双方都确切地知道在哪里找到参数并构造汇编语言来做到这一点。

答案 1 :(得分:1)

某些指令集中可能存在一些最小选项,但通常情况并非如此。

有些汇编程序虽然模仿程序调用(通常只有几个可注册的基类),但它们都有宏。

不,仅在内联函数的情况下,使用参数替换参数化生成新函数。

编译器不会通过文本替换参数来为过程生成代码,而是通过将所有相关参数放入寄存器或堆栈中,并将其置于称为"调用约定"的固定方案中。

为每次调用生成计算和加载参数(在寄存器或堆栈中)的代码,并且过程/函数保持不变,并从它知道可以找到它们的位置加载参数