CSAPP:datalab实验记录

bitXor

/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/

这道题的意思就是限定符号实现异或。我们很容易就知道:

\[a \oplus b = \overline a b + a \overline b
\]

再化简以下(逻辑代数的知识):

\[\overline a b + a \overline b = \overline { \overline {(a \overline b)} \overline {(\overline a b)}}
\]

对照着实现就是:

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

tmin

/*
* tmin - return minimum two's complement integer
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 4
* Rating: 1
*/

补码的最小值就是最高位位1咯,一个移位算法解决。

int tmin(void) {
return 1 << 31;
}

isTMax

/*
* isTmax - returns 1 if x is the maximum, two's complement number,
* and 0 otherwise
* Legal ops: ! ~ & ^ | +
* Max ops: 10
* Rating: 1
*/

这道题有点难度。

首先,TMax 取反一定是TMinTMin 的特点就是取反加一是相同的。

而有一个特殊值0TMin 的特点是一样的,需要排除。

所以,首先判断是否等于,再将0 排除即可。

int isTmax(int x) {
x = ~x;
return !((~x + 1) ^ x) & !!(x ^ 0);
}

allOddBits

/*
* allOddBits - return 1 if all odd-numbered bits in word set to 1
* where bits are numbered from 0 (least significant) to 31 (most significant)
* Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 12
* Rating: 2
*/

这道题,我们可以先构造一个常数0xAAAAAAAA ,与x 取与之后,再与这个常数判断是否相等即可。

int allOddBits(int x) {
int temp = (0xAA << 24) + (0xAA << 16) + (0xAA << 8) + 0xAA;
return !((temp & x) ^ temp);
}

negate

/*
* isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
* Example: isAsciiDigit(0x35) = 1.
* isAsciiDigit(0x3a) = 0.
* isAsciiDigit(0x05) = 0.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 3
*/

补码的取反加一。(提醒一下这个取反加1,不是因为首位是符号位,是因为首位是负权值位!!!)

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

isAsciiDigit

/*
* isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
* Example: isAsciiDigit(0x35) = 1.
* isAsciiDigit(0x3a) = 0.
* isAsciiDigit(0x05) = 0.
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 15
* Rating: 3
*/

判断范围,一个数分别与这两个常数相减,一正一负就是在范围内。

正常思路是这样,然而直接这么实现的话,会有一个0x80000030 数据溢出,它与0x39 相减的时候溢出了。

嗯,所以我们不判断首位是否不同了。与0x39 相减的地方我们改成-x 加上0x39 。然后判断符号是否相同。就能避免溢出问题。

int isAsciiDigit(int x) {
return !((x + ~0x30 + 1) >> 31) & !((~x + 0x39 + 1) >> 31);
}

conditional

/*
* conditional - same as x ? y : z
* Example: conditional(2,4,5) = 4
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 16
* Rating: 3
*/

直接对x取非,就能得到对应的结果。再利用逻辑左移和算术右移,可以构造出一个0x0 或者是0xffffffff

就很简单啦~

int conditional(int x, int y, int z) {
x = (!x << 31) >>31;
return (z & x) | (y & ~x);
}

isLessOrEqual

/*
* 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 x_sign = x >> 31;
int y_sign = y >> 31;
return (x_sign & !y_sign) | (!(x_sign ^ y_sign) & !((y + ~x + 1) >> 31));
}

logicalNeg

/*
* logicalNeg - implement the ! operator, using all of
* the legal operators except !
* Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
* Legal ops: ~ & ^ | + << >>
* Max ops: 12
* Rating: 4
*/

只有0是要返回1的。所以~

只要首位是1,就是负,返回1。

其余的所有正数加上TMax 都会溢出成负数。唯独0不会。

所以~加上TMax 再康康符号位即可~

int logicalNeg(int x) {
int Tmax = ~(0x1 << 31), sign = (x >> 31) & 0x1;
return (sign | (((x + Tmax) >> 31) & 1)) ^ 0x1;
}

howManyBits

/* howManyBits - return the minimum number of bits required to represent x in
* two's complement
* Examples: howManyBits(12) = 5
* howManyBits(298) = 10
* howManyBits(-5) = 4
* howManyBits(0) = 1
* howManyBits(-1) = 1
* howManyBits(0x80000000) = 32
* Legal ops: ! ~ & ^ | + << >>
* Max ops: 90
* Rating: 4
*/

这道题我不会,是参考别人的写法完成的。二分法非常巧妙啊~

最难理解的当然就是负数的情况。不过想想还是能想明白。

