从扩展精度浮点数(80位值,在某些编译器中也称为“ long double”)转换为MSVC win32 / win64中double(64位)的最便捷和“正确”的方法是什么?
MSVC当前(截至2010年)假定“ long double”是“ double”的同义词。
我可能可以在内联汇编中编写fld / fstp汇编程序对,但是内联汇编不适用于MSVC中的win64代码。我是否需要将此汇编代码移至单独的.asm文件?真的是这样,没有好的解决方案吗?
我读过(http://www.stereopsis.com/FPU.html)中提到的(在x86上将float转换为int的最快方法是什么).有谁知道缓慢的简单演员(参见下面的代码片段)是否也适用于ARM架构?
inline int Convert(float x)
{
int i = (int) x;
return i;
}
Run Code Online (Sandbox Code Playgroud)
要应用FPU文章中提到的一些技巧,您必须设置浮点运算的精度.我如何在ARM上做到这一点?
在ARM体系结构上,最快的浮点转换是什么?
谢谢!
提示和指控比比皆是,使用NaN的算法在硬件FPU中可能"慢".特别是在现代的x64 FPU中,例如在Nehalem i7上,这仍然是真的吗?无论操作数的值如何,FPU乘法都会以相同的速度进行转换?
我有一些插值代码可以离开我们定义的数据的边缘,我正在尝试确定在那里和任何地方检查NaN(或其他一些哨兵值)是否更快,或者只是在方便的点.
是的,我将对我的特定情况进行基准测试(它可能完全由其他东西支配,比如内存带宽),但我很惊讶没有看到一个简洁的摘要来帮助我的直觉.
我将从CLR中做到这一点,如果它对生成的NaN的味道有所不同.
是否可以在没有浮点单元的嵌入式处理器中执行浮点运算?
我想在C中对FPU执行除法(使用整数值):
float foo;
uint32_t *ptr1, *ptr2;
foo = (float)*(ptr1) / (float)*(ptr2);
Run Code Online (Sandbox Code Playgroud)
在NASM中(来自通过GCC编译的对象),它具有以下表示:
mov rax, QWORD [ptr1]
mov eax, DWORD [rax]
mov eax, eax
test rax, rax
js ?_001
pxor xmm0, xmm0
cvtsi2ss xmm0, rax
jmp ?_002
?_001:
mov rdx, rax
shr rdx, 1
and eax, 01H
or rdx, rax
pxor xmm0, xmm0
cvtsi2ss xmm0, rdx
addss xmm0, xmm0
?_002:
mov rax, QWORD [ptr2]
; ... for ptr2 pattern repeats
Run Code Online (Sandbox Code Playgroud)
这个"黑魔法"下的是什么?_001是什么意思?不仅cvtsi2ss足以从整数转换为浮点数吗?
我有一个单行C函数return value * pow(1.+rate, -delay);- 它将未来值折现为现值.反汇编的有趣部分是
0x080555b9 : neg %eax 0x080555bb : push %eax 0x080555bc : fildl (%esp) 0x080555bf : lea 0x4(%esp),%esp 0x080555c3 : fldl 0xfffffff0(%ebp) 0x080555c6 : fld1 0x080555c8 : faddp %st,%st(1) 0x080555ca : fxch %st(1) 0x080555cc : fstpl 0x8(%esp) 0x080555d0 : fstpl (%esp) 0x080555d3 : call 0x8051ce0 0x080555d8 : fmull 0xfffffff8(%ebp)
虽然单步执行此函数,gdb说(速率为0.02,延迟为2;您可以在堆栈上看到它们):
(gdb) si 0x080555c6 30 return value * pow(1.+rate, -delay); (gdb) info float R7: Valid 0x4004a6c28f5c28f5c000 +41.68999999999999773 R6: Valid 0x4004e15c28f5c28f6000 +56.34000000000000341 R5: Valid 0x4004dceb851eb851e800 +55.22999999999999687 …
为什么当它进入ECX的循环时,有一些大的随机值为0?还有其他方法可以在这里制作循环吗?
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
function FPUTest(a:Double):Double;
asm
FINIT
FLD a
MOV ecx,0
@cycle:
FADD st(0), st(0)
loop @cycle
end;
var a:Integer;
begin
readln(a);
Writeln(FPUTest(a));
end
Run Code Online (Sandbox Code Playgroud)
.
如何使用 lldb 打印 FPU 寄存器?
在 gdb 中,您可以执行类似的操作p $st0,但是在 lldb 中执行相同的操作会导致错误:error: use of undeclared identifier '$st0'。
register read st0也不起作用并给出错误error: Invalid register name 'st0'.。
_control87笔记文档:
_control87[...]影响[s] x87和SSE2的控制字(如果存在).
似乎SSE和SSE2 MXCSR控制寄存器是相同的,但是,文档中没有提到SSE单元.是否_control87影响SSE单元的MXCSR控制寄存器或仅适用于SSE2?
我很困惑。我对 FLD m64fp 指令有一些疑问,但我不知道从哪里开始。因为这是作业,所以我不是特意要求答案,而是求解决问题的方法。任何建议或想法将不胜感激。
\n\n内存中的八个连续字节包含十六进制值 01、00、00、00、00、00、00、00。执行 FLD m64fp 指令。它的参数是这八个连续字节中第一个字节的地址。作为 FLD 指令的结果,ST(0) 中的值现在为:
\n\n1) 2^(-1075)\n2) 2^(-1074) \n3) 2^(-1023)\n4) 2^(-1022) \nRun Code Online (Sandbox Code Playgroud)\n\n另外,如果我有以下汇编代码
\n\n \xe2\x94\x820x8048384 <main> lea 0x4(%esp),%ecx \xe2\x94\x82\n \xe2\x94\x820x8048388 <main+4> and $0xfffffff0,%esp \xe2\x94\x82\n \xe2\x94\x820x804838b <main+7> pushl -0x4(%ecx) \xe2\x94\x82\n \xe2\x94\x820x804838e <main+10> push %ebp \xe2\x94\x82\n \xe2\x94\x820x804838f <main+11> mov %esp,%ebp \xe2\x94\x82\n \xe2\x94\x820x8048391 <main+13> push %ecx \xe2\x94\x82\n \xe2\x94\x820x8048392 <main+14> fldpi \xe2\x94\x82\n \xe2\x94\x820x8048394 <main+16> fsqrt \xe2\x94\x82\n \xe2\x94\x820x8048396 <main+18> fld1 \xe2\x94\x82\n \xe2\x94\x820x8048398 <main+20> fsubrp %st,%st(1) \xe2\x94\x82\n \xe2\x94\x820x804839a <main+22> mov $0x0,%eax \xe2\x94\x82\n \xe2\x94\x820x804839f <main+27> pop %ecx …Run Code Online (Sandbox Code Playgroud)