32ビットシステムで80ビット浮動小数点を使用するにはどうすればよいですか?[複製]


13

32ビットシステムでは2 ^ 33の数値を管理できないため(明らかな32ビットの制限のため)、80ビットの浮動小数点数を管理するにはどうすればよいですか?

「80ビット」が必要です...


8
64ビット浮動小数点数を処理するのと同じ方法。3または(2)32ビットレジスタを使用します。80ビットの浮動小数点数は標準サイズではないため、実際には80ビットのみが使用されている96ビットの数値になります。
ラムハウンド14

5
プラットフォームのビット不足を心配すると、他の人が言ったようにCPUの内部動作が心配され、命令がシステムでネイティブに実行される方法が心配されます。IEEE754の数値は通常、CPUのFPU実行ユニットで直接処理できますが、128ビットの数値は、アプリケーションが評価する値の意味を集約できるようにプログラムされた複数の命令を使用する必要があります。番号の処理はアプリケーションに任されます。
フランクトーマス14

2
@Ƭᴇcʜιᴇ007ないのはかなりデュープその 1。その1つは、数値とそのテキスト/ ASCII表現の違いについての詳細ですが、これらの回答の一部はこれに対処する場合もあります。
ボブ14

3
事実上すべての最新のマシンでは、浮動小数点は別のプロセッサで処理されます(ただし、通常はメインプロセッサと同じチップ上にあります)。このようなプロセッサはすべて、80ビットの処理方法を知っています(一部のプロセッサは他のプロセッサよりもはるかに高速に処理します)。(とにかくプロセッサーの「幅」はフィクションのようなものです。
ダニエルRヒックス14

6
@Ramhound:いいえ、80ビットは8087の特殊性であり、1つのFPレジスタを使用します。これは間違いなく96ビットの数字ではありません。
MSalters

回答:


35

32ビットCPUの意味の1つは、レジスタが32ビット幅であることです。これは、たとえば64ビットの数値を処理できないことを意味するのではなく、下位32ビットの半分を最初に処理し、次に上位32ビットの半分を処理する必要があるだけです。(これがCPUにキャリーフラグがある理由です。)CPUがより広い64ビットレジスタに値をロードできる場合よりも遅くなりますが、それでも可能です。

したがって、システムの「ビットネス」は、プログラムが処理できる数値のサイズを必ずしも制限しません。これは、CPUレジスタに収まらない操作を複数の操作にいつでも分割できるためです。そのため、操作が遅くなり、より多くのメモリを消費し(「スクラッチパッド」としてメモリを使用する必要がある場合)、プログラミングがより困難になりますが、操作は可能です。

ただし、CPUの浮動小数点部分には独自のレジスタがあり、それらは80ビット幅なので、たとえばIntel 32ビットプロセッサや浮動小数点では問題になりません。(x86の歴史の初期では、浮動小数点機能は別個のチップであり、80486DX以降のCPUに統合されていました。)


@Breakthroughの答えは私にこれを追加するように促しました。

浮動小数点値は、FPUレジスタに格納されている限り、バイナリ整数値とは大きく異なります。

浮動小数点値の80ビットは、仮数と指数の間で分割されます(常に2である浮動小数点数の「ベース」もあります)。仮数には有効数字が含まれ、指数はそれらの有効数字の大きさを決定します。したがって、別のレジスタへの「オーバーフロー」はありません。仮数に収まらないほど数値が大きくなり、指数が増加して精度が失われます。つまり、整数に変換すると、小数点以下の桁が失われます。これが浮動小数点と呼ばれる理由です。

指数が大きすぎる場合、浮動小数点オーバーフローが発生しますが、指数と仮数が結び付けられているため、簡単に別のレジスタに拡張することはできません。

私はそのいくつかについて不正確で間違っているかもしれませんが、それがその要点だと思います。(このウィキペディアの記事は、上記をもう少し簡潔に示しています。)

CPUの「浮動小数点」部分全体が独自の世界にあるため、これがまったく異なる動作をすることは問題ありません-特別なCPU命令を使用してそれにアクセスします。また、質問のポイントに向かって、それは分離されているため、FPUのビット数はネイティブCPUのビット数と密接に結びついていません。


4
私のインスピレーションから追加したものはすべて正しいので、心配する必要はありません:)言及する必要があるのは、浮動小数点ユニットが存在するネイティブCPU命令を使用できますが、ソフトウェアで浮動小数点演算を実行することもできます(ビット単位でまたは整数演算)。十分なメモリがあれば、その時点まで拡張するために、ソフトウェアアルゴリズム/ライブラリを使用して(この場合は固定の64ビットまたは80ビットではなく)任意の精度の数値を使用することもできます(一般的に使用されるのはGNU Multiple Precisionライブラリ)。
ブレークスルー14

