深入理解操作系统——datalab-handout

实验目的:

1.替换bits.c中各个函数中的return,格式要求如下所示:
int Funct(arg1, arg2, …) {
/* brief description of how your implementation works */
int var1 = Expr1;

int varM = ExprM;

  varJ = ExprJ;
  ...
  varN = ExprN;
  return ExprR;

}
其中,每一个“Expr”只能使用如下规则:
① 数字只能使用0到255(0xff),不能使用像0xffffffff这样大的数字
② 函数参数和局部变量(没有全局变量)
③ 一元运算目:! ~
④ 二元运算目:& ^ | + << >>
2.bits.c中所给的15个函数都是缺失的,需要用上每个函数被允许的操作去实现所要求的功能。
3.下面的操作不被允许:
① 使用任何控制结构,如if, do, while, for, switch等。
② 定义或使用任何宏。
③ 在此文件中定义任何其他函数。
④ 调用任何库函数。
⑤ 使用任何其他的操作,如&&, ||, -, or ?:
⑥ 使用任何形式的casting
⑦ 使用除int以外的任何数据类型。这意味着你不能使用数组、结构等。
对于需要你执行浮点运算的问题,编码规则较不严格。允许使用循环和条件控制也可以同时使用int和unsigned。可以使用任意整数和无符号常量。

实验内容及操作步骤:

一、初步安装dlc:
由于第二次试验是基于dlc编译环境,所以需要先进行添加,即将本次实验的文件夹datalab-handout复制到linux环境下,之后的实验都是在这个文件夹下进行:
在这里插入图片描述
在这里插入图片描述
二、填写bits.c中实验需填写的内容,并进行简单的解释:
先对整个bits.c文件进行翻译,了解到要求是:
警告:请不要使用<stdio.h>头文件,他会使dlc编译器发生错误,你可以仍旧在不包含<stdio.h>头文件的情况下使用printf语句来调试,尽管你可能会有警告信息。一般情况,忽视警告信息是不对的,但在这里没有问题
你将会通过编译和调用在这个源文件中的函数来设计自己的代码,并最终向数据实验室提供你的解决方案。通过一行或多行的c语言代码来替代函数中的return语句并实现函数,你的代码必须满足下面几个规则:

  1. 0到255(包含)之间的整数常量,你不能使用太大的常数
  2. 功能语句和局部变量(不能使全局变量)
  3. 一元整数操作如!(逻辑非)和~(按位非)
  4. 二元整数操作如&(按位与)、^(异或)、|(或)、+(相加)、<<(算术左移)、>>(算术右移)
    你不被允许以下操作:
  5. 使用任何一个控制结构,像if,do,while,for,switch等等
  6. 定义或使用宏
  7. 在本文件中定义任何一个格外的函数
  8. 声明或调用任何函数
  9. 使用别的任何操作符,如&&、||、-或者?
  10. 使用任何形式的指针
  11. 使用任何除了int之外的数据类型,这里暗示你不能使用数组,结构体和类
    你可以假定你的机器:
  12. 使用2的补码表示负数,32位表示整数
  13. 执行算术右移
  14. 移动一个整数超过他的字长的时候会产生不可预测的后果
    对于要执行浮点操作的问题,编码规则不那么严格,允许使用循环和条件控制即if和for语句,你可以使用int和unsigned,可以使用任意整数和无符号常量
    你被禁止:
  15. 定义或使用宏
  16. 在本文件中定义任何其他函数
  17. 声明或调用任何函数
  18. 使用任何形式的指针
    5.使用除int和无符号以外的任何数据类型,意味着不能用数组,结构体或类
  19. 使用任何浮点数据类型,操作或常量
    提示:
  20. 使用dlc(数据实验室检查器)编译器(在讲义中描述)来检查解决方案的合法性
  21. 每一个函数都有一个最大数量的操作符,允许你在实现该函数时使用这些操作符。最大操作符计数由dlc检查,请注意“=”不计算在内,你可以随意使用运算符
  22. 使用btest测试工具来检查你的功能是否正确
  23. 使用bdd检查器正式的验证你的功能
  24. 每个函数的最大操作数在每个函数的头注释中给出,如果在编写和次文件中最大操作数之间存在不一致,请将此文件作为权威来源
    三、对函数进行添加和重写:
    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));
}

代码解释:使用~与|实现按位与,真值表为(每一位):
在这里插入图片描述
由于最高限制次数为8次,那么只能使用德摩根律,得到x&y=(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);
}

