arm-none-eabi-gcc编译、链接选项详解

文章详细介绍了GCC编译器的一些关键选项,如-mthumb和-marm用于选择ARM指令集的版本,-mfloat-abi选择浮点运算的软硬件实现,-fno-builtin解决自定义函数与内置函数冲突,以及-fdata-sections和-ffunction-sections用于代码分割和裁剪。这些选项对于嵌入式系统开发尤其重要,能有效控制代码大小和性能。

1、-mthumb-mthumb-interwork

"-mthumb”的意义是:使用这个编译选项生成的目标文件是Thumb指令的,目前还没有发现GNU编译器中有哪一个选项可以指定生成的目标文件是thumb-2的。

相对应的,“-marm“的意义是,使用编译选项生成的目标文件是ARM指令的。

注意,不同编译器对该选项是否默认开启是不一样的,实际测试的结果如下:

arm-none-eabi-gcc (20160919) 为Cortex-m4编译,(-mcpu=cortex-m4),不加-mthumb选项,提示“target CPU does not support ARM mode”(Cortex-M处理器只支持Thumb指令,包含16位和32位);

arm-none-eabi-gcc (20191025) 为Cortex-m4编译,(-mcpu=cortex-m4),不加-mthumb选项,可以顺利通过编译。

"-mthumb-interwork ”编译选项生成的目标文件就是thumb的,但是可以被其他的ARM的目标文件交叉调用。

一般如果工程中需要一部分文件目标文件编译为ARM指令,一部分目标文件编译为Thumb指令时, 可以在这两部分的编译选项中都加入"-mthumb-interwork”选项,这样就可以在后面将这两部分链接为一个可执行文件,例如:

arm-elf-gcc -mthumb-interwork -marm -c arm.c -o arm.o 
arm-elf-gcc -mthumb-interwork -mthumb -c thumb.c -o thumb.o 
arm-elf-gcc -mthumb-interwork arm.o thumb.o -o a.out

2、-mfloat-abi=softfp 和 -mfloat-abi=hard

该选项指定了浮点运算的实现方式,用软件计算还是硬件计算。实际使用中需要根据硬件特性(是否支持硬件浮点单元)以及链接的Lib库(包括libc,libm等)类型进行选择,如果不匹配链接时会出现"VFP register arguments"错误(VFP=Virtual Float Point,虚拟浮点运算)。

如果不加以指定,默认使用-mfloat-abi=softfp 软件浮点方式。

3、-fno-builtin

-fno-builtin用于解决当用户自定义的函数与C语言的内建函数(C库函数)冲突的问题。当用户自定义的函数与内建函数冲突时,若在gcc的编译选项中加上-fno-builtin时,则表示不使用C语言的内建函数

对于有些函数不想用内建函数,而其他的某些函数还是希望使用内建函数时的场景,那么可以使用 -fno-builtin-function 选项,其中的function就是冲突的函数名,例如-fno-builtin-printf。

4、-fdata-sections-ffunction-sections

-fdata-sections用于将每个符号创建为一个sections,其中每个sections名与data名保持一致

-ffunction-sections用于将每个函数创建为一个sections,其中每个sections名与function名保持一致。

用于代码的分割和裁剪,会将每一个函数都拆分成.text、.rodata、.data、.bss段,这部分和对象文件的链接有关。加上这两个参数,配合链接器可以去除代码中无用的部分,减少代码大小。如果没有这两个参数,编译器就会按文件分段而不是按照函数分段。

5、-fno-common

-fno-common用于未初始化的全局变量当成强符号,重复定义就会报错

6、-Xlinker -print-memory-usage

-Xlinker -print-memory-usage用于打印各段实际使用情况

LDFLAGS += -Xlinker -print-memory-usage

效果:

