Jetson TK下如何写汇编语言

时间:2022-03-09 12:45:53

首先,可以根据http://www.cnblogs.com/zenny-chen/p/3816620.html来安装CUDA工具链。这个工具集里包含了CUDA编译器以及其它必要的工具。然后,我们进入/usr/local/cuda-6.0/samples/0_Simple 目录下找到最简单的vectorAdd文件夹,把它复制到你Home目录下的某个子目录下。然后,我们在命令行(terminal)使用cd命令进入此目录。注意,Ubuntu下可以直接把文件夹或文件拖进命令行,这样就把该文件夹或文件的绝对路径复制到命令行里了。

由于,我们使用Jetson的时候,往往会用CUDA,所以会跟CUDA一起编译连接。而CUDA的源文件(.cu)最终会被翻译为C++源文件(.cpp),而CUDA源文件里又不能使用连接存储指定符(Link Storage Specifier,比如extern "C"),因此,如果我们要使用汇编源文件的外部函数,必须得另写一个.cpp文件——C++源文件是可以通过extern "C"来找到C语言或汇编语言的外部符号的,在C++源文件里使用汇编源文件的外部函数。


因此,我们第一步是要在vectorAdd里新增两个文件,一个叫testASM.s(汇编源文件),一个叫hello.cpp(C++源文件)。

然后,我们编辑testASM.s:

 1 .text
2 .align 4
3
4 .globl MyASMTest
5
6 .thumb
7
8 MyASMTest:
9
10 add r0, r0, r1
11 vadd.i32 q0, q0, q0
12 bx lr

注意上述第6行,.thumb指示符,由于NVCC编译器默认使用Thumb-2指令集来编译所有源文件,而此工具链比较矬,不支持-mthumb-interwork编译选项,因此无法混编ARM与Thumb代码。因此,我们要么在汇编源文件里写.thumb,如果用.arm的话,那么得修改编译选项(后面会讲),把编译选项默认设置为ARM即可。


然后,我们看看hello.cpp的内容:

#include <stdio.h>

extern "C" int MyASMTest(int, int);

void HelloTest(void)
{
printf(
"The vaue is: %d\n", MyASMTest(10, 20));
}


最后,我们在默认的vectorAdd.cu源文件里,找到main函数最后的return 0;语句,在上面插入以下代码:

extern void HelloTest(void);

HelloTest();


这样,所有源文件都编辑好了。下面,我们需要修改makefile文件来把新增的源文件都参加编译与连接。

对于此MakeFile,我们从上到下来看:

首先,我们找到EXTRA_CCFLAGS这个符号,这里可以定义额外的编译选项。如果我们要把源文件都默认编译为ARM指令集,那么可以将其修改为:

EXTRA_CCFLAGS    ?= -marm

由于我们在汇编文件里动用了NEON指令集,因此我们需要增加-mfpu=neon命令,因此,我们可以这么加:

如果之前已经动用了?=,那么我们再添加使用+=。EXTRA_CCFLAGS ?= -mfpu=neon

然后,我们找到build: vectorAdd

我们复制vectorAdd.o:vectorAdd.cu以及下面的编译选项语句,然后粘贴到下一行(中间最好空一行,更容易查看),将vectorAdd.o改为testASM.o,把vectorAdd.cu改为testASM.s,然后编译选项不用动。

然后再粘贴一行,同样,把vectorAdd.o改为hello.o;把vectorAdd.cu改为hello.cpp。

OK,这样就把需要编辑的源文件都添加好了。后面再添加连接目标文件。在下一行,我们发现vectorAdd:  vectorAdd.o后面再把testASM.o与hello.o添加上即可——vectorAdd:  vectorAdd.o testASM.o hello.o

最后,我们在clean:里把需要清除的.o都加上,即上述的testASM.o hello.o。这样,我们就可以通过make clean很快把生成的目标文件都删除了。


这里顺带说一下,我们找到GCC这个符号,会看到默认采用g++。这样不管什么.c还是.cpp都会默认使用G++编译器来编译,即最后是C++文件。如果我们想编译为.c源文件(再加上支持C11标准),我们可以直接改用gcc。比如,我们再增加一个源文件,名字为pureC.c,内容如下:

int MySum(void)
{
int buffer[] = { [0] = 10, [2] = -5, [4] = 16, [7] = -1 };
int sum = 0;
for(int i = 0; i < sizeof(buffer) / sizeof(buffer[0]); i++)
sum
+= buffer[i];

return sum;
}

我们可以在hello.cpp中调用此函数。增加此源文件时,需要修改一下MakeFile,首先,我们在ALL_CCFLAGS符号定义下,ALL_LDFLAGS符号定义的上面插入以下makefile命令:

MY_CFLAGS := $(CCFLAGS)
MY_CFLAGS
+= $(EXTRA_CCFLAGS)
MY_CFLAGS
+= -std=gnu11

最下面的-std=gnu11就是启用了满足GNU规范的C11标准。然后,我们添加pureC.o:pureC.c

gcc $(INCLUDES) $(MY_CFLAGS) -o $@ -c $<

连接选项和make清除都一样加。这样,我们的PureC就能跑起来了。