3

こんにちは、私は x86 FPU アセンブリを学んでいますが、答えが見つからない簡単な質問があります。

ST(0)(FPU スタックの一番上)から に値を移動する方法はEAX?

また:
このコードは正しいですか:

; multiply (dot) two vectors of 3 floats passed by pointers as arg 1 arg 2
; passings are ok I think, but not sure if multiplies-adds are ok

    push    ebp                                     
    mov     ebp, esp                                
    mov     eax, dword [ebp+8H]                     
    mov     edx, dword [ebp+0CH]                    

    fld     qword [eax]                             
    fmul    qword [edx]                             
    fld     qword [eax+4H]                          
    fmul    qword [edx+4H]                          
    fld     qword [eax+8H]                          
    fmul    qword [edx+8H]                          
    faddp   st1, st(0)                              
    faddp   st1, st(0)                            
    fstp    qword [ebp+10H]     ; here I vould prefer 'mov eax, st0'

    pop     ebp                                   
    ret                                           
4

2 に答える 2

5

あなたがしなければならない本当の理由はありません。FPUEAXはデフォルトで 80 ビット浮動小数点で計算を行うため、すべての FPU レジスタは幅が 80 ビットですが、これは 32 ビット レジスタのみであることに注意してください。したがって、FPU レジスタから汎用レジスタにデータを移動すると、データが失われます。本当にそのようなことをしたい場合は、これを試してください(利用可能なスタックスペースがあると仮定して):

sub esp, 4           ; or use space you already reserved
fstp dword [esp]
mov eax, [esp]       ; or better,  pop eax
add esp, 4

この命令シーケンスは、現在 FPU スタックの一番上にあるフロートを 32 ビットに丸め、それを一時的なスタックの場所に書き込み、float(binary32) ビット パターンをにロードEAXし、使用済みスタック スペースをクリーンアップします。


これはほとんどあなたが望むものではありません。 標準の呼び出し規約は float / double / long double の値を に返すst(0)double foo()ため、C コンパイラは関数が値を残すことを期待します。(またはxmm0SSE/SSE2 を使用)。

これは、整数操作/FP ビットパターンのテストを行う場合にのみ必要です。memcpy(つまり、 from a floattoのように C で型パニングを実装するためuint32_t)。たとえば、Quake のソース コードで使用されている、有名だが現在はほとんど時代遅れになっている高速近似sqrtf逆魔法数ハックなどです。

于 2012-08-10T12:25:43.853 に答える
4

FPU レジスタと CPU レジスタ間で浮動小数点値を移動する x87 命令はありません。

中間としてメモリを使用する必要があります。

于 2012-08-10T10:53:24.760 に答える