【问题标题】:How does C code call assembly code (e.g. optimized strlen)?C 代码如何调用汇编代码(例如优化的 strlen)?
【发布时间】:2011-09-04 15:17:12
【问题描述】:

我经常阅读有关 C 编程语言中的某些函数如何通过用汇编语言编写来优化的内容。如果这句话听起来有点误导,让我道歉。

那么,我会说清楚:当您在 UNIX/C 系统上调用 strlen 之类的函数时,您调用的实际函数是用汇编编写的,这是怎么回事?你能以某种方式将汇编直接写入 C 程序还是外部调用情况?能够做到这一点是 C 标准的一部分,还是操作系统特定的东西?

【问题讨论】:

  • 您需要的最重要的信息之一是描述您的 C 编译器如何将参数和返回地址传递给子例程。这称为该机器或处理器的“调用约定”。例如,在 x86 上通常使用堆栈传递参数和返回地址。这仅适用于可变参数函数,如果参数以从右到左的顺序压入堆栈,然后返回地址被压入。如果您编写汇编语言函数以期望这种堆栈布局(“激活记录”),那么唯一重要的......
  • ...另外的实现是您的 asm 函数,一旦组装和链接,就会在您的程序代码段中分配一个地址。因此,您的 C 代码可能会将处理器的执行转移到您的 asm 函数的这个地址。那时,只要您的函数使用寄存器做正确的事情(必须为调用者保留一些寄存器,例如 EBP),知道如何在堆栈上查找参数和返回地址,并将其结果返回到正确的位置( 32 位返回值在 x86 上的 EAX 中),那么没有什么会取消它。

标签: c unix assembly


【解决方案1】:

C 标准规定了每个库函数必须做什么,而不是如何实现。

几乎所有已知的 C 实现都被编译成机器语言。由 C 编译器/库的实现者决定他们如何选择实现像 strlen 这样的函数。他们可以选择用 C 语言实现它并将其编译成一个对象,或者他们可以选择用汇编语言编写它并将其组装成一个对象。或者他们可以以其他方式实现它。只要你调用strlen时得到正确的效果和结果就没有关系。

现在,碰巧的是,许多 C 工具集确实允许您编写内联汇编,但这绝对不是标准的一部分。任何此类功能都必须作为 C 标准的扩展。

【讨论】:

  • 注意:如果像strlen这样的函数是用汇编而不是C编写的,通常是出于性能原因。
【解决方案2】:

最终编译的程序和汇编程序都是机器语言,所以它们可以互相调用。这样做的方法是让汇编代码使用与用 C 编写的程序相同的调用约定(准备调用的方法、准备参数等)。可以找到 x86 处理器的流行调用约定的概述@987654321 @。

【讨论】:

【解决方案3】:

许多(大多数?)C 编译器确实支持inline assembly,尽管它不是标准的一部分。也就是说,编译器并不一定需要支持任何此类事情。

首先,认识到汇编大多只是人类(半)可读的机器代码,而 C 最终还是机器代码。

“调用”一个 C 函数只是生成一组指令,这些指令根据一些已建立的调用约定准备寄存器、堆栈和/或其他一些与机器相关的机制,然后跳转到被调用函数的开头。

一个汇编代码块可以符合适当的调用约定,从而生成一个机器代码块,另一个最初用 C 编写的机器代码块能够调用。当然,反过来也是可以的。

调用约定、汇编过程和链接过程(将汇编生成的目标文件与 C 生成的目标文件链接)的细节在平台、编译器和链接器之间可能会有很大差异。适合您选择的平台的良好组装教程可能会涵盖这些细节。

我碰巧喜欢以 x86 为中心的 PC Assembly Tutorial,它专门针对接口汇编和 C 代码。

【讨论】:

    【解决方案4】:

    当 C 代码由 gcc 编译时,它首先被编译为汇编指令,然后再次编译为二进制的机器可执行文件。你可以通过指定-S来查看生成的汇编指令,如gcc file.c -S

    汇编程序代码只是通过了 C 到汇编程序编译的第一阶段,然后与从 C 编译的代码没有区别。

    【讨论】:

    • 在汇编中实现函数的一种方法是写一个空的C函数,用-S编译,然后直接编辑汇编文件。
    【解决方案5】:

    一种方法是使用内联汇编程序。这意味着您可以将汇编代码直接写入您的 C 代码中。具体语法是编译器特定的。例如,请参阅 GCC syntaxMS Visual C++ syntax

    【讨论】:

      【解决方案6】:

      您可以在 C 代码中编写内联汇编。其语法是高度特定于编译器的,但通常使用 asm 关键字。查看内联汇编以获取更多信息。

      【讨论】:

        猜你喜欢
        • 2015-04-26
        • 2013-07-24
        • 2013-09-21
        • 2017-05-08
        • 2013-04-16
        • 2016-06-01
        • 2015-04-21
        • 2017-01-19
        • 2020-11-04
        相关资源
        最近更新 更多