Chinaunix首页 | 论坛 | 博客
  • 博客访问: 501933
  • 博文数量: 704
  • 博客积分: 39800
  • 博客等级: 大将
  • 技术积分: 4950
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-15 13:32
文章分类

全部博文(704)

文章存档

2011年(1)

2008年(703)

我的朋友

分类:

2008-10-15 13:43:39

    昨天跟一个朋友讨论一个问题:
    float n1=3.0;

    double n2=3.0;

    long n3=2000000000;

    long n4=1234567890;

    printf("%ld %ld %ld %ld\n", n1, n2, n3, n4);

    在x86 32位机上执行,输出结果是:0 1074266112 0 1074266112按照我的理解,float和long在32位机下都占4个字节,即使无法格式化为long进行输出,后面的值也不至于都出问题。

    实际里面涉及以下的知识,

    1. 把上面的代码反汇编可以看到:

    mov 0x80494b4,%eax

    mov %eax,0x18(%esp)

    mov 0x80494b0,%eax

    mov %eax,0x14(%esp)

    fldl 0x80494a8 fstpl 0xc(%esp)

    flds 0x80494a0 fstpl 0x4(%esp)

    movl $0x8048478,(%esp)

    call 0x804828c

    我先后把这几个变量定义成了局部和全局的进行了,这段是用全局的汇编码。

    关键是这几句:

    fldl 0x80494a8

    fstpl 0xc(%esp)

    flds 0x80494a0

    fstpl 0x4(%esp)

    fldl把浮点地址交给浮点运算寄存器,浮点寄存器是64为精度的,然后fstpl再把值取出按照64位入栈,表象就是按照double类型入栈了

    所以虽然内存中单精度浮点数是以4字节的,但编译器把它转成了8字节进行处理。

    所以最后在栈里的就成了
    | 00 00 00 00 |<——ESP

    | 40 40 00 00 |

    | 00 00 00 00 |

    | 40 40 00 00 |

    | 49 96 02 d2 |

    | 77 35 94 00 |<——EBP

    2. printf的处理方式是将输入参数按照字符串进行格式化解析,由于输入的是ld ld ld ld,按照4字节依次进行取值,就得到了上面的结果。

    3. float是单精度浮点,遵从IEEE754, S(1)-E(8)-M(23)。3二进制位11,表示为:1.1×2^1 => 指数部分127+1=128-

  >10000000,小数部分为1,因此其浮点表示为:

    0 10000000 10000000000000000000000,也就是上面1中看到的0x40400000,打印出的十进制就是1074266112.

    后来又找来台cavium64位的机器上跑了一下,发现都是正确的,即使按照%d方式输出也没有问题,没法在cavium上反汇编无法确认。

【责编:huangchunmei】

--------------------next---------------------

阅读(1989) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~