学习汇编基础之一(浮点数的计算机表示)

 

最作发布于:http://33024.blog.163.com/blog/static/123070422201172215949412/

参考:http://www.feiesoft.com <<经典汇编语言教程>>

             谭浩强《C语言教程》

author:wysoft@gmail.com

学习编程,整数、实数、字符等三种数据类型在计算机中的表示是以后学习编程的关键。很多类型在计算机中最终是转换这三种类型的数据进行表示。今天学习浮点数的计算机表示。

1、  非计算机的浮点数表示

两种形式:十进制表示法与指数形式表示法。指数形式表示法为:a E n(a为十进制数,n为十进制整数),其值为a*10如2.156e2=2.156*102=215.6

2、  计算机的浮点数表示.IEEE 754标准定义两种大小的浮点数,一种是32bits浮点数,称之为单精度浮点数,一种是64bits浮点数,称之为双精度浮点数。另英特尔自己弄了一个扩展型浮点数80bits。他们的表示形式为:

1)       单精度浮点数

2)       双精度浮点数

3)       扩展精度浮点数

 

3、  十进制浮点数转计算机表示的浮点数步骤

1)  把十进制浮点数转化成二进制表示。整数部分用2除,小数部分用2乘。

2)  规格化二进制数:改变阶码,使小数点前面仅有第一位有效数字。

3)  计算阶码:

a)  单精度数,新阶码=原阶码+0x7F

b)  双精度数,新阶码=原阶码+0x3FF

c)  扩展双精度,新阶码=原阶码+0x3FFF

4、  以浮点格式存储,把符号位、阶码、有效数字组合在一起即可。

注意:尾数是带有一个隐含位的23位数,即:数“1.XXXX”的尾数是“XXXX”,前面的”1”被隐含掉,它只在扩展精度的格式中才被显式表示出来。

5、  转换实例

a、转换成单精度浮点数

12.5转换成32位浮点数的二进制表示

1)12.5成了:1100.1

2)规格化为:1.1001*23,最终为:1.1001*211

3)计算阶码,11+01111111=10000010

4)合成为:0 10000010 10010000000000000000000

b、转换成双精度浮点数

32.58转换成64位双精度浮点数

1)32.58的二进制代码为:100000.1001010001

2)规格化为:1.000001001010001*2101

3)因为是双精度:新阶码=101+011 1111 1111=100 0000 0100

4)合成为 0100 0000 0100 0000 0100 1010 0010 0000 0000 0000 0000 0000 0000 0000 0000 0000

5)把合成的字符串转换成16进制数为:0x40404a4000000000

6、程序演示。c语言

在c语言中直接给浮点型变量赋上浮点数的16进制值或2进制值,是得不到我们期望的数据结果,因为在c语言中2进制值与16进制的表示只会被看作整形数,如 float a=0x40404a4000000000,c编译器会把0x40404a4000000000当作整型数转换成浮点数,会进行类型转换,c翻译成汇编代码后就不再是0x40404a4000000000这个值了。所以要用16进制或二进制数表示浮点型,必须用到字符数组,这玩意是原原本本表示内存内容的。废话少说,上代码:

/**********************************************************

  float.c 演示在程序中用十六进制或二进制代码方式表示浮点数

  author:wsysoft@gmail.com

 *********************************************************/

#include<stdio.h>

int main(void){

      /*12.5的单精度浮点的16进制代码为:0x41480000, 12.5的单精度二进制代码为:01000001010010000000000000000000因Intel cpu是little-endian,故转换成数组时低地址要存低位值

           */

      unsigned char str[4] __attribute__((aligned(4)))={0x00,0x00,0x48,0x41};

 

     /*double 32.58

            十六进制:0x40404a4000000000

            二进制:0100 0000 0100 0000 0100 1010 0010 0000 0000 0000 0000 0000 0000 0000 0000 0000

            用数组表示时请考虑是big-endian还是little-endian

            小数部分0.58因乘以2不能归零,所以计算机的显示与我们想象的会有误差。为了保证字符数组地址转成double指针变量的值

            需要告诉编译器字符数组的起始地址要按8的整数倍地址开始

     */

           unsigned char dstr[8] __attribute__((aligned(8)))=

                     {0x00,0x00,0x00,0x00,0x40,0x4a,0x40,0x40};

 

 

           /*c以下被注释的代码不行,因为字符串变成了ascill编码了,行不通*/

           //char *pchar __attribute__((aligned(4)))="\0x00\0x00\0x48\0x41";

 

           /***************************************************

             用一个长整型保存-12.5的16进制数,这种方式转可能有数据丢失,因为表达的范围不一致

           *                                                    */

           long longInt=0xc1480000;

     

/*用一个64位长整形转双精度,可能发生精据丢失*/

           long long int llint=0x40404a4000000000;

 

           float *a=(float *)str;

           float *b=(float *)&longInt;

           double *db=(double * )dstr;

           double *dc=(double * )&llint;

     

        

           printf("单精度数为:%f\n",*a);

           printf("单精度数为:%f\n",*b);

           printf("双精度数为:%lf\n",*db);

      printf("双精度数为:%lf\n",*dc);

 

           return 1;

}

 

输出结果是:float.exe

单精度数为:12.500000

单精度数为:-12.500000

双精度数为:32.580078

双精度数为:32.580078

 

6、  程序实例:汇编语言

在汇编语言中不能用.float 二制数编码或十六进制编码的形式来表示浮点数,原因c语言一样,本程序为了显示输出,调用了c的printf函数。在汇编中用字节来表浮点数的二进制编码(与c的char 数组功能一样)然后通过fpu单元 flds,flstp指令进行浮点数转换。从字节转换成真正地浮点数值。

.section .data

LC1:

   .ascii "%f\12\0"

value1:

   .byte 0x00,0x00,0x48,0x41

value2:

   .float 0.0

.section .text

.globl _start

_start:

   pushl         %ebp

   movl %esp, %ebp

   andl  $-16, %esp

   subl  $32, %esp

   movl $0x41480000, %eax

   movl %eax, 28(%esp)

   flds   28(%esp)

   fstpl  4(%esp)

   movl $LC1, (%esp)

   call   _printf

   flds    value1

   fstpl   value2

        addl $8,%esp

   pushl value2

        pushl  $LC1

   call _printf

   movl $1, %eax

   leave

   ret

         .def  _printf;     .scl    2;      .type          32;   .endef

 

编译连接:

as -o floattest.o floattest.s

ld -o floattest.exe floattest.o msvcrt.dll

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值