最適化の理由から、関数「fldl」と「fist」を直接(インラインアセンブラを使用して)呼び出すことを考えました。悲しいことに、私はアセンブラーの神ではないので、それを実行する方法がわかりません。
私はこれ以上進んでいませんでした:
double* input;
long long output;
__asm fldl input;
__asm fist output;
最適化の理由から、関数「fldl」と「fist」を直接(インラインアセンブラを使用して)呼び出すことを考えました。悲しいことに、私はアセンブラーの神ではないので、それを実行する方法がわかりません。
私はこれ以上進んでいませんでした:
double* input;
long long output;
__asm fldl input;
__asm fist output;
__asm fld input
実際には、浮動小数点値であるかのようにポインタ値を読み取ろうとします。ポインタが指す浮動小数点値を読み取りたい場合は、2段階のプロセスを実行する必要があります。つまり、アドレスをレジスタに読み取り、次にレジスタ内のアドレスを使用してデータを読み取ります。32ビットプラットフォームでは、次のようなものになります。
__asm {
mov eax, input
fld qword ptr [eax]
fistp output
}
VS2005で試したところ、動作します。(他の人がコメントで述べているように、fist
64ビットへの保存はサポートしていませんが、サポートしlong long
ていることに注意してください。しかし、とにかく、つまりポップストアfistp
が必要になるでしょう。)fistp
最も簡単なのはおそらく:
double input;
long long output;
__asm fld input
__asm fisttp output
これは、Cキャストのように、「通常の」ダブルからロングロングへの変換を行い、ゼロに向かって切り捨てます。非常に古い(Pentium4より前の)CPUはサポートしていませんが、そのようなマシンでは、代わりに現在の丸めモード(通常は最も近い値に丸める)をfistpp
使用する必要があります。fistp
したがって、たとえば-無限大に向かって丸める場合は、現在の丸めモードを保存し、必要なものに設定して、を実行しfistp
、丸めモードを復元する必要があります。
double input;
long long output;
unsigned short oldcw, cw;
__asm fld input
__asm fstcw oldcw
cw = (oldcw & ~0xc00) | 0x400; // round towards -infinity
__asm fldcw cw
__asm fistp output
__asm fldcw oldcw