计算机系统基础 - Lab1
要求:
1.运用虚拟机在Linux 32位系统下完成实验
2.每个函数功能在限定的操作符下完成
lsbZero
- lsbZero - set 0 to the least significant bit of x
- 最低位设0
int lsbZero(int x) {
return (x>>1)<<1;
}
byteNot
- byteNot - bit-inversion to byte n from word x
- 获取指定字节
int byteNot(int x, int n) {
n=n<<3;
int m=0xff;
m=m<<n;
return m^x;
}
由于一个字节为八位,n需先乘上3(n<<3)
byteXor
- byteXor - compare the nth byte of x and y, if it is same, return 0, if not, return 1
- 比较指定字节
int byteXor(int x, int y, int n) {
int m=0xff;
n=n<<3;
m=m<<n;
x=x&m;
y=y&m;
return !!(x^y);
}
由于一个字节为八位,n需先乘上3(n<<3)
logicalAnd
- logicalAnd - x && y
合取
int logicalAnd(int x, int y) {
x=!(!x);
y=!(!y);
return x&y;
}
- 两次取反将值转化为0-1形式
logicalOr
- logicalOr - x || y
- 析取
int logicalOr(int x, int y) {
x=!(!x);
y=!(!y);
return x|y;
}
rotateLeft
- rotateLeft - Rotate x to the left by n
int rotateLeft(int x, int n) {
int m=0xffffffff;
m=~(m<<n);
int k=x<<n;
x=x>>(32+(~n+1));
x=x&m;
return k+x;
}
parityCheck
- parityCheck - returns 1 if x contains an odd number of 1’s
int parityCheck(int x) {
x=x^(x<<16);
x=x^(x<<8);
x=x^(x<<4);
x=x^(x<<2);
x=x^(x<<1);
x=x>>31;
return !(!x);
}
方法的巧妙在于
每次将数前后分成两组
然后将这两组进行异或运算(^)
如 1001 和 1010 (1001^1010)
得到0011
发现任意两组运算时都会消去偶数个 “ 1 ”
而得到的最后一组若为零则说明前面以每次消除偶数个的方式
消除了所有的 “ 1 ”,说明原数中有偶数个 “ 1 ”
反之为奇数个
mul2OK
- mul2OK - Determine if can compute 2*x without overflow
- 判断乘二是否溢出
int mul2OK(int x) {
return (((x>>31)&0x1)^((x>>30)&0x1))^0x1;
}
讨论两种情况分别正数和负数
无论是哪种情况
当第31位和第30位不同时,乘二即左移都会改变符号位,产生溢出
mult3div2
- mult3div2 - multiplies by 3/2 rounding toward 0,
int mult3div2(int x) {
x=x+(x<<1);
x=(x>>1)+(((x>>31)&0x1)&(((x<<31)>>31)&0x1));
return x;
}
乘3可以转化为 (x<<1)+x
重点是负数在除2的时候
由于负数是补码的形式
如果一个负数最低位为1(如-3这种情况)
我们都知道 -3/2=-1
而 -3(0xfffffffd)右移1位的结果为 -2(0xfffffffe)
可推理出这种情况应加上1
subOK
- subOK - Determine if can compute x-y without overflow
- 判断x-y是否溢出
int subOK(int x, int y) {
int z=x+(~y+1);
x=x>>31;
x=x&0x1;
y=y>>31;
y=y&0x1;
z=z>>31;
z=z&0x1;
return !((x^y)&(x^z));
}
先算出z
我们知道x-y等于x加上y的补码(~y+1)
判断依据为 x , y , z 符号位
(1)符号位相等时,一定不溢出
(2)符号位不同时,结果z与x符号不同才溢出
absval
- absVal - absolute value of x
- 求绝对值
int absVal(int x) {
int y=(x>>31);
return (y&(~x+1))+((~y)&x);
}
float_abs
- float_abs - Return bit-level equivalent of absolute value of f for
- 求单精度浮点数绝对值
unsigned float_abs(unsigned uf) {
int m = uf&0x7fffffff;
if(m>0x7f800000)
return uf;
else
return m;
}
熟记IEEE754单精度浮点数表示这道题应该不难
将浮点数最高位设置为0再赋值给m,即可得到一个整数(不一定)
还需考虑NaN,sNaN情况
即符号位为1,阶码全1,尾数非零情况
我们将该数原封不动返回
floeat_f2i
-
float_f2i - Return bit-level equivalent of expression (int) f
-
float to int
int float_f2i(unsigned uf) {
int x,y;
unsigned m = 0x80000000;
x=(uf>>23)&0xff;//取阶码
y=(uf&0x007fffff)^0x00800000;//将尾数与隐藏的1结合形成一个1xxxxxxxxx....
if(x>158){
return m;//若阶码大于31(158-127),超出int数据范围
}
if(x<127){
return 0;//阶码<0(-127<0)说明这是一个0.xxxx..的数,转化为int为0
}
//范围内的数可以开工
//150为127+23,阶码大于它说明小数点可以左移,否则右移
//y最高位默认为0(0x00800000),因为我们过滤了下>158的情况
//所以在左移过程中不会有溢出的情况(符号位改变),所以如果为负数则将所有位取反再+1即为所求
else if(((uf>>31)&0x1)==1){
if(x>150)
return ((~(y<<(x-150)))+1);
else
return ((~(y>>(150-x)))+1);
}
else{
if(x>150)
return (y<<(x-150));
else
return (y>>(150-x));
}
}
考察IEEE754标准
步骤:
1.取出阶码, 尾数
2.讨论x>158和x<127情况
3.将阶码与尾数结合形成int类型数,若为负数则取反加1