CSAPP:Datalab

The first ICS lab is
equipped with VMWare and Linux systems
. After two days
of silent "I'm going to die", I finally finished writing. I'm not very satisfied (especially howManyBits...), but at least I got it out...?
First record your thoughts, I hope you can Optimize howManyBits before ddl


Initial submission result:Insert picture description here

Yes, the 81-step brute force algorithm?


 
The int part of Datalab cannot use loops and conditions, and can only be implemented by bit operations

Very simple two:
bitXor&tmin

/* 
 * 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 mark=(~x)&(~y);/*identify the 0&0 occasion*/
  return ~(x&y)&(~mark);
}
/* 
 * tmin - return minimum two's complement integer 
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 4
 *   Rating: 1
 */
int tmin(void) {
    
    
  return 1<<31;
}

 
Tmax is
stuck with my Tmax. I don’t know why I used int temp=x+1 to report an error... I
used Xcode to run the temp version and the result was correct... The teaching assistant could not help me...

  • The reason is unknown so far, but I will understand later (maybe it is a bug??
/*
 * 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 (!(x+2+x))&(!!(x+1));
}

 
allOddBits
tried to simplify allOddBits, but failed...
but there were fewer operands

/* 
 * 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 temp=0xAA+(0xAA<<8)+(0xAA<<16)+(0xAA<<24);
  return !((temp&x)^temp);
}

 
negate
the one that is no problem

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

 
I’ve been
thinking about isAsciiDigit for a long time, but the logic is still very clear. I
learned to use & to control the output conditions (used to exclude negative situations)

/* 
 * 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 x1=!((x>>4)^0x3),x2=!(((x&0xF)+0x6)&0x10);
  return x1&x2;
}

 

The idea of conditional was there at the beginning, but there were too many operations. I
learned from the writing of the Internet bosses, and finally simplified it to the least

/* 
 * 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 temp=(~0)+!x;
  return (temp&y)+(~temp&z);
}

 
isLessOrEqual
has a reference, learned &, | methods to control the results (very useful

  • The best way to write less to learn
/* 
 * 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 minus=x+(~y+1);
return(((minus>>31)&1)|(!(x^y))|(((x>>31)&1)&(!((y>>31)&1))))&(!(!((x>>31)&1)&((y>>31)&1)));
}

 
LogicalNeg
is a modified idea, only 0 will the sign bit of x and -x are both 0, to judge

/* 
 * 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) {
    
    
  int neg=(~x)+1,temp=1<<31;
  return ((~((neg&temp)|(x&temp)))>>31)&0x1;}

 
howManyBits
brute force algorithm it coming?
can only be converted to positive numbers first calculate the bit, and then depending on the conditions (a power of 2 -1 negative, because the first place can act as a symbol position) addition and subtraction
to learn the idea of big brother, with x^(x-1) judge whether it is a power of 2 and
look for new ideas in the past few days, hoping to succeed~

/* howManyBits - return the minimum number of bits required to represent x in
 *             two's complement
 *  Examples: howManyBits(12) = 5
 *            howManyBits(298) = 10
 *            howManyBits(-5) = 4
 *            howManyBits(0)  = 1
 *            howManyBits(-1) = 1
 *            howManyBits(0x80000000) = 32
 *  Legal ops: ! ~ & ^ | + << >>
 *  Max ops: 90
 *  Rating: 4
 */
int howManyBits(int x)
{
    
    
    int temp=24,judge=0,x1=0,n=0,sign=x&(1<<31),xpos=((sign>>31)&(~x+1))+((~sign>>31)&x),t=0,zero=0,m=0,x2=0;
    judge=!(xpos>>24);temp+=(~(judge<<3)+1);
    judge=!(xpos>>16);temp+=(~(judge<<3)+1);
    judge=!(xpos>>8);temp+=(~(judge<<3)+1);
    x2=x1=((0xff<<temp)&xpos)>>temp;
    x1^=(x1<<1);
n+=(!!x1)+(!!(x1>>1))+(!!(x1>>2))+(!!(x1>>3))+(!!(x1>>4))+(!!(x1>>5))+(!!(x1>>6))+(!!(x1>>7));
    t=(!((xpos+(~0))&xpos))&(sign>>31);
    zero=!x;
    m=!!((x2&0xFF)&0x80);
    return n+temp+(~t+1)+m+zero;
}

The float part is written quite smoothly, and the loop condition is used to solve the
floatScale2 & floatFloat2int & floatPower2. The
focus is on considering the choice between infinity and overflow.

/* 
 * floatScale2 - Return bit-level equivalent of expression 2*f for
 *   floating point argument f.
 *   Both the argument and result are passed as unsigned int's, but
 *   they are to be interpreted as the bit-level representation of
 *   single-precision floating point values.
 *   When argument is NaN, return argument
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned floatScale2(unsigned uf) {
    
    
    unsigned e=0x7F800000&uf,m=0x7FFFFF&uf;
    if(!e) return (m<<1)|(uf&(0x1<<31));
    if(e!=0x7F800000) return (0x800000+uf);
    return uf;
}
/* 
 * floatFloat2Int - Return bit-level equivalent of expression (int) f
 *   for floating point argument f.
 *   Argument is passed as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point value.
 *   Anything out of range (including NaN and infinity) should return
 *   0x80000000u.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
int floatFloat2Int(unsigned uf) {
    
    
    int i=1,num1=0,sum=0,exp=1;
    unsigned s=0x80000000&uf,e=(0x7F800000&uf)>>23,m=0x7FFFFF&uf;
    num1=e-127;
    if(e>158) return 0x80000000u;
    if(e<127)  return 0;
    for(i=0;i<num1;i++)
    exp*=2;
    sum=(s?(-1):1)*exp;
    if(!m) return sum;
    else if(m&0x400000)
    {
    
    
        if(m^0x400000) return !(sum%2)?sum:sum+1;
        else return sum+1;
    }
    else return sum;
}
/* 
 * floatPower2 - Return bit-level equivalent of the expression 2.0^x
 *   (2.0 raised to the power x) for any 32-bit integer x.
 *
 *   The unsigned value that is returned should have the identical bit
 *   representation as the single-precision floating-point number 2.0^x.
 *   If the result is too small to be represented as a denorm, return
 *   0. If too large, return +INF.
 * 
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while 
 *   Max ops: 30 
 *   Rating: 4
 */
unsigned floatPower2(int x) {
    
    
    int e=x+127,exp=0,result=0;
    exp=(e>=0)?e:(-e);
    if(x>127) return 0x7F800000;
    if(x<-256) return 0x0;
    if(x==-256) return 0x40000000;
    else{
    
    result=(exp<<23);return result;}
}

Finally, attach the referenced information:
Basic operation: https://blog.csdn.net/greatljc/article/details/97194030
I am very desperate to just get started with the Linux terminal... Will the preparation work be better after reading this?

The configuration of the 32-bit compilation environment:
https://blog.csdn.net/gezhiwu1213/article/details/78564455
Linux is equipped with 64-bit, but this program seems to be 32-bit running. The
card has been stuck for a long time...
If it is not configured, it cannot be detected. Delay problem, you can change -m32 in makefile to -m64


Here’s an update...but there are still many big guys in the class~

Insert picture description here
howManyBits 2.0

int howManyBits(int x) {
    
    
int n = 0;
  x^=(x<<1);//to locate the 1st left 1
  n+=((!!(x&((~0)<<(n+16)))) << 4);//find the 1st left 1
  n+=((!!(x&((~0)<<(n+8)))) << 3);
  n+=((!!(x&((~0)<<(n+4)))) << 2);
  n+=((!!(x&((~0)<<(n+2)))) << 1);
  n+=(!!(x&((~0)<<(n+1))));
return n+1;
}

Guess you like

Origin blog.csdn.net/Rachel_IS/article/details/102482872