深入了解计算机系统——实验二(Data Lab)(详解)

   日期:2020-05-14     浏览:86    评论:0    
核心提示:深入了解计算机系统——实验二(Data Lab)(详解)实验内容及操作步骤bitAnd函数getByte函数logicalShift函数bitCount函数bang函数tmin函数fitsBits函数divpwr2函数negate函数isPositive函数isLessOrEqual函数ilog2函数float_neg函数float_i2f函数float_twice函数如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注

简述

个人感觉这个实验还是很耗脑子的,因此把我的结果拿出来分享一下(仅供参考)。希望大家在阅读这些文章时,能带着一种辩证的思维去看待,不要认为博主写的就是正确的。当然,如果本文有任何错误,欢迎各位指正。或者大家有什么意见和建议的话,也欢迎和我交流。话不多说,直入正题。

1、bitAnd函数

(1) 函数描述及操作要求
① 函数功能:实现两个int型数据x和y的与运算,并返回结果,结果为int型数据
② 可用操作:~ |
③ 最大操作数:8

(2) 函数实现
① 函数实现代码

int bitAnd(int x, int y) {
	return ~((~x) | (~y));
}

② 函数实现思路
因为只有~ |两个可用操作,但是要实现的是&操作,因此可以考虑用德摩根定律将&运算变为~ |结合的表达式。

2、getByte函数

(1) 函数描述及操作要求
① 函数功能:int数据x从低位到高位的4个字节依次编号为0~3,要求取出该数据中的第n个字节,并返回结果,结果为int型数据
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:6

(2) 函数实现
① 函数实现代码

int getByte(int x, int n) {
	int result = (x >> (n << 3));
	return result & 0xff;
}

② 函数实现思路
要获取数据x中的第n个字节,可以考虑先将要得到的字节通过移位操作移到第0个字节的位置,然后将其与0xff进行与运算,这样就得到了x的第n个字节,并且同时保证了高位的3个字节都为0。

3、logicalShift函数

(1) 函数描述及操作要求
① 函数功能:将int型数据x逻辑右移n位,0 <= n <= 31,并返回结果,结果为int型数据
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:20

(2) 函数实现
① 函数实现代码

int logicalShift(int x, int n) {
	int result = x >> n;
	int val = (1 << 31) >> n;
	val = ~(val << 1);
	return result & val;
}

② 函数实现思路
要实现将int型数据逻辑右移n位,可以先将其进行算数右移,然后将其与数据(最高的n位均为0,其他位均为1)进行与运算使得最高的n位清0,且其他位保持不变。

4、bitCount函数

(1) 函数描述及操作要求
① 函数功能:计算int型数据x的二进制串中1的个数,并返回结果,结果为int型
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:40

(2) 函数实现
① 函数实现代码

int bitCount(int x) {
	int var1 = 0, var2 = 0, var3 = 0, var4 = 0, var5 = 0, result = 0;
	var1 = 0x55 | (0x55 << 8);
	var1 = var1 | (var1 << 16);
	var2 = 0x33 | (0x33 << 8);
	var2 = var2 | (var2 << 16);
	var3 = 0x0f | (0x0f << 8);
	var3 = var3 | (var3 << 16);
	var4 = 0xff | (0xff << 16);
	var5 = 0xff | (0xff << 8);

	result = (x & var1) + ((x >> 1) & var1);
	result = (result & var2) + ((result >> 2) & var2);
	result = (result & var3) + ((result >> 4) & var3);
	result = (result & var4) + ((result >> 8) & var4);
	result = (result & var5) + ((result >> 16) & var5);
	return result;
}

② 函数实现思路
计算1的个数就相当于计算x的二进制串的所有位的和。首先将int型数据x的32位分成16组,并进行X31+X30,X29+X28,…,X3+X2,X1+X0的运算;然后将x分成8组,并进行X31+X30+X29+X28,…,X3+X2+X1+X0的运算。依次类推,接着将x分成4组,2组并进行相应的运算。最后只剩下1组,此时将所有的位进行相加即得到了最终结果。

5、bang函数

(1) 函数描述及操作要求
① 函数功能:不使用!运算符实现!x,x为int型数据,并返回结果,结果为int型
② 可用操作:~ & ^ | + << >>
③ 最大操作数:12

(2) 函数实现
① 函数实现代码

int bang(int x) {
	return ((x | ((~x) + 1)) >> 31) + 1;
}

② 函数实现思路
考虑到对于每一个非0的int型数据x,将其和它的相反数-x进行或运算后,最高位为1,而如果x为0,进行同样的操作后,最高位仍为0。因此可以将以上述运算得到的结果右移31位,最后将这个数加1,就能得到与!运算相同的结果。

