如何在C中使用asm函数

时间:2017-04-27 11:22:58

标签: c assembly

我在开发hadoop源代码方面遇到了问题。我需要在asm库中使用函数。例如,给出了API: uint32_t func(uint32_t var1,const char var2,uint64_t var3)。 如何使用此函数并在C程序中获取返回值?我总是得到undefined reference to "a function name(which I want to use asm api)"。 我是否需要在C或其他地方添加一些典型的声明?

对于专业的C程序员来说似乎很容易,并且没有值得提出的问题。但我是一名Java程序员,对ASM和C来说真的很陌生。我希望能有效地得到答案。谢谢。

2 个答案:

答案 0 :(得分:1)

让我们以gnu为例,gcc和语言本身告诉我们,如果我们将一个函数声明为static,那么它就不可用于其他.c文件。在gnu汇编语言和汇编语言由汇编程序定义而不是某些通用语言标准,标签是本地的,除非声明为全局。

hello:
.globl there
there:

我们无法链接到你好,但我们可以链接到那里。

然后你需要知道调用约定,你可以查找并阅读它和/或做实验来弄清楚它。即使您阅读它以确保您使用的编译器符合您正在阅读的编译器,您仍然应该进行实验,您使用的编译器将符合它使用的任何标准,而不是您希望它使用的标准。 ,所以让你的asm匹配...

unsigned int fun ( unsigned int a, unsigned int b )
{
    return((a<<2)+b);
}

给出

00000000 <fun>:
   0:   e0810100    add r0, r1, r0, lsl #2
   4:   e12fff1e    bx  lr

这是arm,在这种情况下,如果参数适合,参数将在r0,r1,r2,r3中传递,如果有更多,则转到堆栈。返回值如果适合则在r0中,有很多例外。你可以在函数中销毁r0-r3但是必须保留r4(可能有一个例外)。所以在这种情况下,r0向左移动2并加到r1,所以r0是a,r1必须是b,并且每次实验的返回值都是r0。

00000000 <fun>:
   0:   0f 5f           rla r15     
   2:   0f 5f           rla r15     
   4:   0f 5e           add r14,    r15 
   6:   30 41           ret 

使用另一个指令集r15似乎是a和r14 b,答案在r15中返回

00000000 <_fun>:
   0:   1166            mov r5, -(sp)
   2:   1185            mov sp, r5
   4:   1d40 0004       mov 4(r5), r0
   8:   0cc0            asl r0
   a:   0cc0            asl r0
   c:   6d40 0006       add 6(r5), r0
  10:   1585            mov (sp)+, r5
  12:   0087            rts pc

而另一个指令集使用堆栈

我建议您使用C中的C调用asm函数的原型,然后编译它并从那里反汇编并构建asm。实际组装它要容易得多,而不是尝试使用内联汇编,这是一个高级主题并且非常依赖于编译器,如果你不使用内联汇编,你有更好的工作机会。

所以例如我会学习所学知识并创建

.globl myfun
myfun:
   add r0,r1,r0, lsl #2
   bx lr

然后我可以组装它并将其链接到任何想要用两个参数调用myfun的人。或者我可以使用这些知识用这两个参数做其他事情来创建返回值。

答案 1 :(得分:0)

如果需要从Java调用C或程序集,请使用JNI或其替代方法。要调用程序集,请创建一个小的C包装函数来模拟程序集应该执行的操作,然后使用Java程序对其进行编译和调试(验证您是否可以传递参数,获取返回值)。

当这工作时,专注于从C调用实际的程序集。这实际上取决于“asm库”,它应该有如何从C调用它的文档。

请注意,汇编库通常需要某些CPU架构。例如,如果库是针对Intel 32位的,则无法从Java VM为64位ARM调用它(至少,这并不容易)。