Linux 0.12 OS. math - add.c
来源:互联网 发布:电子数据交换技术ppt 编辑:程序博客网 时间:2024/06/04 19:52
临时实数的加法运算模拟了整数的加法运算,把符号位和尾数部分整合成一个signed整数,在利用add指令完成加法操作。
一 正数与负数
这里说一下我自己理解的另一种补码的表现方式,以下用一个byte来做解释,先来举个例子
5的补码:0b00000101,它对应的无符号值也是为5
-5的补码:0b00000101 -> 取反-> 0b11111010 -> +1 ->0b11111011,它对应的无符号值是251
细心的你应该早已发现,-5的补码其实就是256-5的无符号值,8位二进制可以表示256种数值,也即8位的无符号值可以对应出8位带符号的值
0 -> 0
1 -> 1
...
127 -> 127
128 -> -128
129 -> -127
...
255 -> -1
可以发现负数的补码其实是256-(-负数)的二进制形式。
计算机课程中,-5的补码形式是将原码的符号位不变,数值位取反,然后加1,我们将256-(-负数)变化一下就是255-(-负数)+1,有没有感觉,255-(-负数)其实就是数值位取反。还有一个非常妙的地方,251(-5的无符号数值)的补码是什么,我们来计算一下,256-(-5)=5,也就是说5的正数和负数的补码运算是可逆的。
二 求补码
/* 求补码,正数的补码为本身,负数的补码等于其原码的符号位不变,数值部分的各位取反,然后整个数加1。*/#define NEGINT(a) \__asm__("notl %0 ; notl %1 ; addl $1,%0 ; adcl $0,%1" \:"=r" (a->a),"=r" (a->b) \:"0" (a->a),"1" (a->b))
三 符号化
static void signify(temp_real * a){/* 增加2位防止溢出,一位用来表示符号,一位用来防止溢出 */a->exponent += 2; /* 如果指数已经达到最大值怎么办?这样直接加会导致溢出到符号位,应该这样 if ((a->exponent & 0x7fff) < 0x7ffe) a->exponent += 2;*/__asm__("shrdl $2,%1,%0 ; shrl $2,%1":"=r" (a->a),"=r" (a->b):"0" (a->a),"1" (a->b)); /* 指数+2,对应的尾数向右移动2位 */if (a->exponent < 0) /* 判断符号位负数(最高位为1)*/NEGINT(a); /* 求a(负数)的补码 */a->exponent &= 0x7fff;}static void unsignify(temp_real * a){if (!(a->a || a->b)) { /* zero */a->exponent = 0;return;}a->exponent &= 0x7fff;if (a->b < 0) { /* 最高位为1,为负数 */NEGINT(a);a->exponent |= 0x8000;}while (a->b >= 0) { /* 规范化,指数部分不能<0?*//* while ((a->exponent & 0x7fff) && a->b >=0) */a->exponent--;__asm__("addl %0,%0 ; adcl %1,%1":"=r" (a->a),"=r" (a->b):"0" (a->a),"1" (a->b));}}
四 加法
void fadd(const temp_real * src1, const temp_real * src2, temp_real * result){temp_real a,b;int x1,x2,shift;x1 = src1->exponent & 0x7fff;x2 = src2->exponent & 0x7fff;if (x1 > x2) {a = *src1;b = *src2;shift = x1-x2;} else {a = *src2;b = *src1;shift = x2-x1;}if (shift >= 64) {*result = a;return;}/*当 x1 =x2时,b的64个有效bit需要向右移动shift位数,若shift超过了64,那么b = 0,因此a + b = a + 0 = a。*/if (shift >= 32) {b.a = b.b;b.b = 0;shift -= 32;}/*若shift超过了32,那么b的后32bit尾数会被抹掉。经过两轮条件后,保证了shift<32。*/__asm__("shrdl %4,%1,%0 ; shrl %4,%1":"=r" (b.a),"=r" (b.b):"0" (b.a),"1" (b.b),"c" ((char) shift));/*shrd指令:双精度右移指令,只能在80386以上处理器使用,将目的操作数向右移动相应位数,空出来的位由源操作数的低位填充。EX: shrd $10,%eax,%ebx将ebx向右移动10位,ebx的高10位由eax的低10位补充。到这里后,a和b的指数已经是一样的了,下面就开始把它们符号化模拟正常数的加法。*/signify(&a); /* 加上符号 */signify(&b);__asm__("addl %4,%0 ; adcl %5,%1":"=r" (a.a),"=r" (a.b):"0" (a.a),"1" (a.b),"g" (b.a),"g" (b.b));unsignify(&a); /* 去掉符号 */*result = a;}
- Linux 0.12 OS. math - add.c
- Linux 0.12 OS. math - convert.c
- Linux 0.12 OS. math - ea.c
- Linux 0.12 OS. math - get_put.c
- Linux 0.12 OS. math - mul.c
- Linux 0.12 OS. math - div.c
- Linux 0.12 OS. math - compare.c
- Linux 0.12 OS. math - math_emulate.c
- Linux 0.12 OS. math - error.c
- Linux 0.12 OS. math - CR0
- Linux 0.12 OS. math - math_emu.h
- Linux 0.12 OS. block - ll_rw_blk.c
- [leetcode][math] Add Binary
- [leetcode][math] Add Digits
- Linux下C库学习 - math.h
- math.c
- 2,Add Two Number (LinkList Math)
- 【leetcode】【Easy】【258. Add Digits】【Math】
- 13周项目2:派生新类
- 推荐一个优秀的:产品需求分析和需求管理培训教材、相关参考模板、样例
- 【redis】Redis几个认识误区
- 面向对象--继承,多态,封装
- 基础知识 黑客域名劫持攻击详细步骤
- Linux 0.12 OS. math - add.c
- Android学习笔记之AndroidManifest.xml文件解析
- shell脚本监控监听器进程
- CSS中Backgroud-position(背景图片)定位问题详解
- Assert(断言实现机制剖析)
- mssql server 导入oracle的方法之一
- 以前攒的一些函数,都是用来抓网页做分析的,有可能有失效的,凑合看吧
- 框架搭建之二--引入SDWebImage
- 计算当天起始点和结束点时间戳 去当天的数据