这是一个关于机器级的整数、浮点数表示和位运算的实验。要求用给定的操作符、尽可能少的操作数去实现对应的函数功能。

完整的实验包:链接: https://pan.baidu.com/s/1xUBi3XDlidPQFNexbjXoLw 密码: 2333

以下是全部函数的代码:

 /*****************************计算log2(x)向下取整*******************************/
int ilog2(int x) {
int bit_16, bit_8, bit_4, bit_2, bit_1;
bit_16 = (!!(x >> )) << ; //如果x >> 16非零,则至少有16位
x = x >> bit_16;
bit_8 = (!!(x >> )) << ;
x = x >> bit_8;
bit_4 = (!!(x >> )) << ;
x = x >> bit_4;
bit_2 = (!!(x >> )) << ;
x = x >> bit_2;
bit_1 = x >> ; //还剩两位时,直接判断首位。bit_1 == 1,剩两位;bit_1 == 0,剩一位
return bit_16 + bit_8 + bit_4 + bit_2 + bit_1;
     //实际是(bit_1 + 1)-1;由于向下舍入,总位数减一
} /****************************表达x所需要的最少位数******************************/
int howManyBits(int x) {
int bit_16, bit_8, bit_4, bit_2, bit_1, result;
int k = x >> ;
int temp = x ^ k;
     //x为正,temp = x;x为负,temp = ~x
int isZero = (!!(temp << )) >> ;
     //x = 0或x = -1时,temp = 0,isZero = 0...0;否则isZero = 1...1
bit_16 = (!!(temp >> )) << ;
temp = temp >> bit_16;
bit_8 = (!!(temp << )) << ;
temp = temp >> bit_8;
bit_4 = (!!(temp << )) << ;
temp = temp >> bit_4;
bit_2 = (!!(temp << )) << ;
temp = temp >> bit_2;
bit_1 = temp >> ;
result = bit_16 + bit_8 + bit_4 + bit_2 + bit_1 + ;
      //真正位数为bit_16 + ... + bit_1 + 1,再加符号位一位
return (!isZero) | (result & isZero);
} /************************************逻辑右移*************************************/
int logicshift(int x, int n)
{
int temp = ~( << );
temp = ((temp >> n) << ) + ; //生成掩码0...01...1(前面为n个0)
return (x >> n) & temp;
} /*************************类似于c语言中的x ? y : z**********************************/
int conditional(int x, int y,int z)
{
int temp = (~(!x)) + ; //要在return中完成,必须生成x,y的掩码
return (temp & z) | ((~temp) & y); //当x = 0时,temp = 1...1;当x != 0时,temp = 0...0
} /*********************************** x/ 2^n *****************************************/
int divpwr2(int x, int n)
{
int temp = ( << n) + (~); //temp为baising(偏置),1...1(共n个1)
return (x + ((x >> ) & temp)) >> n; //只有负数才要加偏置,所以temp要与符号位相与
} /****************************** x < y ? ***********************************/
int isLessOrEqual(int x, int y)
{
int signx = x >> ;
int signy = y >> ;
int signEqual = (!(signx ^ signy) & ((x + (~y)) >> ));//符号位不同时,做差
int signDiffer = signx & (!signy); //符号位相同,直接比较符号位
return signEqual | signDiffer;
} /**********************操作数更小的版本**************************/
int isLessOrEqual_2(int x, int y)
{
int not_y = ~y;
return ((((x + not_y) & (x ^ not_y)) | (x & not_y)) >> ) & ;
// x-y-1<0 <----------x,y不同号------>x为负,y为正,才为正
} /****************************不用负号得到-x*********************************/
int negate(int x)
{
return ~x + ; //按位取反,末位加一
} /**********************返回最小的补码***************************************/
int tmin(void)
{
return << ;
} /*************************只用~ 和 | 实现x&y*****************************/
int bitAnd(int x, int y)
{
return ~(~x | y); //摩根律
} /**************************从字x中取出第n个字节*********************************/
int getByte(int x, int n)
{
return (x >> (n << )) & 0xff; //是从0开始数的
} /*********************************计算x中1的数目*********************************/
int bitCount(int x)
{
int result;
int tmpmark1 = 0x55 + (0x55 << ); //最大0xff
int mark1 = tmpmark1 + (tmpmark1 << );
int tmpmark2 = 0x33 + (0x33 <<);
int mark2 = tmpmark2 + (tmpmark2 << );
int tmpmark3 = 0x0f + (0x0f << );
int mark3 = tmpmark3 + (tmpmark3 << );
int mark4 = 0xff + (0xff << );
int mark5 = 0xff + (0xff << ); //以上生成5个掩码 result = (x & mark1) + ((x >> ) & mark1);
result = (result & mark2) + ((result >> ) & mark2); //这两个由于进位问题,不能先加再与
result = (result + (result >> )) & mark3; //分治
result = (result + (result >> )) & mark4;
result = (result + (result >> )) & mark5;
return result;
} /***************************计算uf/2*********************************/
unsigned float_half(unsigned uf)
{
unsigned s = uf & 0x80000000;
unsigned exp = uf & 0x7f800000;
int lsb = ((uf & ) == ); //判断frac最后两位是否为11
if (exp == 0x7f800000)
return uf;
else if (exp <= 0x800000)
return s | (((uf ^ s) + lsb) >> ); //uf^s将符号位置零,uf^s = frac + exp末位
else
return uf - 0x800000; //整体思路就是模拟
} /****************************计算(float)x***********************************/
int float_f2i(unsigned uf)
{
int abs;
int sign = uf >> ;
int exp = (uf >> ) & 0xff;
int frac = uf & 0x007fffff;
if (exp < 0x7f) return ;
if (exp > ) return 0x80000000; //Tmax = 2^31 -1 abs = ((frac >> ) + ) << (exp - ); //模拟
if (sign)
return -abs;
else
return abs;
} /****************************计算2*f***************************************/
unsigned float_twice(unsigned uf)
{
int result;
int exp = uf & 0x7f800000;
int frac = uf & 0x7fffff;
if (exp == 0x7f800000)
return uf;
else if (exp == )
frac = frac << ; //frac也可用uf代替,因为此时frac = uf
else
exp = exp + 0x800000;
result = (uf & 0x80000000) | exp | frac;
return result;
}

