csapp Lab1

bitXor函数

函数要求:

函数名bitXor
参数int , int
功能实现x^y
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

根据逻辑代数 a n s = x ‾ × y + x × y ‾ = x ‾ y ‾ × x y ‾ ‾ ‾ ans=\overline{x}×y+x×\overline{y}=\overline{\overline{\overline{x}y}×\overline{x\overline{y}}} ans=x×y+x×y=xy×xy

函数实现:

int bitXor(int x, int y) {
  return ~(~((~x)&y)&~(x&(~y)));
}

getByte(x, n)函数

函数要求:

函数名getByte(x, n)
参数int , int
功能实现从字x中取出第n个字节
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

x右移8n(n<<3)位,取最后一个字节

函数实现:

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

logicalShift(x, n)函数

函数要求:

函数名logicalShift(x, n)
参数int , int
功能实现逻辑右移
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

利用全1掩码将前32-n (32+~n+1) 位置0,但注意到当 n==0 时编译会自动取模导致不移动,因此可以分两步移动:mask<<(32+~n))<<1

函数实现:

int logicalShift(int x, int n) {
  int mask=~0;
  return (~((mask<<(32+~n))<<1))&(x>>n);
}

bitCount(x)函数

函数要求:

函数名bitCount(x)
参数int
功能实现计算x中1的数目
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

  最直观的想法是分别做32次右移判断每一位是不是1(不行),但可以进行优化。
  首先,我们可以在局部沿用以上思路,例如四位一组,使用用掩码 m = 00010001 m=00010001 m=00010001,进行操作:(x&m)+((x>>1)&m)+((x>>2)&m)+((x>>3)&m),这会使每四位的1个数保存在四位的小组里。(如11010101运算后会得到00110010=0x32)
  接下来需要做的就是将结果归并,由于结果最大是32,需要两组(8位)表示,因此在第一步相邻两组归并时需要利用掩码消除右移操作导致的高位上的重复 mm=0x0f0f0f0f,之后的归并由于高位不会影响结果所以可以不用舍去。归并完成后,通过&0x3f取最后6位(最大结果32仅需6位表示)

函数实现:

int bitCount(int x) {
  int m=0x11|(0x11<<8)|(0x11<<16)|(0x11<<24); //m=0x11111111
  int mm=0x0f|(0x0f<<8)|(0x0f<<16)|(0x0f<<24); //mm=0x0f0f0f0f
  int temp=(x&m)+((x>>1)&m)+((x>>2)&m)+((x>>3)&m);
  temp=(temp+(temp>>4))&mm;
  temp=(temp>>8)+temp;
  temp=(temp>>16)+temp;
  return temp&0x3f;
}

conditional(x,y,z)函数

函数要求:

函数名conditional(x,y,z)
参数int , int , int
功能实现类似于C语言中的 x ? y : z
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

利用!!操作的特性将x转化位0或全1,随后根据逻辑写出

函数实现:

int conditional(int x, int y, int z) {
  x=!!x;
  x=~x+1;
  return (x&y)+((~x)&z);
}

tmin()函数

函数要求:

函数名tmin()
参数
功能实现返回最小的补码
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

0x 8 0 0 0 0 0 0 0

函数实现:

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

fitsBits(x,n)函数

函数要求:

函数名fitsBits(x,n)
参数int , int
功能实现x的补码是否可以表示成n位
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

如果第n位及之前为全0或全1则可以表示为n位补码

函数实现:

int fitsBits(int x, int n) {
  int move=32+(~n+1);
  return !(x^((x<<move)>>move));
}

dividePower2(x,n)函数

函数要求:

函数名dividePower2(x,n)
参数int , int
功能实现计算 x / 2 n {x}/{2^n} x/2n
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

正数直接右移n位即可,负数右移当不能被 2 n 2^n 2n 整除时结果会输出下取整,而我们需要的是上取整,所以在移动前需要加上11···1(n个1)的偏移,这对于整除的情况没有影响,而不整除时会在第n+1位产生一个进位,转为上取整。

函数实现:

int dividePower2(int x, int n) {
   return (x+(x>>31&((1<<n)+~0)))>>n;
}

negate(x)函数

函数要求:

函数名negate(x)
参数int
功能实现取负
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

补码,取反加一

函数实现:

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

howManyBits(x)函数

函数要求:

函数名howManyBits(x)
参数int
功能实现计算表达 x 所需的最少位数
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

目标将x左侧连续的0/1保留一个,如1110->10, 0000101->0101。
可以通过x=x^(x<<1)操作,将x左侧连续两个以上的0/1均转化为"一串0"+1的形式(1110->0010 , 0000101->0001111),然后只需定位最左侧的1的位置即可("一串0"中最后一个0位置+1)
具体操作可以使用二分查找,代码如下所示。

