计算机系统基础 - Lab1

计算机系统基础 - 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值