购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.6
工具链

在Linux的编程中,通常使用GNU工具链编译Bootloader、内核和应用程序。GNU组织维护了GCC、GDB、glibc、Binutils等,分别见于 https://gcc.gnu.org/ https://www.gnu.org/software/gdb/ https://www.gnu.org/software/libc/ https://www.gnu.org/software/binutils/

图3.12 crosstool-ng的配置菜单

建立交叉工具链的过程相当烦琐,一般可以通过类似crosstool-ng这样的工具来做。crosstool-ng也采用了与内核相似的menuconfig配置方法。在官网 http://www.crosstool-ng.org/ 上下载crosstool-ng的源代码并编译安装后,运行ct-ng menuconfig,会出现如图3.12的配置菜单。在里面我们可以选择目标机处理器型号,支持的内核版本号等。

当然,也可以直接下载第三方编译好的、开放的、针对目标处理器的交叉工具链,如在 http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/ 上可以下载针对ARM、MIPS、高通Hexagon、Altera Nios II、Intel、AMD64等处理器的工具链,在 http://www.linaro.org/downloads/ 可以下载针对ARM的工具链。

目前,在ARM Linux的开发中,人们趋向于使用Linaro( http://www.linaro.org/ )工具链团队维护的ARM工具链,它以每月一次的形式发布新的版本,编译好的可执行文件可从网址 http://www.linaro.org/downloads/ 下载。Linaro是ARM Linux领域中最著名最具技术成就的开源组织,其会员包括ARM、Broadcom、Samsung、TI、Qualcomm等,国内的海思、中兴、全志和中国台湾的MediaTek也是它的会员。

一个典型的ARM Linux工具链包含arm-linux-gnueabihf-gcc(后续工具省略前缀)、strip、gcc、objdump、ld、gprof、nm、readelf、addr2line等。用strip可以删除可执行文件中的符号表和调试信息等来实现缩减程序体积的目的。gprof在编译过程中在函数入口处插入计数器以收集每个函数的被调用情况和被调用次数,检查程序计数器并在分析时找出与程序计数器对应的函数来统计函数占用的时间。objdump是反汇编工具。nm则用于显示关于对象文件、可执行文件以及对象文件库里的符号信息。其中,前缀中的“hf”显示该工具链是完全的硬浮点,由于目前主流的ARM芯片都自带VFP或者NEON等浮点处理单元(FPU),所以对硬浮点的需求就更加强烈。Linux的浮点处理可以采用完全软浮点,也可以采用与软浮点兼容,但是使用FPU硬件的softfp,以及完全硬浮点。具体的ABI(Application Binary Interface,应用程序二进制接口)通过-mfloat-abi=参数指定,3种情况下的参数分别是-mfloat-abi=soft/softfp/hard。

在以前,主流的工具链采用“与软浮点兼容,但是使用FPU硬件的softfp”。softfp使用了硬件的FPU,但是函数的参数仍然使用整型寄存器来传递,完全硬浮点则直接使用FPU的寄存器传递参数。

下面一段程序:

float mul(float a, float b)
{
        return a * b;
}
void main(void)
{
        printf("1.1 * 2.3 = %f\n", mul(1.1, 2.3));
}

对其使用arm-linux-gnueabihf-gcc编译并反汇编的结果是:

000 08394 <mul>:
     8394:       b480        push  {r7}
     8396:       b083        sub  sp, #12
     8398:       af00        add  r7, sp, #0
     839a:       ed87 0a01   vstr  s0, [r7, #4](null)
     839e:       edc7 0a00   vstr  s1, [r7]
     83a2:       ed97 7a01   vldr  s14, [r7, #4](null)
     83a6:       edd7 7a00   vldr  s15, [r7]
     83aa:       ee67 7a27   vmul.f32  s15, s14, s15
     83ae:       eeb0 0a67   vmov.f32  s0, s15
     83b2:       f107 070c   add.w  r7, r7, #12
     83b6:       46bd        mov  sp, r7
     83b8:       bc80        pop  {r7}
     83ba:       4770        bx lr

0000 83bc <main>:
     83bc:       b580        push  {r7, lr}
     83be:       af00        add  r7, sp, #0
     83c0:       ed9f 0a09   vldr  s0, [pc, #36](null)  ; 83e8 <main+0x2c>
     83c4:       eddf 0a09   vldr  s1, [pc, #36](null)  ; 83ec <main+0x30>
     83c8:       f7ff ffe4   b8394 <mul>
     83cc:       eef0 7a40   vmov.f32  s15, s0
     83d0:       eeb7 7ae7   vcvt.f64.f32  d7, s15
     83d4:       f248 4044   movw  r0, #33860  ; 0x8444
     83d8:       f2c0 0000   movt  r0, #0
     83dc:       ec53 2b17   vmov  r2, r3, d7
     83e0:       f7ff ef82   blx  82e8 <_init+0x20>
     83e4:       bd80        pop  {r7, pc}
     83e6:       bf00        nop

而使用没有“hf”前缀的arm-linux-gnueabi-gcc编译并反汇编的结果则为

000 0838c <mul>:
     838c:       b480        push  {r7}
     838e:       b083        sub  sp, #12
     8390:       af00        add  r7, sp, #0
     8392:       6078        str  r0, [r7, #4]
     8394:       6039        str  r1, [r7, #0]
     8396:       ed97 7a01   vldr  s14, [r7, #4](null)
     839a:       edd7 7a00   vldr  s15, [r7]
     839e:       ee67 7a27   vmul.f32  s15, s14, s15
     83a2:       ee17 3a90   vmov  r3, s15
     83a6:       4618        mov  r0, r3
     83a8:       f107 070c   add.w  r7, r7, #12
     83ac:       46bd        mov  sp, r7
     83ae:       bc80        pop  {r7}
     83b0:       4770        bx lr
     83b2:       bf00        nop

000 083b4 <main>:
     83b4:       b580        push  {r7, lr}
     83b6:       af00        add  r7, sp, #0
     83b8:       4808        ldr  r0, [pc, #32]  ; (83dc <main+0x28>)
     83ba:       4909        ldr  r1, [pc, #36]  ; (83e0 <main+0x2c>)
     83bc:       f7ff ffe6   bl  838c <mul>
     83c0:       ee07 0a90   vmov  s15, r0
     83c4:       eeb7 7ae7   vcvt.f64.f32  d7, s15
     83c8:       f248 4038   movwr0, #33848     ; 0x8438
     83cc:       f2c0 0000   movtr0, #0
     83d0:       ec53 2b17   vmovr2, r3, d7
     83d4:       f7ff ef84   blx  82e0 <_init+0x20>
     83d8:       bd80        pop  {r7, pc}
     83da:       bf00        nop

关注其中加粗的行,可以看出前面的汇编使用s0和s1传递参数,后者则仍然使用ARM的r0和r1。测试显示一个含有浮点运算的程序若使用hard ABI会比softfp ABI快5%~40%,如果浮点负载重,结果可能会快200%以上。 URfRRV4yrY/ok/xZfMk7SPHQt9lZ3gVrT14wvgQ5hBTZiLOspQ9ay4v7+of4+80o

点击中间区域
呼出菜单
上一章
目录
下一章
×