CSAPP DataLab学习笔记

1. bitXor

/* 
 * bitXor - x^y using only ~ and & 
 *   Example: bitXor(4, 5) = 1
 *   Legal ops: ~ &
 *   Max ops: 14
 *   Rating: 1
 */
int bitXor(int x, int y) {

  return 2;
}

思路

将异或的真值表写出来,再用 & | ~ 表示,最后化简

代码

int bitXor(int x, int y) {
  /*
  int exp1 = ~(x & ~y);
  int exp2 = ~(~x & y);
  int res = ~(exp1 & exp2);
  */

  return ~((~x)&(~y))&(~(x&y));
}

2.tmin

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

思路

返回二进制补码的最小值,即0x80000000,使用左移操作即可

代码

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

3.isTmax

/*
 * isTmax - returns 1 if x is the maximum, two's complement number,
 *     and 0 otherwise 
 *   Legal ops: ! ~ & ^ | +
 *   Max ops: 10
 *   Rating: 1
 */
int isTmax(int x) {
  return 2;
}

思路

如果x是二进制补码的最大值0x7fffffff,返回1,否则返回0.
我的思路是将x进行运算,如果是0x7fffffff,运算结果会是一个特殊值,比如全0,而其他数进行运算则不是全0,最后取非。
想到了0x7fffffff + 0x7fffffff + 1 = 0xffffffff,按位取反后为0x0.
但一直有bug调试不出来,调试结果如下:

printf("%x %x %d %d\n", x, x + x + 1, (!(~(x + x + 1))), ~(x + x + 1));

输出:
7fffffff ffffffff 0 0
取了非和没取非的值居然相同
最后参考了这篇博客

代码

int isTmax(int x) {
  //printf("%x\n", !(~(0x7fffffff + 0x7fffffff + 1)));
  //printf("%x %x %x\n", x, 0x7fffffff, !!~(x+x+1));
  //printf("%x %x %d %d\n", x, x + x + 1, (!(~(x + x + 1))), ~(x + x + 1));
  int i = x + 1;
  int j = x ^ i;
  int k = ~j;
  return !(k + !i);
}

4. allOddBits

/* 
 * allOddBits - return 1 if all odd-numbered bits in word set to 1
 *   where bits are numbered from 0 (least significant) to 31 (most significant)
 *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */
int allOddBits(int x) {                                                      
  return 2;
} 

思路

如果x的所有奇数位都为1则返回1,否则返回0
先构造一个A8 = 0xAAAAAAAA作为掩模,再和x进行与运算,将无关的偶数位置0
将结果和A8异或,若奇数位全为1,结果将为全0,取个非即答案

代码

/* 
 * allOddBits - return 1 if all odd-numbered bits in word set to 1
 *   where bits are numbered from 0 (least significant) to 31 (most significant)
 *   Examples allOddBits(0xFFFFFFFD) = 0, allOddBits(0xAAAAAAAA) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 2
 */
int allOddBits(int x) {
  int AA = 0xAA;                                                               
  int A4 = (AA << 8) + AA;                                                       
  int A8 = (A4 << 16) + A4;                                                         
  return !((x & A8) ^ A8);                                                          
} 

5. negate

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

思路

返回相反数,即返回-x的补码,取反加一即可

代码

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

6. isAsciiDigit

/*  
 * isAsciiDigit - return 1 if 0x30 <= x <= 0x39 (ASCII codes for characters '0' to '9')
 *   Example: isAsciiDigit(0x35) = 1.
 *            isAsciiDigit(0x3a) = 0.
 *            isAsciiDigit(0x05) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 3
 */
int isAsciiDigit(int x) {
  return 2

思路

判断高28位为0x30且第4位为0或第2位和第三位全为0,用m1, m2, m3来表示这三个条件,满足条件为全0,最后化简

代码

int isAsciiDigit(int x) {
  int mask1 = ~0xf;
  int m1 = (x & mask1) ^ 0x30;
  int m2 = (x & 0x8) ^ 0;
  int m3 = (x & 0x6) ^ 0;
  //printf("%x %x %x %x\n", x, m1, m2, m3);
  //return !(m1 | (!!m2 & !!m3));
  return !m1 & (!m2 | !m3);

7.conditional

/* 
 * conditional - same as x ? y : z 
 *   Example: conditional(2,4,5) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */
int conditional(int x, int y, int z) {
  return 2;
}

思路

实现运算符x ? y : z,x取非得到0或1,取反加一得到全0或全1,再分别和y,z进行与运算,其中一个不变,另一个为0,返回二者的或

代码

int conditional(int x, int y, int z) {
  int bit = !x;
  int bit32 = ~bit + 1;
  //printf("%x %x %x\n", x, bit2, bit32);
  return (y & ~bit32) | (z & bit32);
}

8. isLessOeEqual

/* 
 * 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) {
  return w;
}

思路

进行x - y,判断是否<=0,补码运算为[x]补 + [-y]补,[-y]补 = ~y + 1
res1判断符号位是否为1,res2判断x - y是否等于0

代码

int isLessOrEqual(int x, int y) {
  int dif = x + (~y + 1);
  int m1 = 1 << 31;
  int res1 = !((dif & m1) ^ m1);
  int res2 = !dif;
  return res1 | res2;
}

9.logicalNeg

/* 
 * logicalNeg - implement the ! operator, using all of 
 *              the legal operators except !
 *   Examples: logicalNeg(3) = 0, logicalNeg(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4 
 */
int logicalNeg(int x) {
  return 2;
}

思路

这题比较难,要实现取非运算,关键是区分全0和非全0
我开始的思路是将非0的书转化为全1,即0xffffffff,于是想到了可以进行或运算将32位全部置1,但是由于不知道x的哪一位为1,需要向左和向右移位多次,这样操作个数就超了
后来想到不需要全部置1,只需要保证特定的一位为1即可,因为可以将它移动到第一位再取反加一
考虑x的最高位,有两种情况,要么为1,要么为0
如果为1,使用或运算即可,如果为0,可以用一种巧妙的方法将它置1,即取反加一
因为取反加一有另一种方法:从右数第一个1及其右边数位保持不变,左边数位取反,最高位若为0,它一定会被取反,得到1
因此若x非0,则top1最高为必为1,右移31位后得到全1(补码右移左补1),加一后得到0
若x为0,则top1 >> 31 = 0,加一后得到1

代码

int logicalNeg(int x) {
  int top1 = x | (~x + 1);
  return (top1 >> 31) + 1;
  /*
  int one2 = x | (x << 1) | (x >> 1);
  int one4 = one2 | (one2 << 2) | (one2 >> 2);
  int one8 = one4 | (one4 << 4) | (one4 >> 4);
  int one16 = one8 | (one8 << 8) | (one8 >> 8);
  int one32 = one16 | (one16 << 16) | (one16 >> 16); 
  return one32 + 1;
  */
}
posted @ 2023-07-11 20:49  ying_hua  阅读(47)  评论(0编辑  收藏  举报