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?

x86 CPUにおける浮動小数点の処理とアセンブリ命令の対応

Last updated at Posted at 2025-10-04

目的

小数はx86のCPU上でどのように処理されるのかを確認します。

[追記]ARMでも確かめました。
ARM 32bit/64bit における C 言語の浮動小数点処理とアセンブリ命令の違い

C言語及びアセンブリへ変換

gcc -O0 -S -masm=intel 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;
}

アセンブリ言語

test.s
	.file	"test.c"
	.intel_syntax noprefix
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	endbr64
	push	rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	mov	rbp, rsp
	.cfi_def_cfa_register 6
	movss	xmm0, DWORD PTR .LC0[rip]
	movss	DWORD PTR -36[rbp], xmm0
	movss	xmm0, DWORD PTR .LC1[rip]
	movss	DWORD PTR -32[rbp], xmm0
	movsd	xmm0, QWORD PTR .LC2[rip]
	movsd	QWORD PTR -24[rbp], xmm0
	movsd	xmm0, QWORD PTR .LC3[rip]
	movsd	QWORD PTR -16[rbp], xmm0
	movss	xmm0, DWORD PTR -36[rbp]
	addss	xmm0, DWORD PTR -32[rbp]
	movss	DWORD PTR -28[rbp], xmm0
	movsd	xmm0, QWORD PTR -24[rbp]
	addsd	xmm0, QWORD PTR -16[rbp]
	movsd	QWORD PTR -8[rbp], xmm0
	mov	eax, 0
	pop	rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.section	.rodata
	.align 4
.LC0:
	.long	1069547520
	.align 4
.LC1:
	.long	1074790400
	.align 8
.LC2:
	.long	0
	.long	1074331648
	.align 8
.LC3:
	.long	0
	.long	1075019776
	.ident	"GCC: (Ubuntu 11.4.0-1ubuntu1~22.04.2) 11.4.0"
	.section	.note.GNU-stack,"",@progbits
	.section	.note.gnu.property,"a"
	.align 8
	.long	1f - 0f
	.long	4f - 1f
	.long	5
0:
	.string	"GNU"
1:
	.align 8
	.long	0xc0000002
	.long	3f - 2f
2:
	.long	0x3
3:
	.align 8
4:

浮動小数点形式

10進数の小数を2進数で表す仕組みの説明は、難しいので参考にした記事のURLを貼ります。
浮動小数点数とは?32ビットと64ビットのしくみを理解しよう

1.5 → 1069547520

.LC0:
	.long	1069547520 ; 1.5f
	.align 4

10進数1069547520 → 16進数0x3FC00000 → 2進数0 01111111 10000000000000000000000

0.5×2 = 1.0
よって小数部 = .1
1.1₂ = 1.1 × 2⁰と表せる

符号 0 正の数
指数部 01111111 127(2⁰の指数0に127を足した値)
仮数部 10000000000000000000000 (1.1₂の小数部分)

2.25 → 1074790400

.LC1:
	.long	1074790400 ; 2.25f
	.align 8

10進数1074790400 → 16進数0x40100000 → 2進数0 10000000 00100000000000000000000

2.25₁₀ = 2 + 0.25

0.25 × 2 = 0.5 → 整数部分 0
0.5 × 2 = 1.0 → 整数部分 1
小数部は0.25₁₀ = 0.01₂

随って2.25₁₀ = 10.01₂
正規化すると
10.01₂ = 1.001₂ × 2¹

符号 0 正の数
指数部 10000000 128(2¹の指数1に127を足した値)
仮数部 00100000000000000000000(正規化後1.001₂の小数部分)

3.125 → 1074331648

.LC2:
	.long	0
	.long	1074331648 ; 3.125
	.align 8

10進数 1074331648 → 16進数 0x40440000 → 2進数 0 10000000 10010000000000000000000

3.125₁₀ = 3 + 0.125
0.125 × 2 = 0.25 → 整数部分 0
0.25 × 2 = 0.5 → 整数部分 0
0.5 × 2 = 1.0 → 整数部分 1
小数部は0.125₁₀ = 0.001₂

随って3.125₁₀ = 11.001₂
正規化すると11.001₂ = 1.1001₂ × 2¹

符号 0 正の数
指数部 10000000 128(2¹の指数1に127を足した値)
仮数部 10010000000000000000000(正規化後1.1001₂の小数部分)

4.875 → 1075019776

.LC3:
	.long	0
	.long	1075019776 ; 4.875

10進数 1075019776 → 16進数 0x409E0000 → 2進数 0 10000001 00111000000000000000000

4.875₁₀ = 4 + 0.875

.875 × 2 = 1.75 → 整数部分 1
0.75 × 2 = 1.5 → 整数部分 1
0.5 × 2 = 1.0 → 整数部分 1

小数部 0.875₁₀ = 0.111₂
随って4.875₁₀ = 100.111₂
正規化すると100.111₂ = 1.00111₂ × 2²

符号 0 正の数
指数部 10000001 129(2²の指数2に127を足した値)
仮数部 00111000000000000000000(正規化後1.00111₂の小数部分)

浮動小数を扱うCPU命令

浮動小数の数値をxmm0レジスタ経由でメモリへ格納しています。

movss

対象:単精度浮動小数点 (float, 32bit)
レジスタ:XMM レジスタの 下位 32bit

movss	xmm0, DWORD PTR .LC0[rip]
movss	DWORD PTR -36[rbp], xmm0  ; float f1 = 1.5f
movss	xmm0, DWORD PTR .LC1[rip]
movss	DWORD PTR -32[rbp], xmm0  ; float f2 = 2.25f

movsd

対象:倍精度浮動小数点 (double, 64bit)
レジスタ:XMM レジスタの 下位 64bit

movsd	xmm0, QWORD PTR .LC2[rip]
movsd	QWORD PTR -24[rbp], xmm0 ; double d1 = 3.125
movsd	xmm0, QWORD PTR .LC3[rip]
movsd	QWORD PTR -16[rbp], xmm0 ; double d2 = 4.875

addss

対象:float 型 (32bit)
操作:下位 32bit 同士の加算

movss	xmm0, DWORD PTR -36[rbp]
addss	xmm0, DWORD PTR -32[rbp] ; float fsum = f1 + f2;
movss	DWORD PTR -28[rbp], xmm0

addsd

対象:double 型 (64bit)
操作:下位 64bit 同士の加算

movsd	xmm0, QWORD PTR -24[rbp]
addsd	xmm0, QWORD PTR -16[rbp] ; double dsum = d1 + d2;
movsd	QWORD PTR -8[rbp], xmm0

最後に

浮動小数の計算をする場合はソフト側で泥臭い計算をしているものとばかり思っており、浮動小数専用のレジスタや命令があることは今まで全く知りませんでした。

動作環境(Linux / x86_64 版)

OS: Ubuntu 22.04.5 LTS (Jammy Jellyfish)
Kernel: Linux 6.8.0-84-generic
CPU: Intel Core i5-8250U, 4 cores, 8 threads, Little Endian
GCC: 12.3.0
Architecture: x86_64

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?