CSAPP Lab1:Data Lab

说明

这是CSAPP即《深入理解计算机系统》的配套实验一(网址link.),本实验有助于了解整形与单精度的原理与实现,也对熟悉位运算大有帮助。

先来一张完成实验的截图
在这里插入图片描述

话不多说,开整!

INT部分

规则

仅使用0-255的整型数,只能用本地变量,还有每一题允许使用的一些运算符。

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) {
   
  int a = ~(x&~y);
  int b = ~(~x&y);
  return ~(a&b);
}

tmin

要求返回最小的二进制补码(2’s complement)整数
− 2 31 \\{-2^{31}} 231是int最小可以表达的十进制数,它的十六进制形式是0x80000000,又因为只能用0-255以内的数,故用0x8左移28位来得到。

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

}

isTmax

如果传入的x是二进制补码表示的最大的数,那么返回1,否则返回0
思路就是最大的数加一会溢出到负数,而只有最大的数和0xffffffff加一之后会改变符号位。把x与x+1异或再取反,如果是最大数或0xffffffff,那么会得到0x0,其它的数都不会得到0x0(只考虑符号位,符号位必定相同,异或后为0,取反后为1,故不为全0),再确认加一之后的数不是0就好(由0xffffffff+1得到)。

/*
 * 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) {
   
  int overflow = x+1;
  int res = ~(overflow^x);
  return !res&!!overflow;
}

allOddBits

如果所有的奇数位都是1,则返回1;否则,返回0
注意只说了奇数位都要求为1,没规定偶数位的取值,所以先把奇数位提取出来,再和0xaaaaaaaa(奇数位全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 a = 0xaa;
  int a_8 = a<<8;//0x0000aa00
  int  low_16  = a|a_8;//0x0000aaaa;
  int high_16 = low_16<<16;//0xaaaa0000
  int num = low_16 | high_16;//0xaaaaaaaa
  int check = (x&num)^num;
  //如果check是0 则满足要求 返回1
  return !check;
}

negate

实现取反,补码的定义,注意正数取反再加一也等于对应负数,而不只是负数取反再加一等于对应正数。

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

isAsciiDigit

如果x在大于等于0x30且小于等于0x39就返回1;否则,返回0.
思路是用减法(或者说加上负数),需要注意的是,为了统一最高的符号位所做的一点小改动。

/* 
 * 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) {
   
  int neg_30 = ~0x30+1;
  int neg_3a = ~0x3a+1;
  int res1 = (x+neg_30)>>31; //大于等于0x30则为全0 否则全1
  int res2 = (x+neg_3a)>>31;//小于等于0x39则为全1 否则全0
  int res = ~res1&res2;//符合为全1 否则全0
  return !!res;//注意第二个取反时用的是3a不是39,因为这样统一了小于等于的符号
}

conditional

实现类似三目运算符 x ? y : z
先对x取两次非,赋值给check,这样就得到了逻辑值(如果x是0,那两次非之后还是0;如果是非0,那两次非之后是1);第二行的先把check左移31位再右移31位是为了得到0x00000000或者0x11111111,注意有符号的数右移是逻辑的;最后再用(check&y) | ((~check)&z)取出想要的部分。

/* 
 * 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) {
   
    int check = !!x;//化为逻辑值
    check = (check<<31)>>31;//x为0时 check为0 否则check为0xffffffff 注意右移是逻辑的
    return (check&y) | ((~check)&z);
}

isLessOrEqual

题目就是返回x小于等于y的真假
分为判断等于和判断小于两块,判断等于还是用异或,而判断小于有些麻烦:先观察两者符号位,如果x与y的符号位相同,那么就用减法(加相反数),这保证了不会溢出;如果符号位不同,那么虽然因为可能溢出不能用前一种方法,但是可以直接判断出x是否小于y,只有x的符号位是1,且y的符号位是0时才小于。具体细节下面代码有注释。

/* 
 * 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) {
   
  int equal_flag = ! (x^y);//相等为1 否则为0
  
  int x_highest = x>>31;
  int y_highest = y>>31;
  int same_highest = x_highest^y_highest;//同号全0 否则全1
  int x1_y0 = !!x_highest & !y_highest;//在x的最高位为1 且y的最高位为0时为1 否则为0 这是考虑了溢出

  int neg_y = ~y+1;
  int x_min_y = x+neg_y;
  int hightest_bit = x_min_y>>31;//若小于则为全1 否则全0
  hightest_bit = !!hightest_bit;//若小于则为1 否则0
  return equal_flag | (~same_highest
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值