这里是利用二分法找到除了最高位以外的最高位。

整数很好说,关键是负数。由于补码的特性,前面是可以有很多没用的1的。所以负数是要找最高位的0哦~所以需要按照符号来取反。

int howManyBits(int x) {
int sign, b1, b2, b4, b8, b16;
sign = (x >> 31);
x = (sign & ~x) | (~sign & x);
b16 = !!(x >> 16) << 4;
x = x >> b16;
b8 = !!(x >> 8) << 3;
x = x >> b8;
b4 = !!(x >> 4) << 2;
x = x >> b4;
b2 = !!(x >> 2) << 1;
x = x >> b2;
b1 = !!(x >> 1);
x = x >> b1;
return b16 + b8 + b4 + b2 + b1 + x + 1;
}

floatScale2

/*
* floatScale2 - 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
*/

分情况判断哦~

  1. 如果是0,直接返回;
  2. 如果阶码是0,直接左移一位。
  3. 如果阶码是最大值,直接返回(NaN,不用处理~)。

接下来就是普通情况。阶码自加1。

再次判断,阶码达到最大值,直接返回不处理。

否则就将阶码拼接到原数据返回即可。

unsigned floatScale2(unsigned uf) {
int e = (uf & 0x7f800000) >> 23;
int sign = uf & (0x1 << 31);
int M = (uf << 9) >> 9;
if(M == 0 && e == 0) return uf;
if(e == 0x0) return (uf << 1) | sign;
if(e == 0xff) return uf;
e++;
if(e == 0xff && M > 0) return uf;
return sign | (e << 23) | M;
}

floatFloat2Int

/*
* floatFloat2Int - Return bit-level equivalent of expression (int) f
* for floating point argument f.
* Argument is passed as unsigned int, but
* it is to be interpreted as the bit-level representation of a
* single-precision floating point value.
* Anything out of range (including NaN and infinity) should return
* 0x80000000u.
* Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
* Max ops: 30
* Rating: 4
*/

根据浮点数的标准哈,将对应的数据分段拿下来~

嗯,如果是0直接返回0哈。

阶码处理一下,减一个偏移量。

如果阶码大于31,直接返回0x80000000

小于0,直接返回0.

而后面那一段数字,如果不处理的话,相当于就是自带有一个值为23的阶码。

所以,如果阶码大于23,就左移阶码多出的一段。小于23,就右移阶码少的一段。

int floatFloat2Int(unsigned uf) {
int sign = uf >> 31;
int exp = ((uf & 0x7f800000) >> 23) - 127;
int M = (uf & 0x007fffff) | 0x00800000;
if(!(uf & 0x7fffffff)) return 0;
if(exp > 31) return 0x80000000;
if(exp < 0) return 0;
if(exp >23) M <<= (exp - 23);
else M >>= (23 - exp);
if(!((M >> 31) ^ sign)) return M;
else if(M >> 31) return 0x80000000;
else return ~M + 1;
}

floatPower2

/*
* floatPower2 - Return bit-level equivalent of the expression 2.0^x
* (2.0 raised to the power x) for any 32-bit integer x.
*
* The unsigned value that is returned should have the identical bit
* representation as the single-precision floating-point number 2.0^x.
* If the result is too small to be represented as a denorm, return
* 0. If too large, return +INF.
*
* Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while
* Max ops: 30
* Rating: 4
*/

2的次方嘛~传入的参数就可以作为阶码了。

阶码加上偏移。然后,阶码小于0,返回0。阶码大于255,返回无限大,否则直接返回阶码左移23位的值。就刚好是对应的答案。因为当阶码不是0的时候自带一个1嗷~

unsigned floatPower2(int x) {
int inf;
inf = 0xff << 23;
x += 127;
if(x <= 0) return 0x0;
else if(x >= 255) return inf;
return x << 23;
}

总结

位运算符号相等运算

这是在第三题学到的:

int equals(int x, int y){
return !(x ^ y);
}

