FXTRACT 指令示例 [英] FXTRACT instruction example
问题描述
我用 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 = 123456
和 fexp = -3
.
或者类似:fsig = 1.23456
和 fexp = 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 or
ing 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
我添加了标签 main
和 int 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屋!