Memory region         Used Size  Region Size  %age Used
          ATCM_I:          0 GB        16 KB      0.00%
          ATCM_D:         184 B        32 KB      0.56%
          DTCM_I:          0 GB        48 KB      0.00%
        RAM_QSPI:          0 GB        16 MB      0.00%
         RAM_DEV:          0 GB         1 MB      0.00%
        RAM_DEV1:          0 GB      1152 KB      0.00%
        RAM_DEV2:          0 GB         1 MB      0.00%
        RAM_ARM0:         576 B        48 KB      1.17%
       RAM_SHARE:          0 GB        48 KB      0.00%
        RAM_ARM1:      102844 B       160 KB     62.77%
        ROX_ARM1:       23587 B       352 KB      6.54%
         XIP_ARM:      313852 B      1536 KB     19.95%

参考资料:

GCC部分编译选项解析 - DF11G - 博客园 (cnblogs.com)

arm-none-eabi-gcc编译选项(ChibiOS)_uav360的博客-优快云博客_arm-none-eabi-gcc

利用gcc-arm-none-eabi开源工具链开发STM32程序 (copyfuture.com)

<think>好的,我现在需要帮助用户了解如何使用arm-none-eabi-gcc编译汇编文件的具体命令和参数。首先,我需要回顾之前的对话历史,确保这次回答符合用户的需求,并且正确引用之前的资料。 用户之前的问题是关于如何在GCC汇编文件中包含其他文件,我的回答详细介绍了使用.include指令和C预处理器的两种方法,并提到了编译时的参数,比如使用-x assembler-with-cpp来启用预处理器。现在用户的新问题是如何使用arm-none-eabi-gcc编译汇编文件,具体命令和参数是什么。 接下来,我需要参考用户提供的三个引用内容。引用[1]提到,使用arm-none-eabi-gcc而不是直接使用链接器,因为对混合C/C++和汇编的支持更好。引用[2]解释了arm-none-eabi-gcc是用于ARM架构的交叉编译器,遵循EABI标准。引用[3]中的用户遇到了编译汇编文件时的问题,特别是注释无法识别,这可能与文件扩展名或预处理器有关。 用户现在的问题是具体的编译命令和参数,所以需要分步骤解释。首先,确定汇编文件的扩展名是.s还是.S,因为.S会触发预处理器,而.s不会。然后,是否需要预处理,比如使用#include宏或条件编译。接着,编译到对象文件,最后链接生成可执行文件。 我需要考虑用户的潜在需求。用户可能是在进行嵌入式开发,比如STM32的启动文件,如startup_stm32f10x_hd.S,这通常需要预处理。因此,正确的编译参数包括启用预处理器,指定目标架构,包含头文件路径,处理不同的注释风格(比如ARM汇编中使用@,而GAS可能使用#),以及链接时的选项,比如指定链接脚本和入口点。 还需要注意用户可能遇到的常见问题,比如汇编器不识别注释,这可能是因为文件扩展名错误导致预处理器未启用,或者注释风格不兼容。例如,在.S文件中使用C风格的/* */注释需要预处理器处理,而.s文件可能不支持。 另外,用户可能需要将汇编代码与C代码混合编译,因此需要说明如何一起编译链接。例如,先分别编译.s和.c文件为.o,然后链接在一起。 最后,根据用户提供的引用,特别是引用[1]中的建议,使用arm-none-eabi-gcc进行链接而不是直接调用ld,这样可以更好地处理库和启动文件。 总结,回答的结构应该包括:基本编译步骤、启用预处理器、指定架构和CPU、包含路径处理、生成中间文件、链接步骤、处理不同注释风格、完整示例命令以及常见问题解决。同时,相关问题可以引导用户进一步了解优化、混合编译链接脚本的使用。</think>以下是使用`arm-none-eabi-gcc`编译汇编文件的具体命令和参数说明,结合引用内容和实际编译需求: --- ### 一、基本编译流程 #### 1. **单汇编文件编译** ```bash arm-none-eabi-gcc -c -mcpu=cortex-m3 -mthumb -o output.o input.s ``` - **`-c`**:仅编译链接,生成目标文件(`.o`) - **`-mcpu=cortex-m3`**:指定目标CPU架构(根据具体芯片调整) - **`-mthumb`**:生成Thumb指令集代码(ARM Cortex-M系列必须) - **`input.s`**:输入的汇编文件(扩展名`.s`或`.S`) --- #### 2. **需要预处理的情况(含`#include`或宏)** 若汇编文件使用`#include`或C预处理指令(如`#ifdef`),需: - 将文件扩展名改为`.S`(大写S) - 添加`-x assembler-with-cpp`参数: ```bash arm-none-eabi-gcc -c -x assembler-with-cpp -mcpu=cortex-m3 -mthumb -o startup.o startup.S ``` - **`-x assembler-with-cpp`**:强制启用预处理器(解决引用[3]中的注释解析问题) --- ### 二、关键参数详解 #### 1. **架构与指令集** - **`-mcpu=<name>`**:指定CPU型号(如`cortex-m4`, `cortex-a7`) - **`-mthumb`**:Thumb模式(Cortex-M必选) - **`-mfloat-abi=hard/softfp`**:浮点运算配置(若芯片支持) #### 2. **包含路径与宏定义** - **`-I<path>`**:添加头文件搜索路径(用于`#include`) - **`-D<macro>`**:定义预处理宏(如`-DSTM32F10X_HD`) #### 3. **生成中间文件** - **`-Wa,-adhln=<file.lst>`**:生成汇编与机器码对照的列表文件 --- ### 三、完整编译链接示例 #### 1. **编译汇编文件** ```bash arm-none-eabi-gcc -c -x assembler-with-cpp \ -mcpu=cortex-m3 -mthumb \ -I./include \ -DUSE_STDPERIPH_DRIVER \ -o startup_stm32f10x_hd.o \ startup_stm32f10x_hd.S ``` #### 2. **链接生成最终二进制** ```bash arm-none-eabi-gcc -nostartfiles \ -T stm32f103c8t6.ld \ -Wl,--gc-sections \ -o firmware.elf \ startup_stm32f10x_hd.o main.o ``` - **`-nostartfiles`**:禁用默认启动文件(嵌入式常用) - **`-T <linker_script.ld>`**:指定链接脚本(定义内存布局) - **`-Wl,--gc-sections`**:删除未使用的代码段(引用[1]中推荐的完整流程) --- ### 四、常见问题解决 #### 1. **注释解析错误** - **问题**:汇编文件中的`@`或`/* */`注释报错(引用[3]) - **解决**: - 确保使用`.S`扩展名并添加`-x assembler-with-cpp` - 统一使用GAS支持的注释风格(`@`或`#`) #### 2. **混合编译C与汇编** ```bash # 编译C文件 arm-none-eabi-gcc -c -mcpu=cortex-m3 -mthumb -o main.c main.o # 链接所有.o文件 arm-none-eabi-gcc -o firmware.elf startup.o main.o -T link.ld ``` (遵循引用[1]中推荐用`gcc`代替直接调用链接器的原则) --- ### 五、完整命令示例(STM32启动文件) ```bash # 启用预处理器 + 指定架构 + 包含路径 arm-none-eabi-gcc -x assembler-with-cpp \ -mcpu=cortex-m3 -mthumb \ -I./Drivers/CMSIS/Include \ -DSTM32F10X_HD \ -c startup_stm32f10x_hd.S -o startup.o # 链接并生成hex文件 arm-none-eabi-gcc -T stm32_flash.ld -o firmware.elf startup.o system.o main.o arm-none-eabi-objcopy -O ihex firmware.elf firmware.hex ``` --- ### 相关问题 1. 如何为ARM Cortex-M系列配置链接脚本? 2. `arm-none-eabi-gcc`编译优化选项(`-O1/-O2`)对汇编代码的影响? 3. 如何将汇编函数与C代码混合调用(参数传递规则)?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值