从汇编指令解决浮点数疑问
x87 FPU
:本文默认使用x87 FPU指令
注:x87 FPU特指与x86处理器配套的浮点协处理器架构
–浮点寄存器采用栈结构
- 深度为8,宽度为80位,即8个80位寄存器
- 名称为 ST(0) ~ ST(7),栈顶为ST(0),编号分别为 0~7
–所有浮点运算都按80位扩展精度进行
–浮点数在浮点寄存器和内存之间传送
- float、double、long double型变量在内存分别用IEEE 754单精度、
双精度和扩展精度表示,分别占32位(4B)、64位(8B)和96位(12B,其中高16位无意义)- float、double、long double类型变量在浮点寄存器中都用80位扩展精度表示
- 从浮点寄存器到内存:80位扩展精度格式转换为32位或64位
- 从内存到浮点寄存器:32位或64位格式转换为80位扩展精度格式
浮点处理指令
•数据传送类
(1) 装入(转换为80位扩展精度)FLD:将数据从存储单元装入浮点寄存器栈顶 ST(0)FILD:将数据从int型转换为浮点格式后,装入浮点寄存器栈顶
(2) 存储(转换为IEEE 754单精度或双精度)FSTx:x为s/l时,将栈顶ST(0)转换为单/双精度格式,然后存入存储单元FSTPx:弹出栈顶元素,并完成与FSTx相同的功能FISTx:将栈顶数据从int型转换为浮点格式后,存入存储单元FISTP:弹出栈顶元素,并完成与FISTx相同的功能
带P结尾指令表示操作数会出栈,也即ST(1)将变成ST(0)
(3) 交换FXCH:交换栈顶和次栈顶两元素
(4) 常数装载到栈顶FLD1:装入常数1.0FLDZ:装入常数0.0FLDPI:装入常数pi (=3.1415926...)FLDL2E :装入常数log(2)eFLDL2T:装入常数log(2)10FLDLG2 :装入常数log(10)2FLDLN2:装入常数Log(e)2•算术运算类
(1)加法FADD/FADDP:相加/相加后弹出栈FIADD:按int型转换后相加
(2)减法FSUB/FSUBP:相减/相减后弹出栈FSUBR/FSUBRP:调换次序相减/相减后弹出栈FISUB:按int型转换后相减FISUBR:按int型转换并调换次序相减
若指令未带操作数,则默认操作数为ST(0)、ST(1)
带R后缀指令是指操作数顺序变反,例如:fsub执行的是x-y,fsubr执行的就是y-x
(3) 乘法FMUL/FMULP: 相乘/相乘后弹出栈FIMUL:按int型转换后相乘
(4) 除法FDIV/FDIVP : 相除/相除后弹出栈FIDIV:按int型转换后相除FDIVR/FDIVRP:调换次序相除/相减后弹
问题一
(右边多一条赋值语句)
问题:使用老版本gcc -O2 编译时,程序一输出0,程序二输出1,是什么原因造成的?
先看函数的汇编
fld1:即将常数1.0压入栈顶ST(0)
fidivl:将指定的操作数epb寄存器内容+8地址中的01序列(即int x 此时为10),中的int型转换为double型,再将ST(0) (1.0)除以该数,并将结果存入ST(0)中f(10)
f(10)=1.0(80位扩展精度)/10(转换为double)=0.1
0.1=0.00011[0011]B无限循环小数无法精确表示程序一
a=f(10);
b=f(10);
i=a==b;
a=f(10);
把10作为参数调用函数,计算的结果赋给a,把f(10)存到0xfffffff8开始的64位单元中(即a的地址)
即从80位->64位
b=f(10);
同样把10作为参数调用函数,此时fldl把64位的a重入栈顶,即64位->80位,此时b在ST(1),
然后fucompp比较ST(0)和ST(1),b仍为80位
所以此时a!=b程序二
a=f(10);
b=f(10);
c=f(10;
i=a==b;
可以发现,a,b都先存入内存,80位->64位,c一直在浮点寄存器中,然后比较前a,b都入栈,即c到ST(2),a到ST(1),b到ST(0),ab同时从64位->80位所以比较时相等。
问题二
不都是强制转换吗?怎么会不一样?
关键差别为fldl和fildl
相信大家看了汇编代码后已经有了答案
参考:南大计算机系统基础(一)
从汇编指令解决浮点数疑问相关推荐
- MIPS指令集处理器设计(支持64条汇编指令)
一.题目背景和意义 二.国内外研究现状 (略) 三.MIPS指令集处理器设计与实现 (一).MIPS指令集功能性梳理 1.MIPS指令集架构 (1).mips基础指令集格式总结 MIPS是(Micro ...
- S5PV210体系结构与接口02:ARM编程模型 汇编指令
目录 1. ARM的基本设定 1.1 ARM数据类型 1.1.1 基本数据类型 1.1.2 浮点数据类型 1.1.3 存储器大小端 1.2 支持的指令集 2. Cortex-A8编程模型 2.1 处理 ...
- 汇编指令入门级整理 | 原力计划
作者 | AlbertS 出品 | CSDN 博客 前言 我们大都是被高级语言惯坏了的一代,源源不断的新特性正在逐步添加到各类高级语言之中,汇编作为最接近机器指令的低级语言,已经很少被直接拿来写程序了 ...
- 程序员如何玩转汇编指令?
作者 | 帅地 责编 | 郭芮 我想大部分都知道 i++ 和 ++i的区别,i++ 就是先拿i来使用,之后再自增加1,而++i则是先自增加1,在拿i来使用.例如对于下面这两个语句,我敢保证大部分人都会 ...
- 常用的arm汇编指令(3) -学无止尽,积土成山,积水成渊
1. NEGS R3, R2; 求补指令 带进位加法指令 ADC(Addition Carry); Bpl是跳转指令,其中pl代表正号+,Bpl也就是当结果为正时,跳转; ORR( ...
- 汇编指令lmm_动画视频角色的LMM神经网络
汇编指令lmm Researchers at Ubisoft have proposed an alternative to the Motion Matching algorithm for aut ...
- ida pro 反汇编 Android so 库后修改 arm 汇编指令的方法总结
1 前言 最近博主在学习Android逆向的时候,参照吾爱破解论坛的<教我兄弟学Android逆向系列课程>学习的时候,学到第8章<教我兄弟学Android逆向08 IDA爆破签名验 ...
- x86与x86-64数据格式与常用的汇编指令笔记
1.数据格式 由于是从16位体系结构扩展成 32位的,Intel 用术语 "字(word)"表示16位数据类型.因此,称32位数为"双字(double words)&qu ...
- Win32汇编:字符串浮点数运算过程
整理复习汇编语言的知识点,以前在学习<Intel汇编语言程序设计 - 第五版>时没有很认真的整理笔记,主要因为当时是以学习理解为目的没有整理的很详细,这次是我第三次阅读此书,每一次阅读都会 ...
最新文章
- 程序员面试题精选100题(27)-二元树的深度[数据结构]
- instance的用法 php,php面向对象之instanceof关键字的用法
- MySQL Server has gone away报错原因汇总
- easyui,layui和 vuejs 有什么区别
- 无配置文件下使用log4net
- 北大助理教授献给「后浪」的建议:奔涌吧,深度学习!
- xu2w显示屏软件下载_LED显示屏控制软件(LED BEST)
- 倾斜摄影技术应用之:自动三维建模对输电线路走廊资源快速调查
- 大数据入门教程系列之Hbase安装(伪分布式)
- 计算机一级程测试题,2017计算机全国一级考试选择题整理.doc
- 还在为取快递而烦恼吗?智宇物联助力自动快递柜
- 关于如何开启本地代理隐藏本地ip
- C++ sprintf 方法使用示例( for循环数组,字符串拼接、删除、格式化等)
- Java面试基础知识III
- php获得客户端ip地址范例
- 阅读 redis 源码,学习缓存淘汰算法 W-TinyLFU
- 在一家虚拟现实公司工作是什么感受?
- Kafka扩分区和分区副本重分配之后消费组会自动均衡吗?
- PHP 越南语转英文大小写
- Go 语言实战: 编写可维护 Go 语言代码建议