assembly - 强制 arm64 gcc 使用指令构造 double float ,无 .rodata 部分

标签 assembly gcc floating-point arm64 immediate-operand

ARM64 指令是 32 位长,所以如果要使用 64 位浮点常数,通常使用数据段来存储文字。

但是,我发现在某些情况下,AArch64 gcc 编译器使用多条指令从立即数构造 double float ,而不是将常量存储在数据部分中。有没有办法强制执行此功能?

我不想在我的嵌入式代码中引入数据部分。

000000000044fda0 <foo>: 1.1, 2.2
  44fda0:       d2800000        mov     x0, #0x0                        // #0
  44fda4:       b0000002        adrp    x2, 450000 <pmalloc+0x78>       // cal data address
  44fda8:       b0000001        adrp    x1, 450000 <pmalloc+0x78>
  44fdac:       fd472c41        ldr     d1, [x2, #3672]                 // load the double
  44fdb0:       fd473020        ldr     d0, [x1, #3680]
  44fdb4:       6d000001        stp     d1, d0, [x0]
  ...
  44fdbc:       d65f03c0        ret


000000000044fda0 <foo>: 5.5, 6.6
  44fda0:       d2800000        mov     x0, #0x0                        // #0
  44fda4:       b203e7e1        mov     x1, #0x6666666666666666         // #7378697629483820646
  44fda8:       1e62d001        fmov    d1, #5.500000000000000000e+00
  44fdac:       f2e80341        movk    x1, #0x401a, lsl #48
  44fdb0:       9e670020        fmov    d0, x1
  44fdb4:       6d000001        stp     d1, d0, [x0]
  ...
  44fdbc:       d65f03c0        ret

我希望 gcc 不要像我展示的第二个 foo 函数那样使用任何数据部分来构造双浮点文字或整型文字。

我使用的是以下 gcc 编译器

$ 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);
}

对于{5.5, 6.6},编译器将通过移位和位或指令构造文字。但是,当您将 {5.5, 6.6} 更改为 {1.1, 2.2} 时,编译器会将常量文字存储在数据部分并使用 adrp指令加载地址并获取它们。

{5.5, 6.6}

$ aarch64-linux-gnu-gcc float.c
$ aarch64-linux-gnu-objdump -d a.out  | grep -A15 '<foo>:'
00000000000007b4 <foo>:
 7b4:   a9bc7bfd        stp     x29, x30, [sp, #-64]!
 7b8:   910003fd        mov     x29, sp
 7bc:   f9000fa0        str     x0, [x29, #24]
 7c0:   90000080        adrp    x0, 10000 <__FRAME_END__+0xf6d8>
 7c4:   f947f000        ldr     x0, [x0, #4064]
 7c8:   f9400001        ldr     x1, [x0]
 7cc:   f9001fa1        str     x1, [x29, #56]
 7d0:   d2800001        mov     x1, #0x0                        // #0
 7d4:   1e62d000        fmov    d0, #5.500000000000000000e+00
 7d8:   fd0017a0        str     d0, [x29, #40]
 7dc:   b203e7e0        mov     x0, #0x6666666666666666         // #7378697629483820646
 7e0:   f2e80340        movk    x0, #0x401a, lsl #48
 7e4:   9e670000        fmov    d0, x0
 7e8:   fd001ba0        str     d0, [x29, #48]
 7ec:   f9400fa0        ldr     x0, [x29, #24]

{1.1, 2.2}

$ aarch64-linux-gnu-objdump -d a.out  | grep -A15 '<foo>:'
00000000000007b4 <foo>:
 7b4:   a9bc7bfd        stp     x29, x30, [sp, #-64]!
 7b8:   910003fd        mov     x29, sp
 7bc:   f9000fa0        str     x0, [x29, #24]
 7c0:   90000080        adrp    x0, 10000 <__FRAME_END__+0xf6b8>
 7c4:   f947f000        ldr     x0, [x0, #4064]
 7c8:   f9400001        ldr     x1, [x0]
 7cc:   f9001fa1        str     x1, [x29, #56]
 7d0:   d2800001        mov     x1, #0x0                        // #0
 7d4:   90000000        adrp    x0, 0 <_init-0x620>
 7d8:   9124e000        add     x0, x0, #0x938
 7dc:   fd400000        ldr     d0, [x0]
 7e0:   fd0017a0        str     d0, [x29, #40]
 7e4:   90000000        adrp    x0, 0 <_init-0x620>
 7e8:   91250000        add     x0, x0, #0x940
 7ec:   fd400000        ldr     d0, [x0]

这是一个非常奇怪的功能。我想要一个编译器选项来打开和关闭它。

最佳答案

你想要的选项叫做 -mslow-flash-data 但我的 gcc 版本的手册至少说这只支持 ARMv7M 架构。

关于assembly - 强制 arm64 gcc 使用指令构造 double float ,无 .rodata 部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74614929/

相关文章:

assembly - 分支罚款是什么意思?

assembly - 左边的数字是什么意思?实用逆向工程书籍

linux - 静态 Sprite 图像设置的段 %fs 在哪里?

c - GSL 的 GCC/MinGW 问题

python - 类型错误:需要 float - Python

c++ - 忽略 C++ 中的浮点上溢和下溢错误

c - 汇编 - 如何找到一个函数为自己分配了多少堆栈空间

c++ - 如何使用 ASM 将 FARPROC 的内存地址移动到另一个函数?

c - 当我从文件中读取时打印出意想不到的结果

math - float 学有问题吗?