如何将ST(0)移动到EAX?

gru*_*htr 3 x86 assembly fpu x87

Hullo,我正在学习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                                           
Run Code Online (Sandbox Code Playgroud)

Dan*_*zar 5

你应该没有真正的理由.请记住,这EAX只是一个32位寄存器,而所有FPU寄存器的宽度都是80位,因为默认情况下FPU会对80位浮点数进行计算.因此,将数据从FPU寄存器移动到通用寄存器将导致数据丢失.如果你真的想做类似的事情,试试这个(假设你有一些堆栈空间可用):

sub esp, 4           ; or use space you already reserved
fstp dword [esp]
mov eax, [esp]       ; or better,  pop eax
add esp, 4
Run Code Online (Sandbox Code Playgroud)

该指令序列将当前位于FPU堆栈顶部的浮点数舍入为32位,然后将其写入临时堆栈位置,将float(binary32)位模式加载到EAX,并清理使用的堆栈空间.


这几乎不是你想要的. 标准调用约定返回float/double/long double值st(0),因此C编译器期望double foo()函数保留该值.(或xmm0使用SSE/SSE2).

如果要对FP位模式进行整数操作/测试,则只需要这个.(即,实现类型双关用C等memcpy从一个floatuint32_t).例如,对于Quake源代码中使用的着名但现在大多数过时的快速近似逆sqrtf魔术数黑客.