首页
社区
课程
招聘
[旧帖] [讨论]fild 的逆运算指令怎么写? 0.00雪花
发表于: 2008-9-7 14:44 4808

[旧帖] [讨论]fild 的逆运算指令怎么写? 0.00雪花

2008-9-7 14:44
4808
DWORD NToFloat(DWORD dw1)
{
       DWORD dw2;
      
      _asm
     {
         fild  dword ptr[dw1]
         fstp dword ptr[dw2]
     }
     return dw2;
}

// dw1 = 100.25 ,浮点数是 42C80000

问题1: 这个的逆运算怎么写.就是知道了浮点数怎么转换回原来的100.25.

问题2:100.25 的浮点数实际是42C88000.小数部分给弄掉了.怎么写才能连小数部分的浮点数一起显示出来.????

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 230
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
[QUOTE=豆腐乳;506283]DWORD NToFloat(DWORD dw1)
{
       DWORD dw2;
      
      _asm
     {
         fild  dword ptr[dw1]
         fstp dword ptr[dw2]
     }
   ...[/QUOTE]
星期一了.该有人回答了.
2008-9-8 08:57
0
雪    币: 305
活跃值: (36)
能力值: ( LV12,RANK:250 )
在线值:
发帖
回帖
粉丝
3
Microsoft Visual C++ 与 IEEE 数值标准一致。存在实数的三种内部变化。在 Visual C++ 中使用 Real*4 和 real*8。Real*4 用字 float 声明。Real*8 用字 double 声明。在 Windows 32 位编程中,long double 数据类型映射为 double。然而,对使用 real*10 数据类型的计算有汇编语言支持。

值如下存储:

值 存储为
real*4 符号位、8 位指数、23 位尾数
real*8 符号位、11 位指数、52 位尾数
real*10 符号位、15 位指数、64 位尾数

在 real*4 和 real*8 格式中,尾数中有一个假定的前导 1,而它并没有存储在内存中,因此尾数实际上是 24 位或 53 位,即使只存储了 23 位或 52 位。real*10 格式实际存储此位。

指数偏离可能值的一半。这表示实际的指数是从存储指数中减去此偏差获得的。如果存储指数小于此偏差,则它实际上是负指数。

指数如下偏离:

指数 偏离量
8 位 (real*4) 127
11 位 (real*8) 1023
15 位 (real*10) 16383

这些指数不是 10 的幂;它们是 2 的幂。也就是说,8 位存储指数最多可以为 127。值 2**127 大约等于 10**38,这是 real*4 的实际限制。

尾数被存储为 1.XXX... 形式的二进制分数。. 此分数有一个大于或等于 1 且小于 2 的值。注意实数总是以规范化形式存储;即尾数左移以使尾数的高序位总是 1。因为该位总是 1,所以在 real*4 和 real*8 格式中采用(而不是存储)它。假定二进制(不是十进制)点刚好在前导 1 的右边。

因此,各种大小的格式如下:

格式 字节 1 字节 2 字节 3 字节 4 ... 字节 n
real*4 SXXX XXXX XMMM MMMM MMMM MMMM MMMM MMMM     
real*8 SXXX XXXX XXXX MMMM MMMM MMMM MMMM MMMM ... MMMM MMMM
real*10 SXXX XXXX XXXX XXXX 1MMM MMMM MMMM MMMM ... MMMM MMMM

S 表示符号位,X 是指数位,M 是尾数位。注意最左边的位在 real*4 和 real*8 格式中被采用,但它在 real*10 格式的字节 3 中以 1 表示。

若要适当地变换二进制点,首先取消阶码,然后将二进制点向左或向右移动适当的位数。

示例
下面是 real*4 格式的一些示例:

在下面的示例中,符号位是零,存储指数是 128,以二进制表示则为 100 0000 0,即 127 加 1。000 0000 ... 存储尾数是 (1.)000 0000 ... 0000 0000,它有一个隐含的前导 1 和二进制点,因此实际的尾数是 1。
                    SXXX XXXX XMMM MMMM ... MMMM MMMM
2   =  1  * 2**1  = 0100 0000 0000 0000 ... 0000 0000 = 4000 0000
除了设置符号位外与 +2 相同。这适用于所有 IEEE 格式的浮点数。
-2  = -1  * 2**1  = 1100 0000 0000 0000 ... 0000 0000 = C000 0000
尾数相同,指数增加 1(偏差值是 129 或者二进制的 100 0000 1)。
4  =  1  * 2**2  = 0100 0000 1000 0000 ... 0000 0000 = 4080 0000
指数相同,尾数大一半 — 它是 (1.)100 0000 ...0000 0000,由于这是二进制分数,即 1 1/2(分数位数的值是 1/2、1/4、1/8 等等)。
6  = 1.5 * 2**2  = 0100 0000 1100 0000 ... 0000 0000 = 40C0 0000
指数与其他 2 的幂相同,尾数是 127 或二进制的 011 1111 1 处小于 2 的 1。
1  = 1   * 2**0  = 0011 1111 1000 0000 ... 0000 0000 = 3F80 0000
阶码是 126(它是二进制中的 011 1111 0),尾数是 (1.)100 0000 ... 0000 0000,表示 1 1/2。
.75 = 1.5 * 2**-1 = 0011 1111 0100 0000 ... 0000 0000 = 3F40 0000
除了在尾数中设置表示 1/4 的位,完全与 2 相同。
2.5 = 1.25 * 2**1 = 0100 0000 0010 0000 ... 0000 0000 = 4020 0000
1/10 在二进制中是重复的分数。尾数害怕 1.6,而阶码假定 1.6 被 16 除(它是二进制中的 011 1101 1,十进制中是 123)。实际的指数是 123 – 127 = –4,表示乘法因数是 2**–4 = 1/16。请注意,存储尾数在最后一位被舍入(尝试尽可能精确地表示无法表示的数)。(1/10 和 1/100 在二进制中表示不严格的原因类似于 1/3 在十进制中表示不严格的原因。)
0.1 = 1.6 * 2**-4 = 0011 1101 1100 1100 ... 1100 1101 = 3DCC CCCD
0 = 1.0 * 2**-128 = all zeros--a special case.
2008-9-8 09:20
0
雪    币: 230
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢了.是不是借助寄存器还能简单点.怎么能利用寄存器写出逆运算来?
2008-9-8 13:28
0
雪    币: 230
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
[QUOTE=豆腐乳;506283]DWORD NToFloat(DWORD dw1)
{
       DWORD dw2;
      
      _asm
     {
         fild  dword ptr[dw1]
         fstp dword ptr[dw2]
     }
   ...[/QUOTE]
假设1.0 换成浮点数是3F800000,怎么把3F800000在换成1.0.
2008-9-10 17:08
0
雪    币: 247
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
没看懂你想说什么
2008-9-10 17:21
0
雪    币: 230
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
我还以为我说得挺清楚的了.
假设:
    DWORD dw1=0x1;
    DWORD dw2;
    _asm
   {
         fild dwor ptr [dw1]
         fstp dword ptr[dw2]
   }
   dw2 得到的3F80000.

我想问的是假设知道了3F80000,怎么才能转回到1.

要是还没说明白.我就不问了.这个就是我能说明白的极限了.
2008-9-10 17:54
0
游客
登录 | 注册 方可回帖
返回
//