1
Nitpick:最初のインテルは、FPUが80486DX、ない80386にあった統合
spudone

2
@markzzz:それが必要な場合、何も狂っていません。核の備蓄を評価するために16ビットの浮動小数点数を使用して原子爆弾をシミュレートするのは、結果に自信を持っているほど正確ではないため、おかしいです。その場合、32ビットが必要です(そして、そう、昔はこれらの計算は16ビットPDPで行われていました)。同様に、気候をシミュレートするために32ビットフォラットを使用することは、計算が混chaとしているため、十分に正確ではありません。
スリーブマン14

2
FWIW、必要なサイズのFPユニットのないマシンに浮動小数点演算を実装する一般的な方法は、整数命令を使用してソフトウェアで実行することです。なぜなら、一日の終わりには、浮動小数点数の指数と仮数の両方が単なる整数だからです。特別な意味を与えるのは、それらをどのように解釈するかです。
スリーブマン14

2
x86の@PTwrには、実際にはデータに7つの使用可能なGPRがあり、EBPが含まれています。ほとんどの言語実装のABIは、このレジスタをスタックフレームポインター用に予約しているだけです。しかし、たとえばGCCを使用する-fomit-frame-pointerと、その登録を取り戻すことができます。
ルスラン

13

32ビット、64ビット、および128ビットはすべて、プロセッサのワード長を指し、これは「基本的なデータ型」と考えることができます。多くの場合、これはシステムのRAMとの間で転送されるビット数、およびポインターの幅です(ただし、1つのポインターがアクセスできる以上のRAMにソフトウェアを使用することを妨げるものはありません)。

一定のクロック速度(およびアーキテクチャ内の他のすべてが一定)を想定し、メモリの読み取り/書き込みが同じ速度であると想定します(ここでは1クロックサイクルを想定していますが、これは現実の場合とは異なります)。 64ビットマシンの1クロックサイクルで2つの64ビット数を追加します(RAMから数をフェッチする場合は3つ):

ADDA [NUM1], [NUM2]
STAA [RESULT]

32ビットマシンで同じ計算を行うことができます...しかし、32ビットマシンでは、下位32ビットを最初に追加し、オーバーフローを補正してから追加する必要があるため、ソフトウェアでこれを行う必要があります上位64ビット:

     ADDA [NUM1_LOWER], [NUM2_LOWER]
     STAA [RESULT_LOWER]
     CLRA          ; I'm assuming the condition flags are not modified by this.
     BRNO CMPS     ; Branch to CMPS if there was no overflow.
     ADDA #1       ; If there was overflow, compensate the value of A.
CMPS ADDA [NUM1_UPPER], [NUM2_UPPER]
     STAA [RESULT_UPPER]

作成したアセンブリ構文を確認すると、高精度の演算が、語長の短いマシンで指数関数的に長い時間を要することが簡単にわかります。これは、64ビットプロセッサと128ビットプロセッサの本当の鍵です。1回の操作でより多くのビットを処理できます。一部のマシンには、キャリーを使用して他の数量を追加するための命令が含まれています(ADCx86など)が、上記の例では任意の精度値が考慮されています。


