一、实验目的

本实验目的是加强学生对位级运算的理解及熟练使用的能力。

二、报告要求

本报告要求学生把实验中实现的所有函数逐一进行分析说明,写出实现的依据,也就是推理过程,可以是一个简单的数学证明,也可以是代码分析,根据实现中你的想法不同而异。

三、函数分析

bitXor函数

函数要求:

函数名 bitXor
参数 int , int
功能实现 x^y
要求 只能使用 ~ 和

实现分析:

a^b = (a & ~b) | (~a & b), 为了将|转变为&, 对这个式子做两次取反即可。得到~(~ (a & ~b) & ~ (~a & b))

函数实现:

int bitXor(int x, int y) {return ~(~(x & ~y) & ~(~x & y));
}

getByte函数

函数要求:

函数名 getByte
参数 int, int
功能实现 从x中取出第n个字节
要求 使用: ! ~ & ^ | + << >>

**分析:**通过x >> (n << 3)移动字节(即n∗23n * 2^3n∗23位),至前8位,实现目标功能

函数实现:

int getByte(int x, int n) {int ret;int t = x >> (n << 3);ret = t & 0xFF;return ret;
}

logicalShift函数

函数要求:

函数名 logicalShift
参数 int , int
功能实现 逻辑右移
要求 ! ~ & ^ | + << >>

**分析:**通过变量va构建一个32位数,前n位都是0,后面的32-n位都是1,与原x进行&运算,得到结果。

函数实现:

int logicalShift(int x, int n) {int va = (0x1 << 31) >> n;x = x >> n;va = ~(va << 1);return (va & x);
}

bitCount函数

函数要求:

函数名 bitCount
参数 int
功能实现 计算int型数据x的二进制串中1的个数
要求 ! ~ & ^ | + << >>

分析:

通过二分法,通过x与010101…0101, 00110011…0011,00001111…00001111…000…00111…111做&运算,依次计算2n(n=1,2,3,4,5)2^n(n = 1,2,3,4,5)2n(n=1,2,3,4,5)位中1的个数,每次计算时都利用到前一次的结果,进行加和得到最终32位数中1的个数。

首先将int型数据x的32位分成16组,并进行X31+X30,X29+X28,…,X3+X2,X1+X0的运算;然后将x分成8组,并进行X31+X30+X29+X28,…,X3+X2+X1+X0的运算。依次类推, 最后只剩下1组,此时将所有的位进行相加即得到了最终结果。

函数实现:

int bitCount(int x) {int mask_1 = 0x55 | (0x55 << 8);int mask_2=0x33|(0x33<<8);int mask_4=0x0f|(0x0f<<8);int mask_8=0xff|(0xff<<16);int mask_16=0xff|(0xff<<8);mask_1 = mask_1 | (mask_1 << 16);mask_2=mask_2|(mask_2<<16);mask_4=mask_4|(mask_4<<16);x = (x & mask_1) + ((x >> 1) & mask_1);x = (x & mask_2) + ((x >> 2) & mask_2);x = (x & mask_4) + ((x >> 4) & mask_4);x = (x & mask_8) + ((x >> 8) & mask_8);x = (x & mask_16) + ((x >> 16) & mask_16);return x;
}

conditional函数

函数要求:

函数名 conditional
参数 int int int
功能实现 类似于C语言中的 x ? y : z
要求 ! ~ & ^ | + << >>

**分析:**首先通过x = !!x把x转换成1或0,再将x转换成-1和0(因为-1的补码表示全为1),通过x得到最后取得y还是取得z。

函数实现:

int conditional(int x, int y, int z) {x = !!x;x = ~x + 1;return ((x & y) | (~x & z));
}

tmin函数

函数要求:

函数名 tmin
参数 Null
功能实现 返回最小的补码
要求 ! ~ & ^ | + << >>

**分析:**0x1左移31位得到结果

函数实现:

int tmin(void) {return (0x1 << 31);
}

fitsBits函数

函数要求:

函数名 fitsBits
参数 int int
功能实现 x的补码是否可以表示成n位
要求 ! ~ & ^ | + << >>

