arm 交叉编译 thumb 与 arm 指令的方法
- 本文实现了在 x86 的 ubuntu 的机器上,使用 arm-linux-gnueabihf-gcc 交叉编译链工具,编译出在 arm 开发板上可以运行的 thumb 指令集的可执行文件。后续会使用 vscode 使用网络进行远程调试。
1. 编译器 arm-linux-gnueabihf-gcc
# arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/arm-linux-gnueabihf/11/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 11.4.0-1ubuntu1~22.04' --with-bugurl=file:///usr/share/doc/gcc-11/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-11 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libitm --disable-libquadmath --disable-libquadmath-support --enable-plugin --enable-default-pie --with-system-zlib --enable-libphobos-checking=release --without-target-system-zlib --enable-multiarch --disable-sjlj-exceptions --with-arch=armv7-a+fp --with-float=hard --with-mode=thumb --disable-werror --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=arm-linux-gnueabihf --program-prefix=arm-linux-gnueabihf- --includedir=/usr/arm-linux-gnueabihf/include --with-build-config=bootstrap-lto-lean --enable-link-serialization=2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
ubuntu 中安装方法 sudo apt-get install binutils-arm-linux-gnueabi gcc-arm-linux-gnuabihf
2. 代码中实现
使用 __attribute__((target("thumb"))) void thumb_ins(void);
指定函数编译为 thumb 指令
c
//完整的 main.c 的示例
#include <stdio.h>
__attribute__((target("thumb"))) void thumb_ins(void);
void thumb_ins(void) {
int ia = 0;
int ib = 0;
int ic = 0;
while (1) {
ia = 0;
ib = 0;
ic = 0xab;
asm volatile ("mov r0, #1");
asm volatile ("mov r4, #0");
asm volatile ("cmp r4, #0");
asm volatile ("itte eq");
asm volatile ("moveq r1, #55");
asm volatile ("moveq r2, #66");
asm volatile ("movne r2, #77");
asm volatile ("mov %0, r1" : "=r" (ia));
asm volatile ("mov %0, r2" : "=r" (ib));
asm volatile ("mov %0, r0" : "=r" (ic));
if ((ia != 55) || (ib != 66)) {
printf("error!!!");
printf(" ia %d ib %d %d\r\n", ia, ib, ic);
}
}
}
int main(void)
{
printf("I run!!! %s %s\r\n", __TIME__, __DATE__);
while (1) {
thumb_ins();
}
return 0;
}
3. 编译方法
-
编译指令
arm-linux-gnueabihf-gcc -g -static -mthumb-interwork -mthumb main.c
参数解释:
-g 添加调试信息
-static 使用静态链接的方式
-mthumb 使用 thumb 指令集
-mthumb-interwork 支持 arm 与 thumb 混合
-
反汇编查看是否正确
arm-linux-gnueabihf-objdump -S a.out > a.asm
attribute((target("thumb"))) void thumb_ins(void);
void thumb_ins(void) {
10438: b580 push {r7, lr}
1043a: b084 sub sp, #16
1043c: af00 add r7, sp, #0
int ia = 0;
1043e: 2300 movs r3, #0
10440: 607b str r3, [r7, #4]
int ib = 0;
10442: 2300 movs r3, #0
10444: 60bb str r3, [r7, #8]
int ic = 0;
10446: 2300 movs r3, #0
10448: 60fb str r3, [r7, #12]while (1) { ia = 0; 1044a: 2300 movs r3, #0 1044c: 607b str r3, [r7, #4] ib = 0; 1044e: 2300 movs r3, #0 10450: 60bb str r3, [r7, #8] ic = 0xab; 10452: 23ab movs r3, #171 ; 0xab 10454: 60fb str r3, [r7, #12] asm volatile ("mov r0, #1"); 10456: f04f 0001 mov.w r0, #1 asm volatile ("mov r4, #0"); 1045a: f04f 0400 mov.w r4, #0 asm volatile ("cmp r4, #0"); 1045e: 2c00 cmp r4, #0 asm volatile ("itte eq"); 10460: bf06 itte eq asm volatile ("moveq r1, #55"); 10462: 2137 moveq r1, #55 ; 0x37 asm volatile ("moveq r2, #66"); 10464: 2242 moveq r2, #66 ; 0x42 asm volatile ("movne r2, #77"); 10466: 224d movne r2, #77 ; 0x4d asm volatile ("mov %0, r1" : "=r" (ia)); 10468: 460b mov r3, r1 1046a: 607b str r3, [r7, #4] asm volatile ("mov %0, r2" : "=r" (ib)); 1046c: 4613 mov r3, r2 1046e: 60bb str r3, [r7, #8] asm volatile ("mov %0, r0" : "=r" (ic)); 10470: 4603 mov r3, r0 10472: 60fb str r3, [r7, #12] if ((ia != 55) || (ib != 66)) { 10474: 687b ldr r3, [r7, #4] 10476: 2b37 cmp r3, #55 ; 0x37 10478: d102 bne.n 10480 <thumb_ins+0x48> 1047a: 68bb ldr r3, [r7, #8] 1047c: 2b42 cmp r3, #66 ; 0x42 1047e: d0e4 beq.n 1044a <thumb_ins+0x12> printf("error!!!"); 10480: 4b06 ldr r3, [pc, #24] ; (1049c <thumb_ins+0x64>) 10482: 447b add r3, pc 10484: 4618 mov r0, r3 10486: f004 fb67 bl 14b58 <_IO_printf> printf(" ia %d ib %d %d\r\n", ia, ib, ic); 1048a: 68fb ldr r3, [r7, #12] 1048c: 68ba ldr r2, [r7, #8] 1048e: 6879 ldr r1, [r7, #4] 10490: 4803 ldr r0, [pc, #12] ; (104a0 <thumb_ins+0x68>) 10492: 4478 add r0, pc 10494: f004 fb60 bl 14b58 <_IO_printf> ia = 0; 10498: e7d7 b.n 1044a <thumb_ins+0x12> 1049a: bf00 nop 1049c: 0003f1be .word 0x0003f1be 104a0: 0003f1ba .word 0x0003f1ba
000104a4 <main>:
}
}
最后将 a.out 放入目标板卡使用 chmod +x
添加执行权限,即可运行。