CSAPP:datalab实验记录的更多相关文章

  1. 实验记录:Oracle redo logfile的resize过程

    实验记录:Oracle redo logfile的resize过程. 实验环境:RHEL 6.4 + Oracle 11.2.0.3 单实例 文件系统 实验目的:本实验是修改redo logfile的 ...

  2. case7 淋巴瘤子类分类实验记录

    case7 淋巴瘤子类分类实验记录 简介 分类问题:3分类 (identifying three sub-types of lymphoma: Chronic Lymphocytic Leukemia ...

  3. 使用Scapy向Mininet交换机注入流量 实验记录

    使用Scapy向Mininet交换机注入流量 实验记录 用Python脚本及Scapy库写了一个简单的流量生成脚本,并打算使用该脚本往Mininet中的OpenvSwitch交换机注入流量.拓扑图如下 ...

  4. 树莓派4B智能小车机器套件——入手组装实验记录

    树莓派4B智能小车机器套件--入手组装实验记录 4WD智能小车(4WD SMART ROBOT KIT),支持Arduino.51.STM32.Raspberry Pi等4个版本.本套件采用的是树莓派 ...

  5. CSAPP buffer lab记录——IA32版本

    CSAPP buffer lab为深入理解计算机系统(原书第二版)的配套的缓冲区溢出实验,该实验要求利用缓冲区溢出的原理解决5个难度递增的问题,分别为smoke(level 0).fizz(level ...

  6. CSAPP Bomb Lab记录

    记录关于CSAPP 二进制炸弹实验过程 (CSAPP配套教学网站Bomb Lab自学版本,实验地址:http://csapp.cs.cmu.edu/2e/labs.html) (个人体验:对x86汇编 ...

  7. 《CSAPP》实验一:位操作

    <CSAPP>号称程序员圣经,虽然中文译名为<深入理解计算机系统>,但其实没那么"深",只是覆盖面很广,一般用作计算机专业大一导论课的教科书.早就听闻书上配 ...

  8. CS:APP3e 深入理解计算机系统_3e Datalab实验

    由于http://csapp.cs.cmu.edu/并未完全开放实验,很多附加实验做不了,一些环境也没办法搭建,更没有标准答案.做了这个实验的朋友可以和我对对答案:) 实验内容和要求可在http:// ...

  9. 实验记录三 通用输入输出(GPIO)

    之前把全部程序都跑了一次后,得到了导师下一步的安排. 例如以下: 1.编写一个程序.实如今LCD上显示一个万年历,包含年月日 星期 还有室内的温度.2.编写一个程序,将原来的交通灯改为跑马灯. 期限是 ...

随机推荐

  1. 【UG二次开发】 UF_OBJ_ask_name 获取对象名字

    代码 char name[256]; UF_OBJ_ask_name(objTag, name);

  2. 为什么有些公司的IT很乱?

    --别问,问就是赛马,问就是KPI驱动 为什么很多公司甚至是闻名遐迩的资深IT公司,都被吐槽IT技术建设很烂呢?按惯例,问为什么之前,先问是不是. ▒壹·鹅厂▒ 2018年一个名为"当下腾讯 ...

  3. 高吞吐、低延迟 Java 应用的 GC 优化实践

    本篇原文作者是 LinkedIn 的 Swapnil Ghike,这篇文章讲述了 LinkedIn 的 Feed 产品的 GC 优化过程,虽然文章写作于 April 8, 2014,但其中的很多内容和 ...

  4. Java中JVM、JRE和JDK三者有什么区别和联系?

    Java 语言的开发运行,也离不开 Java 语言的运行环境 JRE.没有 JRE 的支持,Java 语言便无法运行.当然,如果还想编译 Java 程序,搞搞小开发的话,JRE 是明显不够了,这时候就 ...

  5. OO unit2 summary

    Unit2 一.第一次作业 1.UML 2.Sequence Diagram 3.同步块设置与锁处理 采用了生产者-消费者模式,用共享对象来连接不同的线程. 第一次作业中,我有三个线程:Receive ...

  6. 可扩展的 Web 架构与分布式系统

    作者:Kate Matsudaira 译者:尹星 本文介绍了分布式架构是如何解决系统扩展性问题的粗略方法,适合刚刚入门分布式系统的同学,我把整篇文章翻译如下,希望给你一些启发. 备注:[idea]标注 ...

  7. npm 操作代码

    npm cache clean -force    //强制清除缓,比如安装echarts失败后,清除,在安装

  8. 使用 CKEditor编辑插件

    1, 安装方法 下载CKEditor插件,然后解压到对应的文件中.建议解压到JS文件夹下面的CKEditor这个文件夹下.下载地址 : http://down.chinaz.com/soft/2516 ...

  9. 精尽Spring Boot源码分析 - Condition 接口的扩展

    该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...

  10. Spring Boot整合MybatisPlus逆向工程(MySQL/PostgreSQL)

    MyBatis-Plus是MyBatis的增强工具,Generator通过MyBatis-Plus快速生成Entity.Mapper.Mapper XML.Service.Controller等模块的 ...