**分析:**将x左移(32-n)位,再右移(32-n)位,再检查此时的数字是否与x相同,如果相同即符合条件,否则不符合。

函数实现:

int fitsBits(int x, int n) {int shift = ~n + 33;// 32 - n = ~n + 1 + 32int tmp = (x << shift) >> shift;tmp = tmp + ~x + 1;tmp = !!tmp;return !tmp;
}

dividePower2函数

函数要求:

函数名 dividePower2
参数 int int
功能实现 计算x/(2^n)
要求 ! ~ & ^ |+ << >>

分析:

根据定义,如果是正数,直接右移n位。如果是负数,则要加上一个偏置量2k−12^k-12k−1。

函数实现:

int dividePower2(int x, int n) {int sign = 0,var = 0;sign = x >> 31;var = (1 << n) + (~0);return (x + (sign & var)) >> n;
}

negate函数

函数要求:

函数名 negate
参数 int
功能实现 不用负号得到
要求 ! ~ & ^ |+ << >>

**分析:**根据定义,补码倒数取反加一。

函数实现:

int negate(int x) {return (~x + 1);
}

howManyBits函数

函数要求:

函数名 howManyBits
参数 int
功能实现 计算表达 x 所需的最少位数
要求 ! ~ & ^ |+ << >>

**分析:**问题的关键是计算这个数第一个“1”出现在第几位,再加上1个符号即可得到。

找到第一个1的方法是二分查找,先将32位一分为2,计算第一个1是在前16位,还是在后16位。然后将这16位移到前16位,再查找是前8位还是后8位…最终将每次搜索的结果进行相加,加上一个符号位得到结果。

int howManyBits(int x) {int sign = x >> 31;// 0  -1int ct_16 = 0;int ct_8 = 0;int ct_4 = 0;int ct_2 = 0;int ct_1 = 0;int ct_0 = 0;int fla = 0;x = (sign & ~x) | (~sign & x);sign = ~sign + 1;fla = !!(x >> 16);ct_16 = fla << 4;x = x >> ct_16;fla = !!(x >> 8);ct_8 = fla << 3;x = x >> ct_8;fla = !!(x >> 4);ct_4 = fla << 2;x = x >> ct_4;fla = !!(x >> 2);ct_2 = fla << 1;x = x >> ct_2;fla = !!(x >> 1);ct_1 = fla;x = x >> ct_1;ct_0 = x;return ct_0 + ct_1 + ct_2 + ct_4 + ct_8 + ct_16 + 1;
}

isLessOrEqual函数

函数要求:

函数名 isLessOrEqual
参数 int int
功能实现 x <= y?
要求 ! ~ & ^ |+ << >>

**分析:**通过判断y - x大于零还是小于零,得到结果。将y - x 转换为y + ~x + 1, 再判断溢出的特殊情况:y > 0 , x < 0 和 x > 0 , y < 0的情况。

int isLessOrEqual(int x, int y) {int a = y + ~x + 1;int sign = a >> 31;int s_x = x >> 31;int s_y = y >> 31;int of_1 = s_x & (!s_y);// y > 0, x < 0int of_2 = (!s_x) & (s_y);// x > 0, y < 0return of_1 | ((!of_2) & (!sign));
}

intLog2函数

函数要求:

函数名 intLog2
参数 int
功能实现 计算⌊log2(x)⌋(向下取整)
要求 ! ~ & ^ |+ << >>

**分析:**与howmanybits那题相似,关键是要找到最大的1位所在的位置,取log即为二分法叠加的结果减1。

函数实现:

int intLog2(int x) {int ax = 1;int cnt_16 = 0, cnt_8 = 0, cnt_4 = 0, cnt_2 = 0, cnt_1 = 0, cnt_0 = 0;int flag = 0;flag = !!(x >> 16);cnt_16 = flag << 4;x = x >> cnt_16;flag = !!(x >> 8);cnt_8 = flag << 3;x = x >> cnt_8;flag = !!(x >> 4);cnt_4 = flag << 2;x = x >> cnt_4;flag = !!(x >> 2);cnt_2 = flag << 1;x = x >> cnt_2;flag = !!(x >> 1);cnt_1 = flag;x = x >> cnt_1;cnt_0 = x;return cnt_0 + cnt_1 + cnt_2 + cnt_4 + cnt_8 + cnt_16 + (~ax) + 1;
}