これを質問に拡張するために、使用可能なレジスタよりも大きな数を追加する方法を簡単に確認できます。問題をレジスタのサイズのチャンクに分割し、そこから作業するだけです。@MatteoItaliaで述べたように、x87 FPUスタックは80ビット量をネイティブにサポートしていますが、このサポートを欠いているシステム(または浮動小数点ユニットを完全に欠いているプロセッサー!)では、同等の計算/操作をソフトウェアで実行する必要があります。

したがって、80ビットの数値の場合、各32ビットセグメントを追加した後、81番目のビットへのオーバーフローもチェックし、オプションで上位ビットをゼロにします。これらのチェック/ゼロは、ソースとデスティネーションのオペランドサイズが指定されている特定のx86およびx86-64命令に対して自動的に実行されます(ただし、これらは1バイト幅から始まる2の累乗でのみ指定されます)。

もちろん、浮動小数点数では、仮数と有効数字がオフセット形式で一緒にパックされるため、単純にバイナリ加算を実行することはできません。x86プロセッサのALUには、IEEE 32ビットおよび64ビットの浮動小数点に対してこれを実行するハードウェア回路があります。ただし、浮動小数点ユニット(FPU)がない場合でも、ソフトウェアで同じ計算を実行できます(たとえば、GNU Scientific Libraryを使用することにより、アーキテクチャでコンパイルされたときにFPUを使用し、ソフトウェアアルゴリズムにフォールバックします)浮動小数点ハードウェアが使用できない場合(たとえば、FPUを備えていない組み込みマイクロコントローラーの場合)。

十分なメモリがあれば、任意の(または「無限」-現実的な範囲内)精度の数値で計算を実行できます。精度が必要になるほど、より多くのメモリを使用します。これの1つの実装は、GNU Multiple Precisionライブラリにあり、整数、有理数、および浮動小数点演算で無制限の精度(もちろん、RAMがいっぱいになるまで)を許可します。


2
最も重要な詳細については言及していません。x86プラットフォームのx87 FPUには80ビット幅の浮動小数点レジスターがあるため、そのネイティブ計算は実際には80ビットの浮動小数点で行われ、ソフトウェアでエミュレートする必要はありません。
マッテオイタリア14

@MatteoItaliaなるほど、ありがとうございます。元の質問は、プロセッサのワードサイズよりも大きい数で演算を実行する方法のより一般的な概要を求めていて、x86の拡張80ビットフロートの特定の実装ではないことを求めていたと思いました(また、私の例が80 ...)。これをよりよく反映するように回答を更新しました。ありがとうございました。
ブレークスルー

5

システムのメモリアーキテクチャでは、一度に32ビットしか移動できない場合がありますが、それ以上の数を使用することを妨げません。

乗算を考えてください。最大10x10の乗算テーブルを知っているかもしれませんが、おそらく紙の上で123x321を実行するのに問題はありません:それを多くの小さな問題に分割し、個々の数字を乗算し、キャリーなどを処理します。

プロセッサでも同じことができます。「昔」には、浮動小数点演算を実行できる8ビットプロセッサがありました。しかし、彼らはすごかった。


1
それらはある点の後だけ遅くなった。特定の仕様に限定した場合、「高速」浮動小数点演算を作成できます。
ラムハウンド14

3

「32ビット」は、実際にはプロセッサを分類する方法であり、固定されたルールではありません。「32ビット」プロセッサには通常、32ビットの汎用レジスタがあります。

ただし、プロセッサ内のすべてを32ビットで実行する必要はありません。たとえば、「32ビット」コンピューターで28ビットのアドレスバスを使用することは、ハードウェアを作成する方が安価だったため、前代未聞ではありませんでした。多くの場合、64ビットコンピューターには、同じ理由で40ビットまたは48ビットのメモリバスしかありません。

