目次: C言語とlibc
今まであまりCPUアーキテクチャの違いを感じたことはありませんが、除算命令を触っていたところ、アーキテクチャによってかなり動きが違っていて面白かったので、メモしておきます。
プログラムは下記のとおりです。
#include <stdio.h>
#include <limits.h>
void f(int a, int b)
{
printf("mul:%08x * %08x = %08x\n", a, b, a * b);
printf("div:%08x / %08 = %08x\n", a, b, a / b);
}
int main(int argc, char *argv[])
{
f(INT_MAX, -1);
f(INT_MIN + 1, -1);
f(INT_MIN, -1); //乗算、除算の動作は未定義
f(INT_MAX, 0); //除算の動作は未定義
}
初めに断っておくと、コメントを打った箇所については、C言語上の仕様上、動作が未定義です。つまり、どんなことでも起こり得ます。不定な結果が返ることもあるし、プログラムが停止することだってあります。
このプログラムをx86 (x86_64, Ryzen 7 2700), ARM (AArch64, Cortex A53), RISC-V (RV64GC, SiFive FU540) のLinux上でそれぞれ実行してみます。
#### x86_64 ####
mul:7fffffff * ffffffff = 80000001
div:7fffffff / ffffffff = 80000001
mul:80000001 * ffffffff = 7fffffff
div:80000001 / ffffffff = 7fffffff
mul:80000000 * ffffffff = 80000000
Floating point exception
#### AArch64 ####
mul:7fffffff * ffffffff = 80000001
div:7fffffff / ffffffff = 80000001
mul:80000001 * ffffffff = 7fffffff
div:80000001 / ffffffff = 7fffffff
mul:80000000 * ffffffff = 80000000
div:80000000 / ffffffff = 80000000
mul:7fffffff * 00000000 = 00000000
div:7fffffff / 00000000 = 00000000
#### RV64GC ####
mul:7fffffff * ffffffff = 80000001
div:7fffffff / ffffffff = 80000001
mul:80000001 * ffffffff = 7fffffff
div:80000001 / ffffffff = 7fffffff
mul:80000000 * ffffffff = 80000000
div:80000000 / ffffffff = 80000000
mul:7fffffff * 00000000 = 00000000
div:7fffffff / 00000000 = ffffffff
当然ながら、動作が定義されている演算は、どのアーキテクチャでも同じ結果です。当たり前ですね。
一方で動作が未定義の演算は、かなり挙動が変わります。
個性が出ますね。
先ほどの例でx86上でINT_MIN / (-1) の除算がクラッシュする原因はidiv命令の仕様です。
Intelの命令仕様書(Intel Architectures Software Developer Manual: Vol 2)のIDIV - Signed Divideのページを見ると、保護モード例外 #DEが発生する条件として、
この2条件が挙げられています。INT_MIN / (-1) は結果が32bitで表現できないため、後者に引っ掛かるわけです。
異常な演算に対して例外を発生させる設計思想なら分かりますが、乗算命令は異常な結果でも素通しなのに、除算命令は異常な結果だと例外発生します。片手落ちの不思議な仕様です。変なの……。
< | 2019 | > | ||||
<< | < | 07 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | 1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | - | - | - |
合計:
本日:
管理者: Katsuhiro Suzuki(katsuhiro( a t )katsuster.net)
This is Simple Diary 1.0
Copyright(C) Katsuhiro Suzuki 2006-2023.
Powered by PHP 8.2.18.
using GD 2.3.3(png support.)