floatAbsVal函数

函数要求:

函数名 floatAbsVal
参数 unsigned
功能实现 计算f的绝对值的位级表示
要求 || &&. also if, while

**分析:**分类讨论,除了NaN的情况,其他情况直接将s位改成0,NaN的情况(满足exp == 255且frac != 0)直接返回NaN本身。

函数实现:

unsigned floatAbsVal(unsigned uf) {if(((uf & 0x7F800000) >> 23) == 255 && (uf & 0x007FFFFF))return uf;elsereturn uf & 0x7FFFFFFF;
}

floatScale1d2函数

函数要求:

函数名 floatScale1d2
参数 unsigned
功能实现 计算0.5*f的位级表示
要求 &&. also if, while

**分析:**先将s,exp,frac位分离出来,分类:当exp = 255返回无穷,当exp > 1的其他情况,属于规格化的数,根据IEEE浮点表示(−1)s∗M∗2E(-1)^s*M*2^E(−1)s∗M∗2E,只需要将exp-1即可得到结果。当exp小于等于1的时候,考虑到frac前两位的舍入,然后将原数右移一位即可。

函数实现:

unsigned floatScale1d2(unsigned uf) {int exp = (uf&0x7F800000) >> 23;int s = uf&0x80000000;int frac = uf & 0x7FFFFF;// NaN || infinity(INF)if(exp == 255){return uf;}else if(exp > 1){exp = exp - 1;return s | (exp << 23) | frac;}else if((uf & 0x3) == 0x3){uf = uf + 0x2;}return ((uf >> 1) & 0x007fffff) | s;
}

floatFloat2Int函数

函数要求:

函数名 floatFloat2Int
参数 unsigned
功能实现 计算(int)f的位级表示
要求 &&. also if, while

**分析:**首先提出s,exp,frac位,然后将exp-bias得到E, 分类讨论:当E小于0时,表示0附近的小数,此时直接返回0即可,当E > 31时,已经超过了int可表示的最大值,此时根据题意返回0x80000000u。由于frac最多23位,当E在0到23时,frac右移(23-E)即可得到结果,当E在23到31,frac左移(E-23)即可得到结果。

函数要求:

int floatFloat2Int(unsigned uf) {int s = uf & 0x80000000;int exp = (uf & 0x7f800000) >> 23;int frac = (uf & 0x007fffff) | 0x00800000;// M = f + 1int result = 0;int E = exp - 127;if(E < 0)return 0;else if(E > 31)return 0x80000000u;else if(E > 23){result = frac << (E - 23);}else{result = frac >> (23 - E);}if (s)return (~result) + 1;elsereturn result;
}

四、实验总结

温故了CSAPP第二章的内容,并进行了实践。其中在CourseGrading系统中遇到了一个比较有意思的问题,就是如果在函数的中间声明变量的时候, 在./dlc bits.c的时候会报parse error的错误,修改的方式是:在编写其他语句以前,先将所有的变量进行声明。

在做实验的过程中还要考虑到各种符号的限制。

