【问题标题】:From Compiler to assembler从编译器到汇编器
【发布时间】:2016-05-04 02:30:56
【问题描述】:

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

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

如果不是这种情况,那么这意味着每次调用 C 函数时,它都会被组装到一个子例程中,其中与特定调用相关的参数会在其中自动替换。这基本上意味着每当调用 C 函数时,编译器都会将其转换为内联函数,这肯定不是这种情况:D

那么哪个是正确的? 非常感谢! :)

【问题讨论】:

  • 希望以下链接对您的问题有用:CToAssemblyTranslationWikibooks.
  • 哪个程序集? x86 的call 只是一个“记住它来自哪里的跳转”,涉及零参数,你可以随意传递它们。
  • “如果不是这样,那意味着” 参数要么放在调用指令之前的寄存器中,要么放在堆栈中。这取决于您正在编程的 CPU 架构以及您使用的调用约定。
  • 在 x86 中,参数存储在堆栈中。了解 ebp 和 esp 寄存器(它们用于为函数参数分配内存)

标签: c assembly compiler-construction


【解决方案1】:

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

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

所以它有点像你假设的混合体。为该函数构建的代码在某些方面是为该函数定制的,因为参数的数量和类型决定了哪些寄存器或多少堆栈被消耗以及如何消耗。同时,所有函数都符合相同的公式,因此它们看起来更像而不是不同。

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

【讨论】:

    【解决方案2】:

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

    一些汇编器具有模拟过程调用的宏(通常只有几个可注册的基类型)。

    不,只有在内联函数的情况下,才会生成一个新函数,其中的参数化了参数并替换了参数。

    编译器不会通过参数的文本替换来为过程生成代码,而是通过将所有相关参数以称为“调用约定”的固定机制放入寄存器或堆栈中。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-23
      • 2018-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多