使用 fldcw 指令可以将 FPU 单元的精度更改为 24 位或更多位。然而,在做了一些测试之后,我开始认为实际上很少有 x87 操作使用该设置。
我尚未测试所有操作,但到目前为止,在这台测试机器上,看起来只有 fdiv 和 fsqrt 以选定的精度停止计算,并且所有其他操作(fadd fsub fmul ...)总是计算完整的扩展精度。
如果是这种情况,我希望它是因为这 2 条指令(fdiv 和 fsqrt)比大多数其他 x87 FPU 指令慢得多,所以当较低的精度足够时,可以加快它们的速度,但实际上,我只是想知道如果一直都是这种情况,或者这是我的测试机器中使用的最新处理器的怪癖。
编辑:这是显示它的delphi代码
program Project1;
uses
windows,dialogs,sysutils;
{$R *.res}
const
test_mul:single=1234567890.0987654321;
var
i:longint;
s:single absolute i;
s1,s2,s3:single;
procedure test_24;
asm
mov word([esp-2]),$103f // 24bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s1]
end;
procedure test_53;
asm
mov word([esp-2]),$123f // 53bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s2]
end;
procedure test_64;
asm
mov word([esp-2]),$133f // 64bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s3]
end;
begin
i:=0;
repeat
test_24;
test_53;
test_64;
if (s1<>s2) or (s2<>s3) then begin
showmessage('Error at step:'+inttostr(i));
break;
end;
inc(i);
until i=0;
showmessage('No difference found between precisions');
end.
edit2:误报,我弄错了,我存储为单个而不是扩展,所以无法发现差异,这是一个固定的测试,感谢 hans passant 发现了我的错误:
program Project1;
uses
windows,dialogs,sysutils;
{$R *.res}
const
test_mul:single=1234567890.0987654321;
var
i:longint;
errors:cardinal;
s:single absolute i;
s1,s2,s3:extended;
procedure test_24;
asm
mov word([esp-2]),$103f // 24bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s1]
end;
procedure test_53;
asm
mov word([esp-2]),$123f // 53bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s2]
end;
procedure test_64;
asm
mov word([esp-2]),$133f // 64bit precision, trunc
fldcw word([esp-2])
fld [s]
fmul [test_mul]
fstp [s3]
end;
begin
errors:=0;
i:=0;
repeat
test_24;
test_53;
test_64;
if (s1<>s2) or (s2<>s3) then begin
inc(errors);
end;
inc(i);
until i=0;
showmessage('Number of differences between precisions: '+inttostr(errors));
end.