FXTRACT 指令示例 [英] FXTRACT instruction example

查看:26
本文介绍了FXTRACT 指令示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用 NASM 写了这段代码:

I wrote this code in 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 = 123456fexp = -3.
或者类似:fsig = 1.23456fexp = 3.
那么,我错过了什么?

I was waiting to find: fsig = 123456 and fexp = -3.
Or something like: fsig = 1.23456 and fexp = 3.
So, what Am I missing?

推荐答案

fxtract 为您提供以 2 为底的指数,正如@Jester 在评论中所说.

fxtract gives you the exponent base 2, as @Jester said in the comments.

  • 123.456 = 1.929 ×26

要得到以 10 为底的指数,您必须了解对数.您计算输入的以 10 为底的对数,然后将其截断为整数.在 x87 中,fldlg2 给出 log10(x),那么 fyl2x 就可以计算对数

To get the exponent base 10, you must know about logarithms. You calculate the logarithm base 10 of the input, then truncate it to an integer. In x87, fldlg2 gives log10(x), then fyl2x can calculate the logarithm as

  • log10(x) = log10(2) ×log2(x)
  • log10(x) = log10(2) × log2(x)

要将其截断为整数,请将 x87 设置为向零舍入(通过将 0x0c000 放入控制字中)并使用 frndint.

To truncate it to an integer, you set the x87 to round toward zero (by oring 0x0c000 into the control word) and use frndint.

要计算有效数,您将输入除以 10 的幂.获得 10 的幂的习惯方法是使用 2 和 5 的幂,使用 5 的幂的整数运算(如 David M. Gay 的 pow5mult),并缩放 2 的幂的浮点指数.一种更简单但可能更慢或更不准确的方法是使用 x87 和公式

To calculate the significand, you divide the input by the power of 10. The customary way to get a power of 10 is to use powers of 2 and 5, using integer arithmetic for powers of 5 (as in David M. Gay's pow5mult), and scaling the floating-point exponent for powers of 2. A simpler, but perhaps slower or less accurate way, is to use the x87 and the formula

  • 10p = 2m = 2r ×2m - r 其中 m = log210 ×p 和 r = round(m)
  • 10p = 2m = 2r × 2m - r where m = log210 × p and r = round(m)

在 x87 中,fldl2t 提供 log2(10).f2xm1 计算 2x - 1 如果 x 是 -1 和 1 之间的分数.fscale 乘以 2r如果 r 是整数.

In x87, fldl2t provides log2(10). f2xm1 calculates 2x - 1 if x is a fraction between -1 and 1. fscale multiplies by 2r if r is an integer.

代码是

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

我添加了标签 mainint 3 以便我可以在 OpenBSD/amd64 上的 gdb 中运行它.

I have added the label main and the int 3 so I can run this in gdb on OpenBSD/amd64.

$ 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

这篇关于FXTRACT 指令示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