函数实现:

int howManyBits(int x) {
  int m=0;
  x=x^(x<<1);
  m=m+((!!(x&((~0)<<(m+16))))<<4);
  m=m+((!!(x&((~0)<<(m+8))))<<3);
  m=m+((!!(x&((~0)<<(m+4))))<<2);
  m=m+((!!(x&((~0)<<(m+2))))<<1);
  m=m+(!!(x&((~0)<<(m+1))));
  return m+1;
}

isLessOrEqual(x,y)函数

函数要求:

函数名isLessOrEqual(x,y)
参数int , int
功能实现判断x是否小于等于y
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

基本思想就是判断 y-x 是否>=0,同时还要考虑溢出。
情况1:y-x>=0 此时只有一种情况不行:y<0且x>0
情况2:y-x<0 此时有一种情况可以:y>0且x<0
讨论完成后编程实现即可

函数实现:

int isLessOrEqual(int x, int y) {
  int sig_x=(x>>31)&1;
  int sig_y=(y>>31)&1;
  int sig_c=((y+(~x+1))>>31)&1;
  return ((!sig_y)&(sig_x)&(sig_c))|((!((sig_y)&(!sig_x)))&(!sig_c));
}

intLog2(x)函数

函数要求:

函数名intLog2(x)
参数int
功能实现计算⌊log2(x)⌋(向下取整)
要求Legal ops: ! ~ & ^ | + << >>

实现分析:

二分查找左侧最后一个连续的0

函数实现:

int intLog2(int x) {
  int n=0;
  n=n+((!!(x&((~0)<<(n+16))))<<4);
  n=n+((!!(x&((~0)<<(n+8))))<<3);
  n=n+((!!(x&((~0)<<(n+4))))<<2);
  n=n+((!!(x&((~0)<<(n+2))))<<1);
  n=n+(!!(x&((~0)<<(n+1))));
  return n;
}

floatAbsVal(uf)函数

函数要求:

函数名floatAbsVal(uf)
参数unsigned
功能实现计算f的绝对值的位级表示
要求Any integer/unsigned operations incl. ||, &&. also if, while

实现分析:

阶码全为1的情况直接返回
其他情况符号位取0

函数实现:

unsigned floatAbsVal(unsigned uf) {
  if(((uf&0x7f800000)>>23 == 255) && (uf&0x7fffff)) return uf;
  return uf&0x7fffffff;
}

floatScale1d2(uf)函数

函数要求:

函数名floatScale1d2(uf)
参数unsigned
功能实现计算0.5*f的位级表示
要求Any integer/unsigned operations incl. ||, &&. also if, while

实现分析:

根据逻辑代数 a n s = x ‾ × y + x × y ‾ = x ‾ y ‾ × x y ‾ ‾ ‾ ans=\overline{x}×y+x×\overline{y}=\overline{\overline{\overline{x}y}×\overline{x\overline{y}}} ans=x×y+x×y=xy×xy

函数实现:

unsigned floatScale1d2(unsigned uf) {
  int s=uf&0x80000000;
  int exp=(uf&0x7f800000)>>23;
  if((uf&0x7fffffff)>=(0xff<<23))return uf;
  if(exp>1) return (uf&0x807fffff)+((exp-1)<<23);
  if((uf&0x3)==0x3) uf=uf+2;
  return ((uf>>1)&0x007fffff)|s;
}

floatFloat2Int(uf)函数

函数要求:

函数名floatFloat2Int(uf)
参数unsigned
功能实现计算(int)f的位级表示
要求Any integer/unsigned operations incl. ||, &&. also if, while

实现分析:

先获取 s,exp,frc 三段随后分类讨论
exp 减去 127
能转成int的frc一定是规格化的,在前面先补上1

exp>31时溢出,全部返回0x80000000
exp<0时不到1,全部返回0

其余情况,根据小数点位置,exp>23 时 frc 左移 exp-23 位,ex<=23 时 frc 右移 23-exp 位

最后,判断符号,符号位与原数一致,返回即可
不一致时负数说明缺一位才能表示,溢出了,返回0x80000000;负数返回frc的补码
(这样能通过测评,虽然并没有完美解决负数问题)

函数实现:

int floatFloat2Int(unsigned uf) {
  int s=uf>>31;
  int exp=((uf&0x7f800000)>>23)-127;
  int frc=(uf&0x007fffff)|0x00800000;
  if(!(uf&0x7fffffff)) return 0;

  if(exp>31) return 0x80000000;
  if(exp<0) return 0;

  if(exp>23) frc=frc<<(exp-23);
  else frc=frc>>(23-exp);

  if(!((frc>>31)^s)) return frc;
  else if(frc>>31) return 0x80000000;
  else return ~frc+1;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值