第一次实验

本文详细介绍了一系列位操作函数的实现方法,包括按位与、按位非、复制最低有效位等,通过具体示例展示了如何利用位操作解决实际问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目和解答都在代码里:

/*
 * CS:APP Data Lab
 *
 * bits.c - Source file with your solutions to the Lab.
 *          This is the file you will hand in to your instructor.
 *
 */
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "tests.h"
/*
 * Instructions to Students:
 *
 * STEP 1: Fill in the following struct with your identifying info.
 */

#if 0
/*
 * STEP 2: Read the following instructions carefully.
 */

You will provide your solution to the Data Lab by
editing the collection of functions in this source file.

CODING RULES:

  Replace the "return" statement in each function with one
  or more lines of C code that implements the function. Your code
  must conform to the following style:

  int Funct(arg1, arg2, ...) {
      /* brief description of how your implementation works */
      int var1 = Expr1;
      ...
      int varM = ExprM;

      varJ = ExprJ;
      ...
      varN = ExprN;
      return ExprR;
  }

  Each "Expr" is an expression using ONLY the following:
  1. Integer constants 0 through 255 (0xFF), inclusive. You are
      not allowed to use big constants such as 0xffffffff.
  2. Function arguments and local variables (no global variables).
  3. Unary integer operations ! ~
  4. Binary integer operations & ^ | + << >>

  Some of the problems restrict the set of allowed operators even further.
  Each "Expr" may consist of multiple operators. You are not restricted to
  one operator per line.

  You are expressly forbidden to:
  1. Use any control constructs such as if, do, while, for, switch, etc.
  2. Define or use any macros.
  3. Define any additional functions in this file.
  4. Call any functions.
  5. Use any other operations, such as &&, ||, -, or ?:
  6. Use any form of casting.

  You may assume that your machine:
  1. Uses 2s complement, 32-bit representations of integers.
  2. Performs right shifts arithmetically.
  3. Has unpredictable behavior when shifting an integer by more
     than the word size.

EXAMPLES OF ACCEPTABLE CODING STYLE:
  /*
   * pow2plus1 - returns 2^x + 1, where 0 <= x <= 31
   */
  int pow2plus1(int x) {
     /* exploit ability of shifts to compute powers of 2 */
     return (1 << x) + 1;
  }

  /*
   * pow2plus4 - returns 2^x + 4, where 0 <= x <= 31
   */
  int pow2plus4(int x) {
     /* exploit ability of shifts to compute powers of 2 */
     int result = (1 << x);
     result += 4;
     return result;
  }
#endif

/*
 * STEP 3: Modify the following functions according the coding rules.
 *
 */
/* NO:1
 * bitAnd - x&y using only ~ and |
 *   Example: bitAnd(6, 5) = 4
 *   Legal ops: ~ |
 *   Max ops: 8
 *   Rating: 1
 */
int bitAnd(int x, int y) {
  return ~((~x)|(~y));
}

/* NO:2
 * bitNor - ~(x|y) using only ~ and &
 *   Example: bitNor(0x6, 0x5) = 0xFFFFFFF8
 *   Legal ops: ~ &
 *   Max ops: 8
 *   Rating: 1
 */
int bitNor(int x, int y) {
  return (~x)&(~y);
}
/* NO:3
 * copyLSB - set all bits of result to least significant bit of x
 *   Example: copyLSB(5) = 0xFFFFFFFF, copyLSB(6) = 0x00000000
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int copyLSB(int x) {
  return (x<<31)>>31;
}
/* NO:4
 * evenBits - return word with all even-numbered bits set to 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 2
 */
int evenBits(void) {
  int x=0x55;
  int result=0;
  result|=x;
  result|=x<<8;
  result|=x<<16;
  result|=x<<24;
  return result;
}
/* NO:5
 * logicalShift - shift x to the right by n, using a logical shift
 *   Can assume that 1 <= n <= 31
 *   Examples: logicalShift(0x87654321,4) = 0x08765432
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 16
 *   Rating: 3
 */
int logicalShift(int x, int n) { 
  return (~((1<<31)>>(n-1)))&(x>>n);
}
/* NO:6
 * bang - Compute !x without using !
 *   Examples: bang(3) = 0, bang(0) = 1
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 12
 *   Rating: 4
 */
int bang(int x) {
  x|=x>>16;
  x|=x>>8;
  x|=x>>4;
  x|=x>>2;
  x|=x>>1;
  return (~x)&1;
}
/* NO:7
 * leastBitPos - return a mask that marks the position of the
 *               least significant 1 bit. If x == 0, return 0
 *   Example: leastBitPos(96) = 0x20
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 4
 */