浮動小数点演算は、サイズが異なる別の場所です。多くの32ビットプロセッサが64ビット浮動小数点数をサポートしていました。彼らは、汎用レジスターよりも広い特殊レジスターに浮動小数点値を格納することでそうしました。これらの大きな浮動小数点数のいずれかを特殊レジスターに格納するには、まず数値を2つの汎用レジスターに分割し、次にそれらを結合して特殊レジスターの浮動小数点数にする命令を発行します。これらの浮動小数点レジスターでは、値は一対の32ビットの半分としてではなく、64ビットの浮動小数点として操作されます。

あなたが言及する80ビットの算術はこの特別な場合です。浮動小数点数を使用したことがある場合は、浮動小数点の丸めの問題から生じる不正確さに精通しています。四捨五入の解決策の1つは、ビットの精度を上げることですが、その場合、より大きな数値を格納し、開発者にメモリ内で異常に大きな浮動小数点値を使用するように強制する必要があります。

Intelのソリューションでは、浮動小数点レジスタはすべて80ビットですが、これらのレジスタとの間で値を移動する命令は、主に64ビットの数値で機能します。Intelのx87浮動小数点スタック内で完全に操作する限り、すべての操作は80ビットの精度で行われます。コードがこれらの値の1つを浮動小数点レジスターから取り出してどこかに保存する必要がある場合、64ビットに切り捨てます。

物語の教訓:「32ビット」のような分類は、物事を深く掘り下げると、常に混乱します!


しかし、32ビット浮動小数点値を16ビットシステムに使用する場合(または64ビット浮動小数点値を32ビットシステムに使用する場合)は、より多くのメモリしか必要ありません(2回のレジスタが必要なため)?または、情報を処理するとオーバーヘッドが追加されるため、さらに時間がかかりますか?
markzzz 14

@markzzz:複数のレジスタを使用する場合、ほとんどの場合、時間がかかります
Mooing Duck 14

32ビット浮動小数点値を特別な目的のレジスタにロードするには、さらに時間がかかります。ただし、特別な目的の浮動小数点レジスターに32ビットの浮動小数点として格納されると、ハードウェアはそれらの浮動小数点値を全速力で操作します。「16ビット」とは、汎用レジスタのサイズのみを指すことを忘れないでください。浮動小数点レジスターは、タスク用に特別なサイズであり、より広い場合があります(32ビット幅の場合)
Cort Ammon-Reinstate Monica 14

2

「32ビット」CPUとは、ほとんどのデータレジスタが32ビットレジスタであり、ほとんどの命令がこれらの32ビットレジスタのデータを操作するCPUです。また、32ビットCPUは、一度に32ビットのメモリとの間でデータを転送する可能性があります。ほとんどのレジスタが32ビットであることは、すべてのレジスタが32ビットであることを意味しません。簡単な答えは、32ビットCPUには、80ビット浮動小数点レジスターや対応する命令など、他のビットカウントを使用する機能があることです。

@sprasoneが@ultrasawbladeの答えのコメントで述べたように、浮動小数点演算を統合した最初のx86 CPUはIntel i486(具体的には80486SXではなく80486DX)であり、i486 Microprocessor Programmersの15-1リファレンスマニュアルには、数値レジスタに「8つの個別にアドレス指定可能な80ビット数値レジスタ」が含まれています。i486には32ビットのメモリバスがあるため、80ビットの値を転送するには3つのメモリ操作が必要です。

486世代の前身であるi386には、浮動小数点演算が統合されていませんでした。代わりに、外部浮動小数点「コプロセッサ」80387の使用をサポートしていました。このコプロセッサは、80387プログラマーズリファレンスマニュアルのページ2-1からわかるように、i486に統合された機能とほぼ同じでした

80ビットの浮動小数点形式は、8086および8088の数学コプロセッサである8087を起源とするようです。8086および8088は16ビットCPU(16ビットおよび8ビットのメモリバス)であり、コプロセッサの80ビットレジスタを活用して、80ビット浮動小数点形式を使用する。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.