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

时间:2012-08-10 10:39:44

标签: assembly x86 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                                           

2 个答案:

答案 0 :(得分: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

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


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

如果要对FP位模式进行整数操作/测试,则只需要这个。 (即从xmm0memcpy实现类似float的C中的类型双关语。例如对于Quake源代码中使用的famous but now mostly obsolete fast approximate inverse-sqrtf magic-number hack

答案 1 :(得分:3)

没有x87指令可以在FPU寄存器和CPU寄存器之间移动浮点值。

你必须使用记忆作为中间人。