CSAPP lab1 datalab-handout的更多相关文章

  1. CSAPP:Lab1 -DataLab 超详解

    写在前面 之前考研的时候csapp的书有刷过5,6遍,所以对书本知识还算比较了解.恰逢最近在学c++的时候,顺带刷一下大名鼎鼎的csapp实验. 0. 环境准备 最好准备一个纯净的Linux系统这里建 ...

  2. CSAPP:datalab实验记录

    CSAPP:datalab实验记录 bitXor /* * bitXor - x^y using only ~ and & * Example: bitXor(4, 5) = 1 * Lega ...

  3. CSAPP lab1 datalab-handout(深入了解计算机系统 实验一)

    主要涉及计算机中数的表示法: (1)整数: two's complement,即补码表示法 假设用N位bit表示整数w: 其中最左边一位为符号位,符号位为0,表示正数,为1表示负数. (2)浮点数: ...

  4. CSAPP 之 DataLab 详解

    前言 本篇博客将会剖析 CSAPP - DataLab 各个习题的解题过程,加深对 int.unsigned.float 这几种数据类型的计算机表示方式的理解. DataLab 中包含下表所示的 12 ...

  5. CSAPP lab1——位运算

    本次为一次计算机系统实验,就是使用一些基本的运算符来实现函数功能. ps做这些题让我想起大一上学期刚学二进制时被鹏哥支配的痛苦. 知识准备: 1.负数等于正数取反加一. 2.左移一位相当于将这个数扩大 ...

  6. CSAPP实验——DataLab

    任务:按照要求补充13个函数,会限制你能使用的操作及数量 bitXor(x,y) 只使用 ~ 和 & 实现 ^ tmin() 返回最小补码 isTmax(x) 判断是否是补码最大值 allOd ...

  7. CSAPP DataLab

    注意不同版本的题目可能会有所不同,搜了很多他们的题目和现在官网给的实验题都不一样,自己独立思考完整做一遍顺便记录一下. PS:这些难度为1的题有的说实话我都做了挺久的,不过完整做一遍感觉很有意思,这些 ...

  8. CSAPP缓冲区溢出攻击实验(上)

    CSAPP缓冲区溢出攻击实验(上) 下载实验工具.最新的讲义在这. 网上能找到的实验材料有些旧了,有的地方跟最新的handout对不上.只是没有关系,大体上仅仅是程序名(sendstring)或者參数 ...

  9. 6.828 lab1 bootload

    MIT6.828 lab1地址:http://pdos.csail.mit.edu/6.828/2014/labs/lab1/ 第一个练习,主要是让我们熟悉汇编,嗯,没什么好说的. Part 1: P ...

随机推荐

  1. XP系统显示控件异常解决方法

    XP下显示WPF控件异常,一般通过关闭Direct 3D加速即可.1.按“WIN”+R键,在“运行”输入框中输入“dxdiag”:2.在DirectX诊断工具”对话框,选择“显示”页面,在“Direc ...

  2. E20190308-hm

    sweep vt. 扫除; 打扫,清理; 彻底搜索; 掠过; vi. 打扫; 扫过; 蜿蜒; 大范围伸展; n. 打扫; 延伸; 挥动; 全胜;

  3. forEach方法如何跳出循环

    1.for方法跳出循环 function getItemById(arr, id) { var item = null; for (var i = 0; i < arr.length; i++) ...

  4. Exists 方法

    public void ExistsMethodDemo() { string userId = "123"; string userName = "admin" ...

  5. 2014-5-10 NOIP模拟赛 by coolyangzc

    Problem 1 机器人(robot.cpp/c/pas) [题目描述] 早苗入手了最新的Gundam模型.最新款自然有着与以往不同的功能,那就是它能够自动行走,厉害吧. 早苗的新模型可以按照输入的 ...

  6. uoj#79. 一般图最大匹配(带花树)

    传送门 带花树 不加证明的说一下过程好了:每次从一个未匹配点\(S\)出发bfs,设\(S\)为\(1\)类点,如果当前点\(v\)在本次bfs中未经过,分为以下两种情况 1.\(v\)是未匹配点,那 ...

  7. hyperledger fabric 1.0.5 分布式部署 (四)

    chaincode 的开发 作者在hyperledger fabric 1.0.5 分布式部署 (三)中向读者介绍了如何开发fabric 的chaincode,那么实际上chaincode 还有其他的 ...

  8. Flutter中的可滚动列表组件-PageView

    PageVIew,可滚动的视图列表组件,而且每一个子组件的大小都和视图窗口大小一样. 属性: controller -> PageController 用于控制视图页面滚动到的位置 childr ...

  9. bzoj1458士兵占领

    传送门 和上一题差不多,每行和每列分别看做一个点,障碍点坐标的行和列就不建边,再按照有源汇上下界建图就好了,唯一的区别就是这个题求的是最小流 这个题的数据好水呢,建错图也能A呢 #include< ...

  10. Python -3-列表和元组

    1.用list就可以像修改列表那样修改字符串了 >>> list('Hello') ['H', 'e', 'l', 'l', 'o'] 可将任何序列作为list的参数   2.列表的 ...