代码解释:将一个32位数实现返回对应编号位置的数字,先将编号n转换为移动的位数,比如2就要移动2x2^3个位置,0则不需要移动,将所需要的数字移动到最低位,接着按位与0XFF,只取最低的两位,得到最终结果。按位与0xFF表示保留最后一个字节。
例:假设x=0x12345678,n=2
那么78是编号0,56编号为1,n移动3位后得到的结果是2x8=16位,即需要把x向右移动16位,算数逻辑均可。以算数为例,则x为0x00001234,取最后的两位即34,即为所求结果。
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) {
  return ~((((1<<31)&x)>>n)<<1)&(x>>n);
}

代码解释:将32位数逻辑右移n位
逻辑右移是在左端补最高有效位的值,算术右移是直接补0,所以将1左移31位后得到最高位为1,其他全为0的数,与x相与后得到x的符号位,其他全为0的数,其再算术右移n位然后左移一位,有n个符号位剩余全为0的数,再取反得到n个符号位的相反位,其他全为1的数。这个数再与x算术右移n为的数进行相与,首先右端的数和1111相与后结果不变,而符号位会进行保留。
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 count; 
    int tmpMask1 = (0x55)|(0x55<<8); 
    int mask1 = (tmpMask1)|(tmpMask1<<16); 
    int tmpMask2 = (0x33)|(0x33<<8); 
    int mask2 = (tmpMask2)|(tmpMask2<<16); 
    int tmpMask3 = (0x0f)|(0x0f<<8); 
    int mask3 = (tmpMask3)|(tmpMask3<<16); 
    int mask4 = (0xff)|(0xff<<16); 
    int mask5 = (0xff)|(0xff<<8); 
    count = (x&mask1)+((x>>1)&mask1); 
    count = (count&mask2)+((count>>2)&mask2); 
    count = (count + (count >> 4)) & mask3; 
    count = (count + (count >> 8)) & mask4; 
    count = (count + (count >> 16)) & mask5; 
    return count; 
}

代码解释:输入一个int型数字,输出该数字中机器码中有多少个1,即通过二分法进行查找记录即可,先计算每两位中1的个数,并用对应的两队来进行存储,然后计算每四位中1的个数,用对应的4位进行存储,最后得到16位中1的个数,即x中1的个数
5、

在这里插入代码片

代码解释:不用!而实现!功能。第一步~x+1求补码,与x本身进行相或后得到最高有效位,如果大于0那么最高有效位必为1,将该数逻辑右移31位后得到要么全零要么全一的数,然后与1相与得到一个相反的值就可以实现!的操作。
6、