6、tmin函数

(1) 函数描述及操作要求
① 函数功能:返回最小二进制补码整数,结果为int型数据
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:4

(2) 函数实现
① 函数实现代码

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

② 函数实现思路
最小二进制补码整数即符号位为1,其他位全为0。直接返回1左移31位的结果即可。

7、fitsBits函数

(1) 函数描述及操作要求
① 函数功能:如果int型数据x可以表示为n位二进制补码整数(其中1 <= n <= 32),则返回1,否则返回0。
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:15

(2) 函数实现
① 函数实现代码

int fitsBits(int x, int n) {
	int sign = 0, var1 = 0;
	sign = x >> 31;
	var1 = x >> (n + (~0));
	return !(sign ^ var1);
}

② 函数实现思路
n位二进制能表示的最大整数为最高位为0,其他位为1,能表示的最小数为最高位为1,其他位为0。所以可以将x右移n-1位后,再将移位后的结果与符号位进行比较,如果两者相同则说明x可以表示为n为二进制数。

8、divpwr2函数

(1) 函数描述及操作要求
① 函数功能:对于0 <= n <= 30,计算x /(2n),向零舍入,返回计算结果,结果为int型。
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:15

(2) 函数实现
① 函数实现代码

int divpwr2(int x, int n) {
	int sign = 0, var = 0;
	sign = x >> 31;
	var = (1 << n) + (~0);
	return (x + (sign & var)) >> n;
}

② 函数实现思路
进行除法运算时,对于非负数来说,是默认向0取整的,而对于负数来说,则需要在移位之前加一个偏置量进行处理。

9、negate函数

(1) 函数描述及操作要求
① 函数功能:返回int型数据x的相反数-x。
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:5

(2) 函数实现
① 函数实现代码

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

② 函数实现思路
x的相反数即为x取反加1

10、isPositive函数

(1) 函数描述及操作要求
① 函数功能:对于int型数据x,如果x > 0,返回1,否则返回0。
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:8

(2) 函数实现
① 函数实现代码

int isPositive(int x) {
	int signal = (x >> 31) & 0x1;
	return !(signal | (!x));
}

② 函数实现思路
考虑!运算的结果和x的符号进行一些运算后可以得到和isPositive函数相同的结果,根据如下表格(根据x的正负进行不同运算返回的结果,signal表示x的符号)

x isPositive signal !
>0 1 0 0
<0 0 1 0
=0 0 0 1

据表可知,只有当signal和!运算得到的结果都为0时,isPositive函数返回值才为1。所以可以将signal和(!x)进行或运算,然后再将得到的结果进行!运算得到最终的结果

11、isLessOrEqual函数

(1) 函数描述及操作要求
① 函数功能:对于int型数据x和y,如果x <= y,则返回1,否则返回0。
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:24

(2) 函数实现
① 函数实现代码

int isLessOrEqual(int x, int y) {
	int signx = 0, signy = 0, signr = 0, result = 0;
	signx = (x >> 31) & 0x1;
	signy = (y >> 31) & 0x1;
	signr = !(signx ^ signy);
	result = x + (~y) + 1;
	return (signr & ((result >> 31) | (!result))) | ((!signr) & signx);
}

② 函数实现思路
x <= y可以分两种情况来考虑:x和y同号,x和y异号。异号时要满足x <= y那么x一定为负数;同号时要满足x <= y,只能是两者相减为负数或者为0。

12、ilog2函数

(1) 函数描述及操作要求
① 函数功能:返回log2x的值,返回结果为int型。
② 可用操作:! ~ & ^ | + << >>
③ 最大操作数:90

(2) 函数实现
① 函数实现代码

int ilog2(int x) {
	int result = 0;
	result = (!!(x >> 16)) << 4;
	result = result + ((!!(x >> (result + 8))) << 3);
	result = result + ((!!(x >> (result + 4))) << 2);
	result = result + ((!!(x >> (result + 2))) << 1);
	result = result + (!!(x >> (result + 1)));
	return result;
}

② 函数实现思路
该函数实际上就是要找到最接近一个数n使得2n最接近x,且满足2n <= x。因此可以先将int型数据x右移16位,并进行两次取反操作,如果得到的值为1,则说明x的高16位中存在至少一个1,那么result应加上16;如果得到的值为0,则说明高16位中不存在1。然后再将x右移(result+8)位,同样进行两次取反操作,如果得到的值为1,则说明在(result+8)和(result+15)这8位中至少有一个1,那么result应加上8;如果得到的值为0,则说明这8位中不存在1。依次类推,继续将x右移(result+4),(result+2),(result+1)位,并进行同样的操作即可得到最终结果。

