从整数到浮点的转换如何工作?

时间:2014-05-12 19:52:41

标签: assembly floating-point integer

每种编程语言都有自己的方法将整数转换为浮点数,将01010转换为其他01010。 如果您看到ASM生成的代码,它会使用协处理器指令向用户隐藏真实值。

但它如何在真实中发挥作用?如何计算尾数,指数算法?

3 个答案:

答案 0 :(得分:4)

如果你知道浮点格式,你应该能够自己计算出算法。

  1. 如果输入为0,则结果为全0位。
  2. 如果输入为负,则将符号位设置为1,并补充输入。
  3. 找到最高位集。将偏差添加到其索引中,这将是您的指数。
  4. 清除最高位集,剩下的是尾数。
  5. 由于此问题已标记为,因此以下是x86的示例实现:

    int_to_float:
        xor eax, eax
        mov edx, [esp+4]
        test edx, edx
        jz .done
        jns .pos
        or eax, 0x80000000 ; set sign bit
        neg edx
    .pos:
        bsr ecx, edx
        ; shift the highest bit set into bit #23
        sub ecx, 23
        ror edx, cl         ; works for cl < 0 too
        and edx, 0x007fffff ; chop off highest bit
        or eax, edx         ; mantissa
        add ecx, 127 + 23   ; bias
        shl ecx, 23
        or eax, ecx         ; exponent
    .done:
        ret
    

    注意:这会返回eax中的float,而调用约定通常会强制st0。我只是想完全避免使用FPU代码。

答案 1 :(得分:2)

当将整数转换为浮点数时,它只是移动直到尾数在正确的范围内,即1 <1。 m&lt; 2,指数就是它移动了多少步。

例如,数字1010会移动到1.010,指数为3,因为它是移位的位数。

尾数的第一个数字,即小数分隔符前的1,不会存储在数字中,因为它总是一个。 (零值被视为一个单独的案例。)

expontent(对于双精度数)存储的偏移量为1023(001111111111),因此expontent 3存储为1026(010000000010)。

这使得1010的表示形式为双精度浮点数:

010000000010 010 0000000000000000000000000000000000000000000000000

010之后的所有零都是填充52位尾数的其余部分。


您可以在此处阅读有关浮点格式的更多信息:
Wikipedia: Double-precision floating-point format

答案 2 :(得分:0)

对于32位int,64位int64和IEEE 64位double,以下技巧有效(除了违反别名规则等):

double convert(int x) {
  double tricky = 0x1.8p53;
  int64 hack = (int64 &)tricky + x;
  return (double &)hack - 0x1.8p53;
}

我在这里tricky = 2^53 + 2^52。此值中可表示的最小变化为1,表示有效数以1为单位进行测量。有效数存储在double的低位52位中。通过向x添加x,我不会溢出或下溢有效数字(因为hack是32位),因此2^53 + 2^52 + xdouble的二进制表示形式一个2^53 + 2^52。减去x给我double,但作为movsx rax, dword ptr [x] add rax, [tricky] mov [hack], rax fld [hack] fsub st(0), [tricky] fstp [answer]

(接下来,我认为,接近于x86-64汇编代码。我不明白为什么它不会做正确的事情,但我还没有对它进行测试。或者甚至组装了它。)

{{1}}