2015-05-24 20 views
3

我很困惑。我对FLD m64fp指令有一些疑问,但我不知道从哪里开始。因为这是一项家庭作业,我不是特意要求答案,而是解决问题的方法。任何建议或想法,将不胜感激。关于程序集FLD指令困惑m64fp

内存中的八个连续字节包含十六进制值01,00,00,00,00,00,00,00.FLD m64fp指令被执行。它的参数是这八个连续字节中第一个的地址。由于FLD指令的结果,在ST的值(0)现在是:

1) 2^(-1075) 
2) 2^(-1074) 
3) 2^(-1023) 
4) 2^(-1022) 

另外,如果我有这下面的汇编代码

│0x8048384 <main>    lea 0x4(%esp),%ecx                                    │ 
    │0x8048388 <main+4>    and $0xfffffff0,%esp                                    │ 
    │0x804838b <main+7>    pushl -0x4(%ecx)                                     │ 
    │0x804838e <main+10>    push %ebp                                       │ 
    │0x804838f <main+11>    mov %esp,%ebp                                     │ 
    │0x8048391 <main+13>    push %ecx                                       │ 
    │0x8048392 <main+14>    fldpi                                        │ 
    │0x8048394 <main+16>    fsqrt                                        │ 
    │0x8048396 <main+18>    fld1                                        │ 
    │0x8048398 <main+20>    fsubrp %st,%st(1)                                     │ 
    │0x804839a <main+22>    mov $0x0,%eax                                     │ 
    │0x804839f <main+27>    pop %ecx                                       │ 
    │0x80483a0 <main+28>    pop %ebp                                       │ 
    │0x80483a1 <main+29>    lea -0x4(%ecx),%esp                                    │ 
    │0x80483a4 <main+32>    ret 

如何找出值会在主返回之前在ST(0)? 谢谢。

+0

浮点数由一个'符号位',一个偏向'指数'和一个'重要/尾数'组成。第一个问题的复杂情况是x86是小端,所以在这种情况下浮点数将是一个反常规。 – EOF

回答

3

让我们从第一个问题开始。

它没有明确说明,但我认为我们可以假设我们在这里处理的是小端技术(现在每台将要使用的PC都将使用它)。因此,如果您在该内存位置执行FLD m64p,则浮点堆栈将以相反顺序包含这些字节 - 即00 00 00 00 00 00 00 01。让我们来看看双精度格式是什么样子: enter image description here

现在,这实际上是一种特殊情况 - 由于指数是零和的尾数是不是,我们代表号 - 一个无法表达使用标准化的尾数,即其中整数部分为1(1.xxx) - 它需要前导零(记住,因为指数偏置(1023),零实际上意味着1 - exponent (0) - 1023在这里,所以-1022

由于Wikipedia告诉我们,我们可以使用以下公式计算次正常值的数值: enter image description here

然而,尾数中的最低有效位(并且只有那一个)被设置,并且这给出了尾数值(因为我们在双精度格式中尾数为52位)。

因此,如果我们使用该公式,我们得到的是:
(-1)^0 x 2^(1-1023) x 2^(-52) = 1 x 2^(-1022) x 2^(-52) = 2^(-1022 - 52) = 2^(-1074),这是答案2

这是最小的正次正规数 - 如果最后一点是没有设置,将位代表签署零

为了测试(或者更容易找出结果,如果您感觉懒惰:)),您可以使用Windows的OllyDbg,它允许您即时修改汇编代码。让我们进入这个问题给出的指令:

enter image description here

,让我们的字节数设置为需要的值:

enter image description here

事实上,当我们执行的是,我们得到这样的:

enter image description here

这是(几乎)等于2^(-1074)



现在,关于第二个问题。我们来分析一下你列出的说明。

  1. 我们从fldpi开始,相当于ST(0) = PI
  2. 我们执行fsqrt,所以现在我们有ST(0) = sqrt(PI)
  3. fld1加载一个到ST(0),所以堆栈看起来像这样:ST(0) = 1,ST(1) = sqrt(PI)
  4. fsubrp执行反转减法并弹出寄存器堆栈。由于这是T组件,因此它的源头是buggy one,所以我们从​​中减去ST(0),将结果存储在​​中,然后弹出寄存器堆栈,以使​​变为ST(0)。实际上,现在我们有ST(0) = sqrt(PI) - 1,这接近0.772。当main返回时,此值将保留在ST(0)中,因为稍后没有任何修改浮点堆栈。
+0

顺便说一句,我没有提及FPU指令的bug - 谢谢Jester。 – szczurcio

+2

@Jester,szczurcio:谢谢你的帮助! – shjnlee