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)
你应该没有真正的理由.请记住,这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从一个float到uint32_t).例如,对于Quake源代码中使用的着名但现在大多数过时的快速近似逆sqrtf魔术数黑客.