13、float_neg函数

(1) 函数描述及操作要求
① 函数功能:返回浮点参数f的表达式-f的位等效项。参数和结果都作为无符号int传递,但是它们将被解释为单精度浮点值的位级表示。 当参数为NaN时,返回参数。
② 可用操作:任何整数/无符号运算,包括 ||, &&. also if, while
③ 最大操作数:10

(2) 函数实现
① 函数实现代码

unsigned float_neg(unsigned uf) {
	unsigned erule, enow, frule, fnow;
	frule = (1 << 23) - 1;
	erule = 0xff << 23;
	fnow = uf & frule;
	enow = uf & erule;
	if ((enow == erule) && fnow){
		return uf;
	}
	return (1 << 31) ^ uf;
}

② 函数实现步骤
函数的参数可能为NaN(Not a Number)因此需要进行判断。如果参数uf的第23位到第30位全为1,而且uf的低23位不为0,这说明uf解释为单精度浮点值的位级表示时是一个NaN,所以应该直接返回,否则应直接将uf的最高位(符号位)取反即可得到-f。

14、float_i2f函数

(1) 函数描述及操作要求
① 函数功能:返回表达式(浮点数)x的等价位。 结果以unsigned int形式返回,但是将其解释为单精度浮点值的位级表示。
② 可用操作:任何整数/无符号运算,包括 ||, &&. also if, while
③ 最大操作数:30

(2) 函数实现
① 函数实现代码

unsigned float_i2f(int x) {
	unsigned sign = 0, enow = 0, fnow = 0, absx = x,
	shiftLeft = 0, tail = 0, result = 0;
	unsigned pos = 1 << 31;
	if (x == 0) {
		return 0;
	}else if (x < 0) {
		absx = -x;
		sign = pos;
	}
	while ((pos & absx) == 0) {
		absx <<= 1;
		shiftLeft += 1;
	}
	enow = 127 + 31 - shiftLeft;
	tail = absx & 0xff;
	fnow = (~(pos >> 8)) & (absx >> 8);
	result = sign | (enow << 23) | fnow;
	if (tail > 0x80) {
		result += 1;
	} else if (0x80 == tail) {
		if (fnow & 1) {
		    result += 1;
		}
	}
	return result;	
}

② 函数实现思路
该函数主要考察int型数据到float型数据转化的过程,因此按照步骤一步一步判断执行即可。首先对x进行判断,如果等于0则可以直接返回,如果小于0则进入循环,找到x除符号位外的最高位的1。找到1后就可以得到左移的值,进而就可以得到阶码值,将被舍去的尾数tail,和将获得的尾数。之后再将符号位,阶码,尾数这三者相或就得到了result。当然最后还要对尾数tail进行判断,如果大于0x80,则result加1;如果等于0x80,则应向偶舍入。最后返回结果即可。

15、float_twice函数

(1) 函数描述及操作要求
① 函数功能:返回浮点参数f的表达式2 * f的位等效项。 参数和结果都作为unsigned int传递,但是它们将被解释为的位级表示。单精度浮点值。当参数为NaN时,返回参数
② 可用操作:任何整数/无符号运算,包括 ||, &&. also if, while
③ 最大操作数:30

(2) 函数实现
① 函数实现代码

unsigned float_twice(unsigned uf) {
	unsigned sign = 0, enow = 0, fnow = 0;
	unsigned pos = 1 << 31;
	unsigned frule = (1 << 23) - 1;
	if (uf == 0) {
		return 0;
	}
	if (uf == pos) {
		return uf;
	}
	sign = uf & pos;
	enow = (uf >> 23) & 0xff;
	if (enow == 0xff) {
		return uf;
	}
	fnow = uf & frule;
	if (enow == 0) {
		fnow = fnow << 1;
		if (fnow & (1 << 23)) {
			fnow = fnow & frule;
			enow += 1;
		}
	} else {
		enow += 1;
	}
	return sign | (enow << 23) | fnow;
}

② 函数实现思路
首先对uf进行判断,如果uf为正0或负0,则直接返回uf,因为他们的两倍还是它本身。然后对阶码值进行判断,如果阶码值等于0xff,则说明uf为无穷大或者NaN,那么应直接返回uf;如果阶码值为0,说明uf为非规格化值,则应先将尾数乘2。然后判断尾数变化后的值是否存在进位,如果是则应该将阶码值加1,且要将尾数的值进行更新;如果阶码值不为0,则直接将其加1即可。最后将符号位,阶码,尾数三者相或就得到了2*uf,最后返回该值即可。

参考资料:
https://www.cnblogs.com/tlz888/p/9271538.html

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
更多>相关资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服