深入理解计算机系统:datalab报告相关推荐

  1. bilibili深入理解计算机系统笔记(2):第一次代码重构,汇编模拟器,递归,指令周期实现。

    文章目录 深入理解计算机系统笔记(2) 第一次代码重构 可变参数输出print函数 bitmap学习 P10 有限自动机 指令周期 递归求和函数c语言和汇编语言 回调函数的实现 call和ret指令的 ...

  2. 深入理解计算机系统9个重点笔记

    引言 深入理解计算机系统,对我来说是部大块头.说实话,我没有从头到尾完完整整的全部看完,而是选择性的看了一些我自认为重要的或感兴趣的章节,也从中获益良多,看清楚了计算机系统的一些本质东西或原理性的内容 ...

  3. 2021春深入理解计算机系统大作业---hello的一生

    计算机系统 大作业 题     目 程序人生-Hello's P2P 专       业 计算学部 学    号 120L021725 班    级 2003006 学       生 杨楠 指 导 ...

  4. 深入理解计算机系统(CSAPP)含lab详解 完结

    文章目录 深入理解计算机操作系统-第一章 1.1 信息就是位 + 上下文 1.2 程序被其他程序翻译成不同的格式 1.3 了解编译系统如何工作是大有益处的 1.4 处理器读并解释储存在内存中的指令 1 ...

  5. 《深入理解计算机系统》实验四Architecture Lab下载和官方文档机翻

    前言 <深入理解计算机系统>官网:http://csapp.cs.cmu.edu/3e/labs.html 该篇文章是是实验四Architecture Lab中的Writeup(archl ...

  6. 《深入理解计算机系统》CSAPP第3版术语索引表

    <深入理解计算机系统>几乎做到了只讲对程序员"有用的"原理,所以这本书性价比非常高.并没有在体系结构和操作系统的许多实现问题上纠缠. 第三版的英文原版是有index表的 ...

  7. 深入理解计算机系统--fork函数

    fork函数 一.函数的解析 (1) fork:创建进程 (2) fork函数调用一次,返回两次.返回的两次一次是在父进程中,fork返回子进程的PID:一次是在子进程中,fork返回0.其中,子进程 ...

  8. 《深入理解计算机系统》第一章-计算机系统漫游

    本系列文章是本人读<深入理解计算机系统>时的摘抄和读书笔记,内容比较精简,可能会有错误,如想展开深入理解请阅读源书 序言 <深入理解计算机系统>适用于想深入理解计算机底层系统以 ...

  9. 《深入理解计算机系统》读书随笔-位操作

    最近开始读<深入理解计算机系统>这本书.对于书中提到的从程序员的角度解读计算机系统这一说法非常感兴趣,所以决定好好读一读.从开始接触计算机编程就是站在一个高级语言的层次,虽然对编译原理,操 ...

  10. 【组队学习】【32期】深入理解计算机系统

    深入理解计算机系统 航路开辟者:李岳昆.易远哲 领航员:初晓宇 航海士:叶前坤.沈豪 基本信息 开源内容:https://github.com/datawhalechina/team-learning ...

最新文章

  1. XML文件操作(C#)
  2. idea 线程内存_Java线程池系列之-Java线程池底层源码分析系列(一)
  3. HTML+CSS(第二天)
  4. NGUI_2.6.3_系列教程一
  5. Linux如何查看所有的用户和组信息
  6. 字符串统计,一个中文算2个字符,一个英文算一个字符
  7. oracle bip报表乱码,Oracle EBS的BIP报表中显示特殊字体
  8. Java 集合 源码分析+重点解析 超详细学习资料
  9. EnableViewState和EnableTheming的作用
  10. 英语计算机考研复试专业翻译题库,计算机专业英语题题库.doc
  11. web前端-写给大家看的设计书-笔记-颜色运用-色轮使用
  12. diamond java_Diamond语法何时在Java 8中不起作用?
  13. 手把手接入高德地图API——POI周边搜索功能实现
  14. WiFi,你真的还安全吗?
  15. django之七(模型层ORM相关)
  16. NetApp FAS混合式Flash Array
  17. Java动态代理原理分析
  18. 前端使用jquery.wordexport.js导出word
  19. android 无法添加帐户,安卓手机outlook无法登录、添加帐户
  20. android pptx mime类型,对于docx,pptx等,什么是正确的MIME类型?

热门文章

  1. SQL Based on practice
  2. Huggingface datasets库读取yelp_review_full数据集时下载失败的解决方法
  3. ucloud挂载磁盘
  4. 招商网上银行接口(自己的网上银行)
  5. vue项目执行cnpm run dev报错cnpm : 无法加载文件 C:\Users\MEH\AppData\Roaming\npm\cnpm.ps1,因为在此系统上禁止运行脚本
  6. 奇迹mu服务端的常用端口及功能
  7. BZOJ1109: [POI2007]堆积木Klo
  8. windows下配置canal
  9. 绝地求生服务器维护7月7日,绝地求生最新维护公告时间 7月7日维护时间内容一览...
  10. 将CSV的数据发送到kafka(java版)