int leastBitPos(int x) {
  return ((~x)+1)&x;
}
/* NO:8
 * TMax - return maximum two's complement integer
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmax(void) {
  int x=~(1<<31);
  return x;
}
/* NO:9
 * negate - return -x
 *   Example: negate(1) = -1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 5
 *   Rating: 2
 */
int negate(int x) {
  return (~x)+1;
}
/* NO:10
 * isPositive - return 1 if x > 0, return 0 otherwise
 *   Example: isPositive(-1) = 0.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 8
 *   Rating: 3
 */
int isPositive(int x) {
  return (!(x>>31))&(!!x);
}
/* NO:11
 * isNonNegative - return 1 if x >= 0, return 0 otherwise
 *   Example: isNonNegative(-1) = 0.  isNonNegative(0) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 3
 */
int isNonNegative(int x) {
  return !(x>>31);
}
/* NO:12
 * sum3 - x+y+z using only a single '+'
 *   Example: sum3(3, 4, 5) = 12
 *   Legal ops: ! ~ & ^ | << >>
 *   Max ops: 16
 *   Rating: 3
 */
/* A helper routine to perform the addition.  Don't change this code */
static int sum(int x, int y) {
  return x+y;
}
int sum3(int x, int y, int z) {
  int word1 = 0;
  int word2 = 0;
  /**************************************************************
     Fill in code below that computes values for word1 and word2
     without using any '+' operations
  ***************************************************************/
  word1=(x^y)^z;
  word2=((x&y&z)|((~word1)&(x|y|z)))<<1;
  /**************************************************************
     Don't change anything below here
  ***************************************************************/
  return sum(word1,word2);
}
/* NO:13
 * addOK - Determine if can compute x+y without overflow
 *   Example: addOK(0x80000000,0x80000000) = 0,
 *            addOK(0x80000000,0x70000000) = 1,
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3
 */
int addOK(int x, int y) {
  int t=x+y;
  int sx=x>>31;
  int sy=y>>31;
  int st=t>>31;
  return !((~(sx^sy))&(sx^st));
}
/* NO:14
 * abs - absolute value of x (except returns TMin for TMin)
 *   Example: abs(-1) = 1.
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 10
 *   Rating: 4
 */
int abs(int x) {
  int sx=x>>31;
  return (x&(~sx))|(((~x)+1)&sx);
}
/* NO:15
 * isNonZero - Check whether x is nonzero using
 *              the legal operators except !
 *   Examples: isNonZero(3) = 1, isNonZero(0) = 0
 *   Legal ops: ~ & ^ | + << >>
 *   Max ops: 10
 *   Rating: 4
 */
int isNonZero(int x) {
  return (((((~x)+1)^x)|x)>>31)&1;
}
蛋疼的实验报告,表示不会用wps

一、 函数分析

1. int bitAnd(int x, int y);

函数实现:

int bitAnd (int x, int y) {

  return ~((~x) | (~y));

}

函数分析:

由德摩根定律得:~(x & y) = (~x) | (~y) 所以:x & y = ~((~x) | (~y)) 

 

2. int bitNor (int x, int y);

函数实现:

Int bitNor(int x,int y){

return (~x)&(~y);

}

函数分析:

  由德摩根定律得:~(x|y)=(~x)&(~y)    

3. Int copyLSB(int x);

函数实现:

Int copyLSB(int x){

return (x<<31)>>31;

}

函数分析:只要注意是算术右移即可

4.Int evenBits(int x);

函数实现:

Int evenBits(int x){

 int x=0x55;

 Int result=0;

 result|=x;

 result|=x<<8;

 result|=x<<16;

 result|=x<<24;

 return result;

}

函数分析:0x5501010101,分别左移0(不移动),8,16,24位就可以将第

1,2,3,4个字节都设为01010101,即所有的偶数字节都是1

5.Int logicalShift(int x,int n);

 Int logicalShift(int x,int n){

   return (~((1<<31)>>(n-1)))&(x>>n);

 }

函数分析:1<<31产生最高为是1,其余位全是0的数,其值右移n-1位再取反得到覆盖原来x且不覆盖算术右移高位补的1的掩码,再和x>>n相与即可

    6.int bang(int x);

 int bang(int x) {

  x|=x>>16;

  x|=x>>8;

  x|=x>>4;

  x|=x>>2;

  x|=x>>1;

  return (~x)&1;

}

函数分析:首先一个数只要有1,就应该返回0,全为0返回1,那么很自然想到要将每一位相或,不过如果是一位一位地或,需要操作31次,因此想到了折半的方法,第一次移16位,那么前16位的1相当于存到了后16位和原先后16位的1并存,相当于改变了运算次序并用了结合律,依次类推。

