You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何强制ARM64 GCC用指令构造双精度浮点数,规避.rodata段

强制AArch64 GCC通过指令构造浮点常量,避免使用数据段

问题说明

ARM64指令长度为32位,使用64位浮点常量时,编译器通常会将字面量存入数据段,再通过加载指令读取。但AArch64 GCC在部分场景下会通过mov/movk/fmov等指令直接构造双精度浮点数,无需依赖数据段。例如:

  • 初始化值为{5.5, 6.6}时,编译器会生成指令构造常量
  • 换成{1.1, 2.2}时,编译器默认将常量存入数据段,通过adrp+ldr加载

需要找到编译器选项强制开启指令构造浮点常量的特性,避免嵌入式代码中引入数据段。

示例汇编对比

常量存入数据段({1.1, 2.2})

000000000044fda0 <foo>: 1.1, 2.2
  44fda0:       d2800000        mov     x0, #0x0                        // #0
  44fda4:       b0000002        adrp    x2, 450000 <pmalloc+0x78>       // 计算数据段地址
  44fda8:       b0000001        adrp    x1, 450000 <pmalloc+0x78>
  44fdac:       fd472c41        ldr     d1, [x2, #3672]                 // 加载双精度常量
  44fdb0:       fd473020        ldr     d0, [x1, #3680]
  44fdb4:       6d000001        stp     d1, d0, [x0]
  ...
  44fdbc:       d65f03c0        ret

指令构造常量({5.5, 6.6})

000000000044fda0 <foo>: 5.5, 6.6
  44fda0:       d2800000        mov     x0, #0x0                        // #0
  44fda4:       b203e7e1        mov     x1, #0x6666666666666666         // 加载低64位立即数
  44fda8:       1e62d001        fmov    d1, #5.500000000000000000e+00
  44fdac:       f2e80341        movk    x1, #0x401a, lsl #48            // 拼接高16位
  44fdb0:       9e670020        fmov    d0, x1                          // 转成浮点寄存器
  44fdb4:       6d000001        stp     d1, d0, [x0]
  ...
  44fdbc:       d65f03c0        ret

环境信息

使用的编译器版本:

$ aarch64-linux-gnu-gcc --version
aarch64-linux-gnu-gcc (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.

测试用C代码(float.c):

void foo(void* base_ptr)
{
    double buffer[2]= {5.5, 6.6};
    double* q = (double*)base_ptr;
    *q++ = buffer[0];
    *q = buffer[1];
    return ;
}

int main() {
    double f[2];
    foo(f);
}

解决方案

使用-mno-fp-read-only-data编译选项,强制GCC通过指令构造所有双精度浮点常量,而非将其存入只读数据段:

aarch64-linux-gnu-gcc -mno-fp-read-only-data float.c -o float

该选项会让GCC针对所有浮点常量生成mov/movk/fmov序列,即使需要多条指令,也不会将常量写入数据段,完全符合嵌入式场景下避免数据段的需求。

注:如果允许浮点常量的近似值,可以配合-ffast-math进一步优化指令数量,但会牺牲数值精度;若需要精确值,仅使用-mno-fp-read-only-data即可。

内容的提问来源于stack exchange,提问作者Capital S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:40:25