0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ARM 32bit/64bit における C 言語の浮動小数点処理とアセンブリ命令の違い

Last updated at Posted at 2025-10-05

目的

昨日x86 CPU上で浮動小数がどう扱われるか調べました。
小数→浮動小数点形式の変換方法は以下の記事をご参照下さい。
浮動小数点形式そのものはx86でもARMでも変わりません。
x86 CPUにおける浮動小数点の処理とアセンブリ命令の対応

今日は32bit/64bitのARM上での扱いを調べてみます。

Cソース

gcc -O0 -S test.c -o test.s
test.c
#include <stdio.h>

int main() {
    float f1 = 1.5f, f2 = 2.25f;
    double d1 = 3.125, d2 = 4.875;

    float fsum = f1 + f2;
    double dsum = d1 + d2;

    return 0;
}

生成されたアセンブリ

Armbian 32bit

test.s
        .arch armv7-a
        .fpu vfpv3-d16
        .eabi_attribute 28, 1
        .eabi_attribute 20, 1
        .eabi_attribute 21, 1
        .eabi_attribute 23, 3
        .eabi_attribute 24, 1
        .eabi_attribute 25, 1
        .eabi_attribute 26, 2
        .eabi_attribute 30, 6
        .eabi_attribute 34, 1
        .eabi_attribute 18, 4
        .file   "test.c"
        .text
        .align  1
        .global main
        .syntax unified
        .thumb
        .thumb_func
        .type   main, %function
