限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。
本文记录开发过程中遇到的各种值得记录的 arm gcc 交叉编译器选项,将会持续更新。
某天编写了简单程序:
int main(void)
{
int i = 3 + 5;
return 0;
}
编译:
arm-linux-gnueabihf-gcc -o test test.c
出于某种目的,反汇编看了下代码:
arm-linux-gnueabihf-objdump -D test > test.S
/* 我们只看 main() 函数部分,这样容易对应到前面的代码 */
000103a0 <main>:
103a0: b480 push {r7} // 2 字节 thumb 指令
103a2: b083 sub sp, #12
103a4: af00 add r7, sp, #0
103a6: 2308 movs r3, #8
103a8: 607b str r3, [r7, #4]
103aa: 2300 movs r3, #0
103ac: 4618 mov r0, r3
103ae: 370c adds r7, #12
103b0: 46bd mov sp, r7
103b2: f85d 7b04 ldr.w r7, [sp], #4 // 4 字节 arm 指令
103b6: 4770 bx lr
啥情况?既有多条 2 字节的 thumb 指令,还有 1 条 4字节的 arm 指令
!原来,根据编译器的默认配置,编译器会默认生成某种模式(thumb 或 arm
)指令。那怎么查看这个默认配置呢?答案是通过查看 gcc 编译器 --verbose
选项输出结果中的 --with-mode=
配置项:
$ arm-linux-gnueabihf-gcc --verbose
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/home/bill/Work/Private/qemu-lab/arm-ubuntu/tool/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/5.3.1/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: /home/tcwg-buildslave/workspace/tcwg-make-release/label/tcwg-x86_64-ex40/target/arm-linux-gnueabihf/snapshots/gcc-linaro-5.3-2016.02/configure SHELL=/bin/bash --with-bugurl=https://bugs.linaro.org --with-mpc=/home/tcwg-buildslave/workspace/tcwg-make-release/label/tcwg-x86_64-ex40/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu --with-mpfr=/home/tcwg-buildslave/workspace/tcwg-make-release/label/tcwg-x86_64-ex40/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu --with-gmp=/home/tcwg-buildslave/workspace/tcwg-make-release/label/tcwg-x86_64-ex40/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu --with-gnu-as --with-gnu-ld --disable-libstdcxx-pch --disable-libmudflap --with-cloog=no --with-ppl=no --with-isl=no --disable-nls --enable-c99 --with-tune=cortex-a9 --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --disable-multilib --enable-multiarch --with-build-sysroot=/home/tcwg-buildslave/workspace/tcwg-make-release/label/tcwg-x86_64-ex40/target/arm-linux-gnueabihf/_build/sysroots/arm-linux-gnueabihf --enable-lto --enable-linker-build-id --enable-long-long --enable-shared --with-sysroot=/home/tcwg-buildslave/workspace/tcwg-make-release/label/tcwg-x86_64-ex40/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu/arm-linux-gnueabihf/libc --enable-languages=c,c++,fortran,lto --enable-checking=release --disable-bootstrap --with-bugurl=https://bugs.linaro.org --build=x86_64-unknown-linux-gnu --host=x86_64-unknown-linux-gnu --target=arm-linux-gnueabihf --prefix=/home/tcwg-buildslave/workspace/tcwg-make-release/label/tcwg-x86_64-ex40/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu
Thread model: posix
gcc version 5.3.1 20160113 (Linaro GCC 5.3-2016.02)
我们看到,这个交叉编译器的 --with-mode=thumb
的配置为 thumb
,所以默认情况下,该交叉编译器将生成 thumb 指令
(也可能夹有 arm 指令
)。要改变这种行为,第1种途径是编译交叉编译器的时候,改变 --with-mode=
配置;第2种途径是,通过 -marm 编译选项
,来指示编译器来生成 arm 指令
。还是前面的测试代码,我们看用 -marm 选项
编译后的结果:
$ arm-linux-gnueabihf-gcc -marm -o test test.c
$ arm-linux-gnueabihf-objdump -D test > test.S
000103a0 <main>:
103a0: e52db004 push {fp} ; (str fp, [sp, #-4]!)
103a4: e28db000 add fp, sp, #0
103a8: e24dd00c sub sp, sp, #12
103ac: e3a03008 mov r3, #8
103b0: e50b3008 str r3, [fp, #-8]
103b4: e3a03000 mov r3, #0
103b8: e1a00003 mov r0, r3
103bc: e24bd000 sub sp, fp, #0
103c0: e49db004 pop {fp} ; (ldr fp, [sp], #4)
103c4: e12fff1e bx lr
哈,现在我们的代码全部使用 arm 指令
了。当然,也可以通过 -mthumb
来指示编译器生成 thumb 指令
。
https://gcc.gnu.org/onlinedocs/