CSAPP 配套实验 DataLab
第一次写博客,当作随笔留给自己看吧,如果能帮到读者,是我的荣幸。
这是 CSAPP 的配套实验 DataLab,概括的来说就是在较严格的限制条件下把 15 个函数补充完整。
本人能力没有那么强,很多题目都是借鉴了(抄袭了= =)网上大佬的做法,当然也有些题目看不懂大佬的做法,但是结合了大佬的思想,自己写了出来。
很多函数的下面都附加了自己的理解。
在 ubuntu 12.04 下测试全部通过
每次修改 bits.c 后的测试顺序
./dlc bits.c (检查编码是否符合规则)
make btest (相当于编译检查语法)
btest bits.c (测试bits.c所有函数的正确性)
注:./dlc bits.c,检查编码是否符合规则 这一步非常有必要,因为即使你后面测试函数得到了满分,但是不符合编码规则将视作零分
btest 测试单个函数的方法是 btest -f FuncName,其他更多用法请自行参考说明文件
1
/*
* bitAnd - x&y using only ~ and |
* Example: bitAnd(6, 5) = 4
* Legal ops: ~ |
* Max ops: 8
* Rating: 1
*/
int bitAnd(int x, int y) {
return ~((~x) | (~y));
}
//利用德摩根律
2
/*
* getByte - Extract byte n from word x
* Bytes numbered from 0 (LSB) to 3 (MSB)
* Examples: getByte(0x12345678,1) = 0x56
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 6
* Rating: 2
*/
int getByte(int x, int n) {
return ((x >> (n << 3)) & 0xFF);
}
//将所要取的字节移到最右端然后其余位通过与运算置0
3
/*
* logicalShift - shift x to the right by n, using a logical shift
* Can assume that 0 <= n <= 31
* Examples: logicalShift(0x87654321,4) = 0x08765432
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 20
* Rating: 3
*/
int logicalShift(int x, int n) {
int tmp = 32 + (~n);
return (x >> n) & ((1 << tmp) + (~0) + (1 << tmp));
}
//运用机器的算术右移,然后高位置0和低位保持
//右移n位后原最高位到了第31-n位,31-n表示为31+((~n)+1) = 32+(~n)
//通过与高n位全为0,第32-n位全为1的数实现高位置0和低位保持
//这个数是(1 << ((32+(~n)+1)) - 1
//由于n可能为0,这样左移32位会根据gcc编译规则左移 32 % 32(类型位长) = 0位
//故将该数表示为(1 << (32+(~n)+1)) + (~0) + (1 << (32+(~n)+1))
4
/*
* bitCount - returns count of number of 1's in word
* Examples: bitCount(5) = 2, bitCount(7) = 3
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 40
* Rating: 4
*/
int bitCount(int x) {
//造数
int _tmp1 = 0x55 | (0x55 << 8); //0x00005555
int _tmp2 = 0x33 | (0x33 << 8); //0x00003333
int _tmp3 = 0xf | (0xf <<8); //0x00000f0f
int tmp1 = _tmp1 | (_tmp1 << 16); //0x55555555
int tmp2 = _tmp2 | (_tmp2 << 16); //0x33333333
int tmp3 = _tmp3 | (_tmp3 << 16); //0x0f0f0f0f
int tmp4 = 0xff | (0xff << 16); //0x00ff00ff
int tmp5 = 0xff | (0xff << 8); //0x0000ffff
//求和
int res = 0;
res = (x & tmp1) + ((x >> 1) & tmp1);
res = (res & tmp2) + ((res >> 2) & tmp2);
res = (res & tmp3) + ((res >> 4) & tmp3);
res = (res & tmp4) + ((res >> 8) & tmp4);
res = (res & tmp5) + ((res >> 16) & tmp5);
//返回
return res;
}
//类似递归分治的思想,以统计二进制数x=10中1的个数为例
//方法是将高位移到低位和0x1相与,(x & 0x1) + ((x >> 1) & 0x1)
//造出5个数,0x55555555,0x33333333,0x0f0f0f0f,0x00ff00ff,0x0000ffff
//这五个数写成二进制,分别隔着1,2,4,8,16个0
/*
* bang - Compute !x without using !
* Examples: bang(3) = 0, bang(0) = 1
* Legal ops: ~ & ^ | + << >>
* Max ops: 12
* Rating: 4
*/
int bang(int x) {
return ((~((x | ((~x)+1)) >> 31)) & 0x1);
}
//将一个非零数的补码与其相反数的补码相或,最高位一定是1
//但如果对0进行此操作,最高位还是0
6
/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return (0x1 << 31);
}
//最小负整数的二进制补码是1000...0000
7
/*
* fitsBits - return 1 if x can be represented as an
* n-bit, two's complement integer.
* 1 <= n <= 32
* Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int fitsBits(int x, int n) {
return !(((x >> (n+(~0))) + 1) >> 1);
}
//若n位能表示这个数
//正数的1只能出现在低n-1位,其余位全为0
//负数的0只能出现在低n-1位,其余位全为1
//故将该数右移n-1位后所得结果,正数全为0,负数全为1
//此时再+1后右移1位,可以得到全0
//若n位不能表示这个数,则一定不会有以上结论
//n-1表示为n+(-1),即n+(~0)
8
/*
* divpwr2 - Compute x/(2^n), for 0 <= n <= 30
* Round toward zero
* Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 2
*/
int divpwr2(int x, int n) {
return ( x + (((x >> 31) & 0x1) << n) + (~0) + (!((x >> 31) & 0x1)) ) >> n;
}
//本题是对于标准除法/的实现,全正取下整,有负取上整
//而通过移位实现除以2的幂,都是取下整
//故对于负数要加一个偏移量(1 << n) - 1 (证明在深入理解计算机系统第9版P73)
//因为是负数才要加偏移量,所以式子中的1刚好可以用符号位((x >> 31) & 0x1)表示
//若x > 0,(((x >> 31) & 0x1) << n)的结果为0,会导致多减去了1即(~0)
//巧妙多加一个符号位的逻辑非结果即(!((x >> 31) & 0x1)),负数为0,整数为1,恰好弥补
9
/*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ((~x) + 1);
}
//对一个数的补码进行按位取反加1就能得到其相反数的补码
10
/*
* isPositive - return 1 if x > 0, return 0 otherwise
* Example: isPositive(-1) = 0.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 8
* Rating: 3
*/
int isPositive(int x) {
return !( ((x >> 31) & 0x1) | (!(x << 1)) );
}
//正数和零的符号位为0,负数为1
//左移1位后用!,正数的结果一定为0,负数的结果可0可1,零的结果一定是1
//将以上两个结果相或,正数的结果为0,负数一定为1,零的结果一定是1
11
/*
* isLessOrEqual - if x <= y then return 1, else return 0
* Example: isLessOrEqual(4,5) = 1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 24
* Rating: 3
*/
int isLessOrEqual(int x, int y) {
int xSign = (x >> 31) & 0x1;
int ySign = (y >> 31) & 0x1;
int signDiff = xSign & (!ySign);
int signSame = !(((y + (~x+1)) >> 31) & 0x1) & !(xSign ^ ySign);
return signDiff | signSame;
}
//作差法判断大小
//首先要判断符号位,因为可能存在溢出
//正数符号位为0,负数符号位为1,列出x,y的真值表
//x y z
//0 0 符号相同要进行下一步作差
//0 1 0(表示x > y)
//1 0 1(表示x < y)
//1 1 符号相同要进行下一步作差
//可以看到若用一个表达式(xSign & !(ySign))可以实现只用第三种情况为1,就可以完成符号位的判断
//接下来还要看其他三种情况,通过与上!(xSign ^ ySign)保证两者同号,因为第二种不同号的情况在该表达式下结果为0,与0就置0
//前面取y-x的符号位,为0说明,y >= x,否则y < x,再取逻辑非配合与操作
12
/*
* ilog2 - return floor(log base 2 of x), where x > 0
* Example: ilog2(16) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 90
* Rating: 4
*/
int ilog2(int x) {
int res = 0;
res = res + ((!!(x>>(16 + res)))<<4);
res = res + ((!!(x>>(8 + res)))<<3);
res = res + ((!!(x>>(4 + res)))<<2);
res = res + ((!!(x>>(2 + res)))<<1);
res = res + ((!!(x>>(1 + res)))<<0);
return res;
}
13
/*
* float_neg - Return bit-level equivalent of expression -f for
* floating point argument f.
* Both the argument and result are passed as unsigned int's, but
* they are to be interpreted as the bit-level representations of
* single-precision floating point values.
* When argument is NaN, return argument.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 10
* Rating: 2
*/
unsigned float_neg(unsigned uf) {
unsigned exp = (uf >> 23) & 0xFF;
unsigned frac = uf & 0x7FFFFF;
unsigned res = uf ^ 0x80000000;
if(exp == 0xFF && frac) {
res = uf;
}
return res;
}
//取exp和frac判断是否为NaN
//异或改变符号位
14
/*
* float_i2f - Return bit-level equivalent of expression (float) x
* Result is returned as unsigned int, but
* it is to be interpreted as the bit-level representation of a
* single-precision floating point values.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned float_i2f(int x) {
unsigned ans;
int xSignx = x & (1 << 31);
int res = 31;
int ss = 0;
int ff = 0;
int tmp;
if(x == 0) ans = 0;
else{
if(xSignx) x = (~x) + 1;
while(!((1 << res) & x)) {
res--;
}
x = x ^ (1 << res);
if(res < 23) x = x << (23 - res);
else {
tmp = res - 24;
if(tmp >= 0) ss = (x >> tmp) & 1,ff = ((1 << tmp) - 1) & x;
x = (x >> (res-23));
}
x = x | ((res+127) << 23);
if(ff == 0) {
ss = (ss & x);
}
x = x + ss;
x = x | xSignx;
ans = x;
}
return ans;
}
15
/*
* float_twice - Return bit-level equivalent of expression 2*f for
* floating point argument f.
* Both the argument and result are passed as unsigned int's, but
* they are to be interpreted as the bit-level representation of
* single-precision floating point values.
* When argument is NaN, return argument
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/
unsigned float_twice(unsigned uf) {
unsigned tmp = uf;
unsigned exp = (tmp >> 23) & 0xFF;
unsigned frac = tmp & 0x007fffff;
if(exp == 0x0) { //非规格化数
tmp = (tmp & 0x80000000) | (frac << 1);
}
else if(exp != 0xFF) { //规格化数
tmp += (1 << 23);
if(((tmp >> 23) & 0xFF) == 0xFF) {
tmp = tmp >> 23 << 23;
}
}
return tmp;
}
CSAPP 配套实验 DataLab的更多相关文章
- 《CSAPP》实验二:二进制炸弹
二进制炸弹是第三章<程序的机器级表示>的配套实验,这章主要介绍了x64汇编,包括:操作数的表示方式,数据传送指令,算术和逻辑指令,控制流跳转指令,过程(procedure)的实现与运行时栈 ...
- 《CSAPP》实验一:位操作
<CSAPP>号称程序员圣经,虽然中文译名为<深入理解计算机系统>,但其实没那么"深",只是覆盖面很广,一般用作计算机专业大一导论课的教科书.早就听闻书上配 ...
- ArcGIS10从入门到精通系列实验图文教程(附配套实验数据持续更新)
@ 目录 1. 专栏简介 2. 专栏地址 3. 专栏目录 1. 专栏简介 本教程<ArcGIS从入门到精通系列实验教程>内容包括:ArcGIS平台简介.ArcGIS应用基础.空间数据的采集 ...
- CSAPP实验——DataLab
任务:按照要求补充13个函数,会限制你能使用的操作及数量 bitXor(x,y) 只使用 ~ 和 & 实现 ^ tmin() 返回最小补码 isTmax(x) 判断是否是补码最大值 allOd ...
- 用Python做2048游戏 网易云课堂配套实验课。通过GUI来体验编程的乐趣。
第1节 认识wxpython 第2节 画几个形状 第3节 再做个计算器 第4节 最后实现个2048游戏 实验1-认识wxpython 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiy ...
- [CSAPP]Bufbomb实验报告
Bufbomb实验报告 实验分析: level 0-3从test開始制运行,通过函数getbuf向外界读取一串内容(buf). Level 4 是通过參数-n,程序运行testn函数,调用getbuf ...
- CS:APP配套实验 Data Lab
刚刚完成注册博客,想写一篇随笔,方便以后自己回顾.如果恰好也能帮助到你,是我的荣幸. 这次随笔是记载我的计算机系统(CS:APP,Computer Systems:A Programer's Pers ...
- 超精讲-逐例分析 CSAPP:实验2-Bomb!(下)
好了话不多说我们书接上文继续来做第二个实验下面是前半部分实验的连接 5. 第五关 首先感觉应该是个递归问题 /* Round and 'round in memory we go, where we ...
- CSAPP 六个重要的实验 lab5
CSAPP && lab5 实验指导书: http://download.csdn.net/detail/u011368821/7951657 实验材料: http://downlo ...
- CSAPP Bomb Lab记录
记录关于CSAPP 二进制炸弹实验过程 (CSAPP配套教学网站Bomb Lab自学版本,实验地址:http://csapp.cs.cmu.edu/2e/labs.html) (个人体验:对x86汇编 ...
随机推荐
- Git创建、diff代码、回退版本、撤回代码,学废了吗
.eye-care { background-color: rgba(199, 237, 204, 1); padding: 10px } .head-box { display: flex } .t ...
- C/C++ 知海拾遗
C语言知识拾遗 2022/11/11 memset()函数用法 包含头文件:<string.h> 作用:给任意类型变量数组初始化,即万能初始化函数. 使用形式:memset( void* ...
- go工具pprof部署
在做内存分析时,用到了pprof,这里做一下部署介绍和入门级别的使用. pprof是golang的性能工具,有两种交互方式:命令行交互和web交互,同时还支持性能分析数据的图形化展示. 部署pprof ...
- 带你从入门到精通学习WireShark
个人名片: 因为云计算成为了监控工程师 个人博客:念舒_C.ying CSDN主页️:念舒_C.ying 带你从入门到精通学习WireShark 一.什么是WireShark? 二.WireShar ...
- Shell脚本--信号发送与捕捉
信号(Signal):信号是在软件层次上对中断机制的一种模拟,通过给一个进程发送信号,执行相 应的处理函数. 进程可以通过三种方式来响应一个信号: 忽略信号,即对信号不做任何处理,其中有两个信号不能忽 ...
- 写一个linux平台的桌面宠物
效果图 前言 我一直在用python 写一下有趣的东西,让编程不那么无聊,之前一直有写一个桌面宠物的想法,无奈这些都是依赖资源文件,没有图片资源没办法写里面的逻辑,直到我看见了 shimiji手机桌面 ...
- 我要涨知识——TypeScript 常见面试题(二)
又是一个年底来了,好大一批人可能又准备跑路了,最近回家待产,翻了翻掘金和 CSDN 发现好多大佬都有大厂 Offer ,看着看着我心动了! 话不多说,赶紧开干,给自己整了一个前端面试小助手--微信小程 ...
- 【Java EE】Day03 DQL、约束、数据库设计、范式、备份和还原
〇.总结 1.DQL 聚合函数有空值需要使用ifnull函数 where不能使用聚合函数 分页开始索引的计算,及mysql和oracle的方言 2.约束 删除唯一约束DROP INDEX 列名; 3. ...
- 预编译SQL为什么能够防止SQL注入
前言 之前我一个搞网络安全的朋友问了我一个的问题,为啥用 PreparedStatement 预编译的 SQL 就不会有被 SQL 注入的风险? 第一时间我联想到的是八股文中关于 Mybatis 的脚 ...
- jupyter 数据显示设置
#设置显示行数pd.set_option('display.max_row',None)#设置显示列数pd.set_option('display.max_column',None)#设置显示宽度pd ...