8位二进制数为例,假设这个数位表示是a1,a2,a3,a4,a5,a6,a7,a8

第一次移4位:(15)(26)(37)(48

第二次移2位:((15)(37))((26)(48))

最后:(((15)(37))((26)(48)))

(为了方便,直接用i代表ai)

7.int leastBitPos(int x);

int leastBitPos(int x) {

  return ((~x)+1)&x;

}

函数分析:设最低位为i,那么0i-1都是0,~xx位相反,0i-1都是1,那么对(~x)+1来说,0i-1都是0,第i位是1i+131位与x相反,那么与x相与直接可得i位的掩码

8.int tmax(void);

int tmax(void) {

  return ~(1<<31);

}

函数分析:INT_MAX就是除了第32位是0,其余都是1的数

9.int negate(int x);

int negate(int x) {

  return (~x)+1;

}

函数分析,即求补码,也就是求反加1

10.int isPostive(int x);

int isPositive(int x) {

  return (!(x>>31))&(!!x);

}

函数分析:由于最高位是符号位,!(x>>31)1时,x>=0,0时,为0时,x<0;现在要排除x=0的情况,只有x!=0时,!!x=1,因此两式相与即可

11.int isNonNegative(int x);

int isNonNegative(int x) {

  return !(x>>31);

}

函数分析:同上

12.static int sum(int x, int y);

static int sum(int x, int y) {

  return x+y;

}

int sum3(int x, int y, int z) {

  int word1 = 0;

  int word2 = 0;

      word1=(x^y)^z;

      word2=((x&y&z)|((~word1)&(x|y|z)))<<1;

      return sum(word1,word2);

}

函数分析:思路是先做一次不进位的加法,然后用sum把进位加上去。

x^y^z相当于是不进位加法,下面对某一位分析进位:当x,y,z中有两个或三个1时产生进位,这时令相应的位为1,最后左移1位相加即可。x&y&z是三个都是1的情况,~word1021x|y|z是至少有一个1,这样就判断了进位

13.int addOK(int x, int y);

int addOK(int x, int y) {

  int t=x+y;

  int sx=x>>31;

  int sy=y>>31;

  int st=t>>31;

  return !((~(sx^sy))&(sx^st));

}

函数分析:sx表示用x的符号位填满32位,y,z一样,函数应当在x,y同号但x+yx异号时返回0,否则返回1

14.int abs(int x);

int abs(int x) {

  int sx=x>>31;

  return (x&(~sx))|(((~x)+1)&sx);

}

函数分析:函数在x>0x=TMIN时返回x,在x<0x!=TMIN)时返回-x(即取反加1),那么需要用符号位来控制两者只有一个被返回

15.int isNonZero(int x)

int isNonZero(int x) {

  return (((((~x)+1)^x)|x)>>31)&1;

}

函数分析:(((~x)+1)^x)|x得到从最低的1位到32位全是1其余全是0的数(对于0来说是全0),那么右移31位让其最高位与1相与即可



### 南京邮电大学汇编语言第一次实验 #### 实验目的 通过本次实验,学生能够掌握基本的汇编语言语法结构以及如何利用集成开发环境(IDE)编写简单的汇编程序。此外,在初次接触单片机系统的背景下,了解其内部工作原理并熟悉调试工具的应用。 #### 实验内容概述 首次实验主要集中在基础概念的学习与实践操作上。具体来说: - **安装配置Keil IDE**:确保每位同学都能顺利打开软件,并完成必要的设置以便后续项目创建和代码编辑[^2]。 - **简单指令集练习**:编写一段用于验证数据传输功能的小型程序,比如实现两个寄存器之间数值交换的操作;这有助于加深对CPU执行过程的理解[^1]。 ```assembly ; Example of swapping two registers in assembly language MOV A, R0 ; Move value from register R0 to accumulator A XCHG A, R1 ; Exchange values between accumulator and another register (R1 here) MOV R0, A ; Store the exchanged result back into original source location ``` - **初步认识存储空间布局**:通过对特定地址范围内的读写测试来探索不同类型的内存区域及其访问方式,如RAM、ROM等特性差异。 #### 报告撰写指南 一份完整的实验报告应当包含以下几个部分: - 封面页注明个人信息及课题名称; - 正文开头简述此次学习目标和个人收获感言; - 中间主体段落详细介绍所做工作的具体内容,包括但不限于遇到的问题解决方案描述; - 结尾处总结整个过程中学到的知识要点,并对未来可能继续深入研究的方向给出建议。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值