● 関数リファレンス

FPU 環境の保存

    void __stdcall    floatex_fpusave(void *pdest);

引数

引数名意味
pdest結果を格納する領域の先頭アドレス

戻り値

無し

説明

レジスタスタックを含む FPU 環境を pdest が指す領域に保存した後で、コントロールワード以外の FPU 情報をリセットします。

pdest が指す領域は、128 バイト以上の大きさが必要です。保存したデータは floatex_fpuload で読み込み、FPU に再設定する事ができますが、設定の一部を変更する目的には使用できません。

領域の型は、どのようなものでもかまいませんが、次の構造体にすると、内容を参照する事ができます。

FPU 環境構造体.

typedef struct {
    unsigned long       cw;
    unsigned long       stw;
    unsigned long       tw;
    unsigned long       instruction_pointer;
    unsigned short      code_seg;
    unsigned short      opecode;
    unsigned long       operand_adr;
    unsigned short      data_seg;
    unsigned short      reserved1;
    FLOATEX             reg[8];
    unsigned long       reserved2[5];
} FPU_ENV,*PFPU_ENV;

この構造体は floatex.h 内で定義されています。

メンバ名意味
cwコントロールワード
stwステータスワード
twタグワード
instruction_pointerラスト命令ポインタ
code_segコードセグメント
opecodeオペコード
operand_adrオペランドアドレス
data_segデータセグメント
reserved1予約
regレジスタスタック
reserved2予約


この関数は、汎用レジスタの内容を変えません。また、EFLAGS の内容を保存します。


内容を参照するプログラム例:最後に実行した FPU 命令を確認する実験(1)

#include <stdio.h>
#include "floatex.h"

void    main(void)
{
    FPU_ENV         env;
    unsigned long   adr;

    _asm{
        fld1

        lea         eax,cmd_address
        mov         adr,eax
    cmd_address:
        fstp        st      ; この命令が、最後に実行されたものになります
    }

    floatex_fpusave(&env);

    printf("\n");

    printf("    実際のアドレス:0x%08x\n",adr);
    printf("ラスト命令ポインタ:0x%08x\n\n",env.instruction_pointer);

    /*
      "fstp  st" は 11011 101 : 11011000b
      オペコードレジスタのフォーマットにすると 0x5d8
      (11011101 11011000b & 7ffh)
    */
    printf("        オペコード:0x%03x\n",env.opecode);
}

/*
  応用時の注意:

  __try ブロック内で、このプログラムのように、ラベルによるアドレス取得を行
  う場合、古いコンパイラでは C2705 が発生する事があります。

  その場合は、アドレスの取得をラベルよりも後ろの位置で行ってください。
  位置の変更が困難な場合は、floatex_get_lastcmd のリファレンスにあるプログ
  ラム例の方法も検討してみてください。
*/