学习汇编基础之一(浮点数的计算机表示)
2011-08-22 02:06
831 查看
最作发布于:http://33024.blog.163.com/blog/static/123070422201172215949412/
参考:http://www.feiesoft.com <<经典汇编语言教程>>
谭浩强《C语言教程》
author:wysoft@gmail.com
学习编程,整数、实数、字符等三种数据类型在计算机中的表示是以后学习编程的关键。很多类型在计算机中最终是转换这三种类型的数据进行表示。今天学习浮点数的计算机表示。
1、 非计算机的浮点数表示
两种形式:十进制表示法与指数形式表示法。指数形式表示法为:a E n(a为十进制数,n为十进制整数),其值为a*10n 如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 |
相关文章推荐
- Linux内核分析第一周学习博客 --- 通过反汇编方式学习计算机工作过程
- Linux基础学习笔记之硬盘空间计量单位换算与计算机数据计量单位换算区别
- 计算机入门基础学习
- 为什么要学习计算机知识(英语专业文化基础第一节课讲稿-部分)
- Call指令和Ret指令讲解03 - 零基础入门学习汇编语言50
- 学习资料收集:计算机系统基础
- [BX]和loop指令05 - 零基础入门学习汇编语言27
- linux学习之计算机基础(五)
- 计算机基础和组成原理——学习资料(更新.........)
- 标志寄存器05 - 零基础入门学习汇编语言58
- 更灵活的定位内存地址的方法02 - 零基础入门学习汇编语言33
- 杂货边角(1):计算机中有符号数和浮点数表示和运算
- 寄存器(CPU工作原理)01 - 零基础入门学习汇编语言06
- 直接定址表01 - 零基础入门学习汇编语言72
- 计算机组成原理与汇编语言学习笔记(1)
- 《IT播吧.-.大灰狼老师出品的零基础汇编视频课程》学习笔记
- 大学计算机基础第四版理论基础和学习指导书后习题答案
- 内中断01 - 零基础入门学习汇编语言60
- TQ2440 学习笔记—— 15、基础知识小结【汇编、vi】