/*
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
  return 1<<31;
}

代码解释:得到最小的二进制数,直接左移1即可
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) {
	//get 32-n;
	return !(((x >> (n+(~0))) + 1)>>1);
}

代码解释:判断x是否能被n位二进制数表示,即x是否在-2(n-1)到2(n-1)-1范围内
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)&((1<<n)+(~0))))>>n;
}

代码解释:x除以2的n次方,实际上直接右移n位即可,面对负数时需要加上一个偏移量
9、

/*
 * negate - return -x 
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
  return ~x+1;
}

代码解释:取x的相反数,直接返回~x+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|(!x));
}

代码解释:如果x大于0则返回1,否则返回0,直接判断符号位,但需要特殊考虑0
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 signx=x>>31;  
  	int signy=y>>31;
  	int signSame=((x+((~y)))>>31)&(!(signx^signy));
  	int signDiffer=signx&(!signy);
  	return signDiffer|signSame;  
}

代码解释:如果x小于等于y,则返回1,否则返回0。先对符号位进行比较,第1,2行得到了x和y的符号位,第3行比较两者相减是否越界,第四行得到两者的符号位是否异号,最终返回两个结果的相或结果,只要有一者为1,那么就代表x小于等于y,否则x大于y
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 bitsNumber=0;
    bitsNumber=(!!(x>>16))<<4;//
    bitsNumber=bitsNumber+((!!(x>>(bitsNumber+8)))<<3);
    bitsNumber=bitsNumber+((!!(x>>(bitsNumber+4)))<<2);
    bitsNumber=bitsNumber+((!!(x>>(bitsNumber+2)))<<1);
    bitsNumber=bitsNumber+(!!(x>>(bitsNumber+1)));
    //for non zero bitsNumber, it should add 0
    //for zero bitsNumber, it should subtract 1
    bitsNumber=bitsNumber+(!!bitsNumber)+(~0)+(!(1^x));
    //当x为0时,还需要减一才能得到正确值。
    return bitsNumber;
}

代码解释:得到一个数是由多少二进制位表示,倒数第二行表示当x为0的时候,还需要进行减一才能得到正确值,是一个类似于分治法,逐步化简。
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 result;
    unsigned tmp;
    result=uf^0x80000000; //将符号位改反 -f 
    tmp=uf & (0x7fffffff);
    if(tmp > 0x7f800000)//此时是NaN
        result = uf;
    return result;
}

代码解释:计算浮点数的相反数,直接将符号位改反即可,但需要判断NAN的情况,这里已经是浮点数类型了,可以使用if判断。
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 shiftLeft=0;
    unsigned afterShift, tmp, flag;
    unsigned absX=x;
    unsigned sign=0;
    //special case
    if (x==0) return 0;
    //if x < 0, sign = 1000...,abs_x = -x
    if (x<0)
    {
        sign=0x80000000;
        absX=-x;
    }
    afterShift=absX;
    //count shift_left and after_shift
    while (1)
    {
        tmp=afterShift;
        afterShift<<=1;
        shiftLeft++;
        if (tmp & 0x80000000) break;// 
    }
    
    if ((afterShift & 0x01ff)>0x0100)
        flag=1;
    else if ((afterShift & 0x03ff)==0x0300)
        flag=1;
    else
        flag=0;
 
    return sign + (afterShift>>9) + ((159-shiftLeft)<<23) + flag;
}

代码解释:将整形转化为无符号浮点数,即求浮点数。先取的符号位,再将剩余部分全部取为正数形式,即absx,即可以得到无符号的数值。然后将有数字的部分直接移动到最高位,记录移动的位数,再将其移动9位(因尾数只要23即可)。对于阶码部分,由于记录的是小数点从31位右数到第一个1,但实际上需要处理的是从第0位到第一位,所以E=32-shiftleft,bias为127,加上为159,if部分做舍入处理
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 f = uf;
    if ((f & 0x7F800000) == 0) //
    {
        //左移一位
        f = ((f & 0x007FFFFF) << 1) | (0x80000000 & f);//007fff---11111111111111111111111 23bit 
    }
    else if ((f & 0x7F800000) != 0x7F800000)
    {
        f =f + 0x00800000;  //100000   23
    }
    return f;
}

代码解释:将无符号浮点数乘2,对无阶码小数,对其尾部乘2即可,即直接左移一位,但要提前记录符号位。对于规格化数,直接对其阶码+1即可
四、实验结果及分析:
1、首先转移dlc所在的目录之下:
在这里插入图片描述
2、然后使用dlc检测bits.c是否有错误,代码行为:./dlc bits.c
在这里插入图片描述
结果显示没有错误,即书写规范
3、通过使用dlc的-e选项
在这里插入图片描述
显示各个操作数符合要求
4、使用btest检验函数实现代码的功能正确性,先使用make编译生成btest可执行程序,具体代码行为:make(make会对当前目录下的所有程序调用gcc进行编译)
在这里插入图片描述
几乎所有的.c文件都生成了相对应的可执行文件:
在这里插入图片描述
5、调用btest命令检查bits.c中的所有函数的功能的正确性,以便下一步查找错误原因,指令行为:./btest bits.c
在这里插入图片描述
至此,基本上所有实验已经完成,但我们可以继续练习一下btest的使用,例如测试所有函数的正确性并打印出错误信息。
在这里插入图片描述
结果基本相同
或者测试特有参数,如测试所有函数在不返回错误信息的紧凑型模式:
在这里插入图片描述
由于没有错误,所以实际上结果还是一样
或者测试特定函数名的函数,如./btest -f bitAnd
在这里插入图片描述
至此,实验的全部内容已经全部完成。

  • 17
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
DLC131相机驱动是用于在计算机上与DLC131相机进行连接和交互的软件程序。相机驱动是必须要安装的,它起到了桥梁的作用,将相机的功能与计算机的操作系统连接起来。 安装DLC131相机驱动有以下几个步骤: 首先,将DLC131相机通过USB线缆连接到计算机上。确保相机已经打开并处于可用状态。 接下来,在计算机操作系统中打开设备管理器。可以通过开始菜单中的“控制面板”进入设备管理器,或者使用快捷键Win+X进行打开。 在设备管理器中,可以看到“图像设备”或“相机”等选项。展开该选项,并找到DLC131相机。通常,该相机会标记为未知设备或带有黄色感叹号的设备。 右键点击该相机设备,并选择“更新驱动程序”。此时,系统会询问是从计算机中查找驱动程序还是在线搜索驱动程序。选择从计算机中查找驱动程序。 接下来,在弹出的窗口中选择“浏览计算机以查找驱动程序”。然后,选择指定位置,将其导航到之前下载的DLC131相机驱动程序所在的文件夹。 在文件夹中选择相机驱动程序文件,点击“下一步”进行驱动程序安装。 最后,等待驱动程序安装完成。安装完成后,可以重新启动计算机,确保DLC131相机驱动已经正常安装。 总之,安装DLC131相机驱动是非常重要的,它能够让计算机识别和与相机进行连接,从而实现数据传输和操作控制。希望上述步骤能够帮助您成功安装DLC131相机驱动。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值