Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly FXTRACT指令示例_Assembly_X86_X87 - Fatal编程技术网

Assembly FXTRACT指令示例

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

我用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] ; fexp = 6
我在等待找到:
fsig=123456
fexp=-3

或者类似于:
fsig=1.23456
fexp=3


那么,我遗漏了什么呢?

fxtract
给出了指数基数2,正如@Jester在评论中所说的那样

  • 123.456=1.929×26
要得到以10为底的指数,必须了解对数。计算输入的以10为底的对数,然后将其截断为整数。在x87中,
fldlg2
给出log10(x),然后
fyl2x
可以作为

  • log10(x)=log10(2)×log2(x)
要将其截断为整数,请将x87设置为向零舍入(通过
将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。为了扩展这个很好的例子,你应该在取对数之前检查符号。无论如何,这是一个很好的例子。