使用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.