我在开发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来说真的很陌生。我希望能有效地得到答案。谢谢。
答案 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调用它(至少,这并不容易)。