刚刚完成注册博客,想写一篇随笔,方便以后自己回顾。如果恰好也能帮助到你,是我的荣幸。

这次随笔是记载我的计算机系统(CS:APP,Computer Systems:A Programer's Perspective)课程的一次实验

为了实现这15个函数,参考了(抄袭了- -)网上很多大佬的解答,但是过程中也有了自己的一些体会。

下面分享一下自己的理解,每个函数的实现都附有相应解释,有个别自己还不是很理解就没有写解释,见谅啊。

注:实验环境 ubuntu 12.04

  每次修改bits.c时,都要make btest才能用btest测试函数的正确性

/*
* CS:APP Data Lab
*
*
* bits.c - Source file with your solutions to the Lab.
* This is the file you will hand in to your instructor.
*
* WARNING: Do not include the <stdio.h> header; it confuses the dlc
* compiler. You can still use printf for debugging without including
* <stdio.h>, although you might get a compiler warning. In general,
* it's not good practice to ignore compiler warnings, but in this
* case it's OK.
*/ #if 0
/*
* Instructions to Students:
*
* STEP 1: Read the following instructions carefully.
*/ You will provide your solution to the Data Lab by
editing the collection of functions in this source file. INTEGER CODING RULES: Replace the "return" statement in each function with one
or more lines of C code that implements the function. Your code
must conform to the following style: int Funct(arg1, arg2, ...) {
/* brief description of how your implementation works */
int var1 = Expr1;
...
int varM = ExprM; varJ = ExprJ;
...
varN = ExprN;
return ExprR;
} Each "Expr" is an expression using ONLY the following:
1. Integer constants 0 through 255 (0xFF), inclusive. You are
not allowed to use big constants such as 0xffffffff.
2. Function arguments and local variables (no global variables).
3. Unary integer operations ! ~
4. Binary integer operations & ^ | + << >> Some of the problems restrict the set of allowed operators even further.
Each "Expr" may consist of multiple operators. You are not restricted to
one operator per line. You are expressly forbidden to:
1. Use any control constructs such as if, do, while, for, switch, etc.
2. Define or use any macros.
3. Define any additional functions in this file.
4. Call any functions.
5. Use any other operations, such as &&, ||, -, or ?:
6. Use any form of casting.
7. Use any data type other than int. This implies that you
cannot use arrays, structs, or unions. You may assume that your machine:
1. Uses 2s complement, 32-bit representations of integers.
2. Performs right shifts arithmetically.
3. Has unpredictable behavior when shifting an integer by more
than the word size. EXAMPLES OF ACCEPTABLE CODING STYLE:
/*
* pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
*/
int pow2plus1(int x) {
/* exploit ability of shifts to compute powers of 2 */
return (1 << x) + 1;
} /*
* pow2plus4 - returns 2^x + 4, where 0 <= x <= 31
*/
int pow2plus4(int x) {
/* exploit ability of shifts to compute powers of 2 */
int result = (1 << x);
result += 4;
return result;
} FLOATING POINT CODING RULES For the problems that require you to implent floating-point operations,
the coding rules are less strict. You are allowed to use looping and
conditional control. You are allowed to use both ints and unsigneds.
You can use arbitrary integer and unsigned constants. You are expressly forbidden to:
1. Define or use any macros.
2. Define any additional functions in this file.
3. Call any functions.
4. Use any form of casting.
5. Use any data type other than int or unsigned. This means that you
cannot use arrays, structs, or unions.
6. Use any floating point data types, operations, or constants. NOTES:
1. Use the dlc (data lab checker) compiler (described in the handout) to
check the legality of your solutions.
2. Each function has a maximum number of operators (! ~ & ^ | + << >>)
that you are allowed to use for your implementation of the function.
The max operator count is checked by dlc. Note that '=' is not
counted; you may use as many of these as you want without penalty.
3. Use the btest test harness to check your functions for correctness.
4. Use the BDD checker to formally verify your functions
5. The maximum number of ops for each function is given in the
header comment for each function. If there are any inconsistencies
between the maximum ops in the writeup and in this file, consider
this file the authoritative source. /*
* STEP 2: Modify the following functions according the coding rules.
*
* IMPORTANT. TO AVOID GRADING SURPRISES:
* 1. Use the dlc compiler to check that your solutions conform
* to the coding rules.
* 2. Use the BDD checker to formally verify that your solutions produce
* the correct answers.
*/ #endif
/*
* 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));
}
//利用德摩根律 /*
* 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 /*
* 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)) /*
* 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 /*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/
int tmin(void) {
return (0x1 << 31);
}
//最小负整数的二进制补码是1000...0000 /*
* 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) /*
* 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,恰好弥补 /*
* negate - return -x
* Example: negate(1) = -1.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 5
* Rating: 2
*/
int negate(int x) {
return ((~x) + 1);
}
//对一个数的补码进行按位取反加1就能得到其相反数的补码 /*
* 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 /*
* 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,再取逻辑非配合与操作 /*
* 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;
} /*
* 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
//异或改变符号位 /*
* 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;
}
/*
* 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;
}

如果读者看完后有自己独到的实现方式,欢迎一起交流学习。

CS:APP配套实验 Data Lab的更多相关文章

  1. 深入理解计算机系统 (CS:APP) - 高速缓存实验 Cache Lab 解析

    原文地址:https://billc.io/2019/05/csapp-cachelab/ 这个实验是这学期的第四个实验.作为缓存这一章的配套实验,设计得非常精妙.难度上来讲,相比之前的修改现成文件, ...

  2. 深入理解计算机系统 (CS:APP) Lab2 - Bomb Lab 解析

    原文地址:https://billc.io/2019/04/csapp-bomblab/ 写在前面 CS:APP是这学期的一门硬核课程,应该是目前接触到最底层的课程了.学校的教学也是尝试着尽量和CMU ...

  3. 《深入理解计算机系统》实验一 —Data Lab

    本文是CSAPP第二章的配套实验,通过使用有限的运算符来实现正数,负数,浮点数的位级表示.通过完成这13个函数,可以使我们更好的理解计算机中数据的编码方式. 准备工作   首先去官网Lab Assig ...

  4. 图文并茂-超详解 CS:APP: Lab3-Attack(附带栈帧分析)

    CS:APP:Lab3-ATTACK 0. 环境要求 关于环境已经在lab1里配置过了.lab1的连接如下 实验的下载地址如下 说明文档如下 http://csapp.cs.cmu.edu/3e/at ...

  5. 【翻译】【中英对照】【企业库6】动手实验 Hands-On Lab 日志应用程序块索引页

    Logging Application Block Hands-On Lab for Enterprise Library 企业库的日志应用程序块动手实验 This walkthrough shoul ...

  6. [mjpeg @ ...] unable to decode APP fields: Invalid data found when processing input

    通过FFmpeg打开自己笔记本摄像头(HP Wide Vision HD Camera)操作时遇到如下错误: [mjpeg @ 0000029be7cbd000] unable to decode A ...

  7. ArcGIS10从入门到精通系列实验图文教程(附配套实验数据持续更新)

    @ 目录 1. 专栏简介 2. 专栏地址 3. 专栏目录 1. 专栏简介 本教程<ArcGIS从入门到精通系列实验教程>内容包括:ArcGIS平台简介.ArcGIS应用基础.空间数据的采集 ...

  8. 深入理解计算机系统 (CS:APP) 缓冲区漏洞实验 – Buffer Lab 解析

    原文地址:https://billc.io/2019/05/csapp-cachelab/ 写在前面 这是 CSAPP 官网上的第 4 个实验 buflab,也是学校要求的第三个实验.这个实验比上一个 ...

  9. 《CS:APP》二进制炸弹实验(phase_1-3)

    <深入理解计算机系统>第三章的bomb lab,拆弹实验:给出一个linux的可执行文件bomb,执行后文件要求分别进行6次输入,每一次输入错误都会导致炸弹爆炸,程序终止.需要通过反汇编来 ...

随机推荐

  1. Java开发环境搭建的准备工作

    Java开发环境搭建的准备工作 网络配置(修改hosts) 什么时候需要 比如我们在安装homeBrew的时候会遇到 curl: (7) Failed to connect to raw.github ...

  2. Android开发禁止首次进入activity弹出软键盘,限制屏幕只能竖屏或者横屏展示

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 只需在在Manifest.xml中设定activity的属性为: android:windowSoft ...

  3. Application.LoadLevel

    Unity在场景切换之间清理下内存 http://www.cnblogs.com/dongz888/p/4920714.html

  4. 令人蛋疼的错误提示 0xcdcdcdcd ,0xdddddddd ,0xfeeefeee ,0xcccccccc ,0xabababab

    原文地址:http://www.cnblogs.com/pcchinadreamfly/archive/2012/04/26/2471317.html参考地址:http://blog.csdn.net ...

  5. js+canvas画随机4位验证码

    啥都不说了,复制代码吧!!! <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  6. indexOf原理,Java,javascript,python实现

      简介 最近做项目的时候,发现无论是前端还是后端,indexOf出现的概率都非常频繁,今天我们来看下他的实现原理吧! indexOf的含义:给定一个字符串去匹配另一个字符串的下标,如果匹配到,返回下 ...

  7. 20191002思维导图工具MindManager 000 033

  8. 极简显示sessionid的jsp程序 war下载

    下载地址:https://files.cnblogs.com/files/xiandedanteng/simpleJspSessionId20200103.zip 解压后得到myweb.war就是可以 ...

  9. appium 基础二:常用api接口

    一.获取手机分辨率 size=driver.get_window_size()#获取手机屏幕大小,分辨率 print(size)#{'width': 720, 'height': 1280} 得到的是 ...

  10. 阿里云openssl升级,实现nginx主动推送,nginx主动推送能够有效减少不必要的报文传输,减少用户请求次数,以达到更快访问速度

    现有版本检查 [root@node3 ~]# openssl version               #这个版本是无法支持http2.0主动推送功能.需要升级为2019版本. OpenSSL 1. ...