【问题标题】:Assembly procedures called and defined in C code用 C 代码调用和定义的汇编程序
【发布时间】:2020-09-28 18:07:19
【问题描述】:

我有以下汇编代码:

global stuff
    
       stuff:
            ;do stuff

我希望从 C 代码中调用它,那么是否可以从包含它在 _asm() 中的 C 程序中调用它?

【问题讨论】:

  • 为什么不在 C 中内联它?
  • 我正在编写一个操作系统,它基本上将字节 x 写入端口 y。
  • 那么,为什么不直接内联呢?这就是 Linux 内核所做的。
  • 您是否使用reference like this 作为基准?
  • 你,你可以在全局范围内使用asm(".globl stuff\n" "stuff:\n" "...");,但通常最好在单独的文件中定义纯asm函数。

标签: c assembly gcc


【解决方案1】:

仅仅因为 Linux 做到了,就不是做某事的理由。我对使用内联汇编的使用/愿望感到困惑,但是是的,当然,有一些方法可以做到这一点,你可以很容易地弄清楚。如果您问这个问题,您还没有准备好编写操作系统。继续努力。在开始之前,您需要 C 和工具基础知识。操作系统本质上是一个大型裸机程序。

如果您标记了这个 nasm,那么您无论如何都对内联 asm 不感兴趣,只需使用真正的 asm gas 或 nasm。

这个

int fun ( void )
{
    return 5;
}

会/可以变成:

0000000000000000 <fun>:
   0:   b8 05 00 00 00          mov    $0x5,%eax
   5:   c3  

这意味着我可以做到这一点

.globl fun
fun:
    mov $0x5,%eax
    retq

还有这个

#include <stdio.h>
int fun ( void );
int main ( void )
{
    printf("%d\n",fun());
    return 0;
}

并构建一个二进制链接两个部分,运行时打印 5。

那么有了 nasm 我就可以了

global fun
fun:
    mov eax,5
    ret

在这种情况下确认它是相同的机器代码或至少是等效的。

0000000000000000 <fun>:
   0:   b8 05 00 00 00          mov    $0x5,%eax
   5:   c3                      retq 

所以我可以链接它,它也会打印 5。

所以现在我可以做一个简单的内联,非常真实的 asm,也许你在问什么

#include <stdio.h>
int fun ( void );
asm(".globl fun ; fun: mov $0x5,%eax ; retq");
int main ( void )
{
    printf("%d\n",fun());
    return 0;
}

这是使用 gcc,内联 asm 是特定于工具的,不假定是可移植的。

现在你可以从那里严重过度复杂化。

在操作系统(或任何地方)中使用抽象来执行 I/O 操作(“它基本上将字节 x 写入端口 y”)绝对是正确的做法(您不想内联类似的东西),因此,一个单独的函数,无论是真正的 asm、C 还是某种混合函数,都是值得追求的好主意。归根结底,对于像这样的访问类型功能,您需要完全控制所使用的指令,因此您选择这样做取决于您。但是在开始这样的任何工作之前,需要对工具和语言的基本使用。您可以检查现在存在的不同操作系统作为参考,但这不是您的,不是他们的,您的个人偏好不是其他人的,您对语言和工具和假设的了解不是其他人的。他们可能有一个系统级的实现,你可能看不到所有的东西,并且可以通过简单地在这里或那里复制一个片段而陷入陷阱。

【讨论】:

  • 我很抱歉标签问题,这是我的第一篇文章。
  • 我刚刚删除了标签
  • 如何将参数传递给 fun()?
  • fun() 在这个例子中不带参数,如果有,参数通常使用堆栈传递(使用(intel 语法)pushpop 指令)
猜你喜欢
  • 2013-09-21
  • 2016-06-01
  • 2013-04-16
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
  • 2011-07-20
  • 1970-01-01
  • 2011-09-04
相关资源
最近更新 更多