Assembly FXTRACT指令示例
我用NASM编写了以下代码:Assembly FXTRACT指令示例,assembly,x86,x87,Assembly,X86,X87,我用NASM编写了以下代码: section .data fvar: dd 123.456 fsig: dq 0.0 fexp: dq 0.0 section .text fld dword[fVar] fxtract ; put significand in ST(0), and exponent in ST(1) fstp qword[fsig] ; fsig = 1.929 fstp qword[fexp] ; f
section .data
fvar: dd 123.456
fsig: dq 0.0
fexp: dq 0.0
section .text
fld dword[fVar]
fxtract ; put significand in ST(0), and exponent in ST(1)
fstp qword[fsig] ; fsig = 1.929
fstp qword[fexp] ; fexp = 6
我在等待找到:fsig=123456
和fexp=-3
或者类似于:
fsig=1.23456
和fexp=3
那么,我遗漏了什么呢?
fxtract
给出了指数基数2,正如@Jester在评论中所说的那样
- 123.456=1.929×26
fldlg2
给出log10(x),然后fyl2x
可以作为
- log10(x)=log10(2)×log2(x)
或将0x0c000插入控制字),然后使用frnint
要计算有效位,将输入除以10的幂。获得10次方的惯用方法是使用2和5次方,使用5次方(如中所示),并缩放浮点指数以获得2次方。一种更简单,但可能更慢或更不准确的方法是使用x87和公式
- 10p=2m=2r×2m-r,其中m=log210×p,r=圆形(m)
在x87中,fldl2t
提供log2(10)f2xm1
如果x是介于-1和1之间的分数,则计算2x-1<代码>fscale
如果r是整数,则乘以2r
代码是
section .data
fvar: dd 123.456
fsig: dq 0.0
fexp: dq 0.0
section .bss
newcw: resw 1
oldcw: resw 1
section .text
global main
main:
fld dword[fvar]
;; fexp = truncate(log_10(fvar))
fld st0
fldlg2
fxch st1 ; st2 = fvar, st1 = log_10(2), st0 = fvar
fyl2x ; log_10(fvar) = log_10(2) * log_2(fvar)
fstcw [oldcw]
mov dx, [oldcw]
or dx, 0x0c000 ; rounding mode = 3, toward zero
mov [newcw], dx
fldcw [newcw]
frndint ; truncate log_10(fvar)
fldcw [oldcw] ; restore old rounding mode
fst qword[fexp]
;; fsig = fvar / 10^(fexp)
fldl2t ; st2 = fvar, st1 = fexp, st0 = log_2(10)
fmulp ; m = log_2(10) * fexp
fld st0
frndint ; integral part of m
fxch st1 ; st2 = fvar, st1 = integer, st0 = m
fsub st0, st1 ; fractional part of m
f2xm1
fld1
faddp ; 2^(fraction)
fscale ; 10^fexp = 2^(integer) * 2^(fraction)
fstp st1 ; st1 = fvar, st0 = 10^fexp
fdivp ; fvar / 10^fexp
fstp qword[fsig]
int 3
我添加了标签main
和int3
,这样我就可以在OpenBSD/amd64上的gdb中运行它
$ nasm -felf64 float10.s && gcc -nopie -o float10 float10.o
$ gdb float10
...
(gdb) run
...
Program received signal SIGTRAP, Trace/breakpoint trap.
...
(gdb) x/1wf &fvar
0x601000 <fvar>: 123.456001
(gdb) x/1wg &fsig
0x601004 <fsig>: 1.2345600128173828
(gdb) x/1wg &fexp
0x60100c <fexp>: 2
$nasm-felf64 float10.s&&gcc-nopie-o float10 float10.o
$gdb浮动10
...
(gdb)运行
...
程序接收信号信号陷阱,跟踪/断点陷阱。
...
(gdb)x/1wf和fvar
0x601000:123.456001
(gdb)x/1wg和fsig
0x601004:1.2345600128173828
(gdb)x/1wg和fexp
0x60100c:2
请注意,处理器以二进制方式工作123.45=1.92890625*2^6
@Jester thank's,我稍微更改了值,但我无论如何都能得到您想要的,链接到C标准库,然后做调用ftoa
:-)另请参见:,并且@Jester您愿意将此作为答案发布吗?或者你认为这个问题应该结束吗?@CodyGray:ftoa
是一个标准的C库函数吗?如果我尝试这段代码(我尝试过),fvar不能为负。它给出了fyl2x上的NaN。为了扩展这个很好的例子,你应该在取对数之前检查符号。无论如何,这是一个很好的例子。