CSAPP:datalab实验记录
CSAPP:datalab实验记录
bitXor
/*
* bitXor - x^y using only ~ and &
* Example: bitXor(4, 5) = 1
* Legal ops: ~ &
* Max ops: 14
* Rating: 1
*/
这道题的意思就是限定符号实现异或。我们很容易就知道:
\]
再化简以下(逻辑代数的知识):
\]
对照着实现就是:
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 取反一定是TMin 。TMin 的特点就是取反加一是相同的。
而有一个特殊值0 跟TMin 的特点是一样的,需要排除。
所以,首先判断是否等于,再将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
*/
分情况判断哦~
- 如果是0,直接返回;
- 如果阶码是0,直接左移一位。
- 如果阶码是最大值,直接返回(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实验记录的更多相关文章
- 实验记录:Oracle redo logfile的resize过程
实验记录:Oracle redo logfile的resize过程. 实验环境:RHEL 6.4 + Oracle 11.2.0.3 单实例 文件系统 实验目的:本实验是修改redo logfile的 ...
- case7 淋巴瘤子类分类实验记录
case7 淋巴瘤子类分类实验记录 简介 分类问题:3分类 (identifying three sub-types of lymphoma: Chronic Lymphocytic Leukemia ...
- 使用Scapy向Mininet交换机注入流量 实验记录
使用Scapy向Mininet交换机注入流量 实验记录 用Python脚本及Scapy库写了一个简单的流量生成脚本,并打算使用该脚本往Mininet中的OpenvSwitch交换机注入流量.拓扑图如下 ...
- 树莓派4B智能小车机器套件——入手组装实验记录
树莓派4B智能小车机器套件--入手组装实验记录 4WD智能小车(4WD SMART ROBOT KIT),支持Arduino.51.STM32.Raspberry Pi等4个版本.本套件采用的是树莓派 ...
- CSAPP buffer lab记录——IA32版本
CSAPP buffer lab为深入理解计算机系统(原书第二版)的配套的缓冲区溢出实验,该实验要求利用缓冲区溢出的原理解决5个难度递增的问题,分别为smoke(level 0).fizz(level ...
- CSAPP Bomb Lab记录
记录关于CSAPP 二进制炸弹实验过程 (CSAPP配套教学网站Bomb Lab自学版本,实验地址:http://csapp.cs.cmu.edu/2e/labs.html) (个人体验:对x86汇编 ...
- 《CSAPP》实验一:位操作
<CSAPP>号称程序员圣经,虽然中文译名为<深入理解计算机系统>,但其实没那么"深",只是覆盖面很广,一般用作计算机专业大一导论课的教科书.早就听闻书上配 ...
- CS:APP3e 深入理解计算机系统_3e Datalab实验
由于http://csapp.cs.cmu.edu/并未完全开放实验,很多附加实验做不了,一些环境也没办法搭建,更没有标准答案.做了这个实验的朋友可以和我对对答案:) 实验内容和要求可在http:// ...
- 实验记录三 通用输入输出(GPIO)
之前把全部程序都跑了一次后,得到了导师下一步的安排. 例如以下: 1.编写一个程序.实如今LCD上显示一个万年历,包含年月日 星期 还有室内的温度.2.编写一个程序,将原来的交通灯改为跑马灯. 期限是 ...
随机推荐
- 【译】.NET 5 中的诊断改进
基于我们在 .NET Core 3.0 中引入的诊断改进,我们一直在努力进一步改进这个领域.我很高兴介绍下一波诊断改进. 诊断工具不再需要 .NET SDK 直到最近,.NET 诊断工具套件还只能作为 ...
- Mac下安装及配置Appium环境
candiceli Mac下安装及配置Appium环境 我是小白,自己研究appium好几周了. 一开始按照同事这篇文章设置Mac下的环境,http://www.cnblogs.com/tangd ...
- H5播放需要解密的m3u8音频文件
<audio ref="audio"></audio> import CryptoJS from "crypto-js"; import ...
- 为什么Mongodb索引用B树,而Mysql用B+树?
引言 好久没写文章了,今天回来重操旧业. 今天讲的这个主题,是<面试官:谈谈你对mysql索引的认识>,里头提到的一个坑. 也就是说,如果面试官问的是,为什么Mysql中Innodb的索引 ...
- 【模拟】10-15 题解 trans
Trans 题目描述 Tgopknight决定使用他的幸运数字2和3来进行这个游戏,他一开始有n个数字,记为{dn}需要 进行k次操作,每次操作找到最小的x使得dx = 2并且dx+1 = 3,此时如 ...
- k8s1.20环境搭建部署(二进制版本)
1.前提知识 1.1 生产环境部署K8s集群的两种方式 kubeadm Kubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群 ...
- Linux中curl的用法
一.简介:在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,是一款强大的http命令行工具.支持文件的上传和下载,是综合传输工具. 二.语法:curl [option] [url ...
- 【问答分享第一弹】MySQL锁总结:MySQL行锁、表锁、排他锁、共享锁的特点
大家好,我是小于哥哈.前几天能分享了第一期面试题,MySQL 中有哪几种锁 和 这些锁各有哪些特点 ,这道面试题是经常会被问到的一个面试题,大家反馈的都挺不错的.今天特此来总结一下. 首发于公众号[终 ...
- DRF之过滤排序分页异常处理
一.过滤 对于列表数据要通过字段来进行过滤,就需要添加 django-filter 模块 使用方法: # 1.注册,在app中注册 settings.py INSTALLED_APPS = [ 'dj ...
- Defense:MS08067漏洞攻防渗透实验
实验环境 Windows XP SP3 IP:172.16.211.129 百度网盘:https://pan.baidu.com/s/1dbBGdkM6aDzXcKajV47zBw 靶机环境 ...