main:
        @ args = 0, pretend = 0, frame = 40
        @ frame_needed = 1, uses_anonymous_args = 0
        @ link register save eliminated.
        push    {r7}
        sub     sp, sp, #44
        add     r7, sp, #0
        mov     r3, #1069547520
        str     r3, [r7, #36]   @ float
        mov     r3, #0
        movt    r3, 16400
        str     r3, [r7, #32]   @ float
        mov     r2, #0
        mov     r3, #0
        movt    r3, 16393
        strd    r2, [r7, #24]
        mov     r2, #0
        mov     r3, #32768
        movt    r3, 16403
        strd    r2, [r7, #16]
        vldr.32 s14, [r7, #36]
        vldr.32 s15, [r7, #32]
        vadd.f32        s15, s14, s15
        vstr.32 s15, [r7, #12]
        vldr.64 d6, [r7, #24]
        vldr.64 d7, [r7, #16]
        vadd.f64        d7, d6, d7
        vstr.64 d7, [r7]
        movs    r3, #0
        mov     r0, r3
        adds    r7, r7, #44
        mov     sp, r7
        @ sp needed
        ldr     r7, [sp], #4
        bx      lr
        .size   main, .-main
        .ident  "GCC: (Debian 12.2.0-14+deb12u1) 12.2.0"
        .section        .note.GNU-stack,"",%progbits

Termux 64bit

test.s
        .file   "test.c"
        .text
        .globl  main                            // -- Begin function main
        .p2align        2
        .type   main,@function
main:                                   // @main
        .cfi_startproc
// %bb.0:
        sub     sp, sp, #48
        .cfi_def_cfa_offset 48
        mov     w0, wzr
        str     wzr, [sp, #44]
        fmov    s0, #1.50000000
        str     s0, [sp, #40]
        fmov    s0, #2.25000000
        str     s0, [sp, #36]
        fmov    d0, #3.12500000
        str     d0, [sp, #24]
        mov     x8, #140737488355328            // =0x800000000000
        movk    x8, #16403, lsl #48
        fmov    d0, x8
        str     d0, [sp, #16]
        ldr     s0, [sp, #40]
        ldr     s1, [sp, #36]
        fadd    s0, s0, s1
        str     s0, [sp, #12]
        ldr     d0, [sp, #24]
        ldr     d1, [sp, #16]
        fadd    d0, d0, d1
        str     d0, [sp]
        add     sp, sp, #48
        .cfi_def_cfa_offset 0
        ret
.Lfunc_end0:
        .size   main, .Lfunc_end0-main
        .cfi_endproc
                                        // -- End function
        .ident  "clang version 20.1.8"
        .section        ".note.GNU-stack","",@progbits

アセンブリの解説

32ビット

mov rX, #0は全ビットを0で初期化している。
movtは上位16ビットのみに書き込む命令。
全ビットを0で初期化した後にmovt命令にて上位16ビットを書き換えることで、下位16ビットは0のままとなる。(=下位16ビットに余計なデータが入らないことを保障できる)

strdは指定したレジスタrXtとrX+12つのレジスタに保存された値を64ビットの値としてメモリへ保存する。
具体的にはstrd rX, [rY] ; rX:rX+1 の64bitを [rY] に書き込む

float 1.5

1.5の浮動小数点形式は1069547520

mov     r3, #1069547520
str     r3, [r7, #36]   @ float

float 2.25

2.25の浮動小数点形式は1074790400

r3の上位16ビットに16400を書き込むと、r3 = 0x40100000 (1074790400)

mov     r3, #0
movt    r3, 16400
str     r3, [r7, #32]   @ float

double 3.125

3.125の浮動小数点形式は1074331648

r3の上位16ビットに16393を書き込むと、r3 = 0x40090000 (1074331648)

[r7+24] = 0x00000000 ; 下位32bit
[r7+28] = 0x40090000 ; 上位32bit

mov     r2, #0 @ 下位32bit
mov     r3, #0 @ 上位32bit
movt    r3, 16393
strd    r2, [r7, #24]

double 4.875

4.875の浮動小数点形式は1075019776

[r7+16] = r2 = 0x00000000 ; 下位32bit
[r7+20] = r3 = 0x400B8000 ; 上位32bit

mov     r2, #0
mov     r3, #32768
movt    r3, 16403
strd    r2, [r7, #16]

floatの加算

sレジスタ:単精度(32bit float)用

s14 = 1.5
s15 = 2.25
s15 = s14 + s15

vldr.32 s14, [r7, #36]
vldr.32 s15, [r7, #32]
vadd.f32        s15, s14, s15
vstr.32 s15, [r7, #12]

doubleの加算

dレジスタ:倍精度(64bit double)用

使用するレジスタと命令が違うだけで処理の方法は同じ。

vldr.64 d6, [r7, #24]
vldr.64 d7, [r7, #16]
vadd.f64        d7, d6, d7
vstr.64 d7, [r7]

64ビット

即値は10進数で書けるようになっている。

float 1.5

fmov    s0, #1.50000000
str     s0, [sp, #40]

float 2.25

fmov    s0, #2.25000000
str     s0, [sp, #36]

double 3.125

fmov    d0, #3.12500000
str     d0, [sp, #24]

double 4.875

mov     x8, #140737488355328            // =0x800000000000
movk    x8, #16403, lsl #48
fmov    d0, x8
str     d0, [sp, #16]

floatの加算

ldr     s0, [sp, #40]
ldr     s1, [sp, #36]
fadd    s0, s0, s1

doubleの加算

str     s0, [sp, #12]
ldr     d0, [sp, #24]
ldr     d1, [sp, #16]
fadd    d0, d0, d1

動作環境

上の携帯が64ビット、下のARM機が32ビット
a0d36ab3ab8828.jpg

32bit

動作環境(Linux / ARM 版)

  • OS: Armbian 23.08.0-trunk (Debian 12 Bookworm)
  • Kernel: Linux 6.1.38-meson (armv7l)
  • CPU: ARM Cortex-A5, 4 cores, Little Endian
  • GCC: 12.2.0
  • Architecture: armv7l
  • 備考: Windows10からSSH接続して使用

動作環境確認コマンドは以下の通り

uname -a
cat /etc/os-release
gcc --version
lscpu

64bit

OPPO-A5-2020
Termux

Termuxの使い方は以前以下の記事にて纏めています。
不要になったアンドロイドをLinuxサーバにする Termuxを試す

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?