"CSAPP" Experiment 1: Bit manipulation

"CSAPP" known programmer Bible, although Chinese translation for "in-depth understanding of computer systems", but in fact is not so "deep", but coverage is very broad, commonly used as a freshman computer science textbook introduction course. Supporting long heard of the book is a classic experiment, this time to review the new (third edition), intends to do about all of the experiments, also wrote a series of blog posts good record during the experiment. Experiments can book companion Web site CSAPP: Lab Assignments downloaded from this first experiment - Start bit operation.

Outline

This experiment was chapter "indicates processing information" supporting experiments, requires the use of a subset of C language implementation specific height restriction logic, integers, floating point functions. Continue to use the argument of the first chapter, information is context-bit addition, computer system all information is represented by a series of bits (or a string of binary digits), the second chapter stresses the C language integer and floating-point numbers encoding, i.e. typically using a computer how a series of bits used to represent the integer and floating point:

  • Unsigned integer: straight binary coding
  • Signed integer: twos complement, MSB negative right
  • Float: the IEEE 754

Also removed from the memory 4 bytes \ (0x80000000 \) , to see it as an unsigned integer, that is, \ (2147483648 \) ; to see it as a signed integer, is \ (- 2147483648 \) ; it as a single precision floating point of view, is \ (- 0 \) . The so-called context, is the interpretation of this bit string of ways, cross as a peak. It is noteworthy that, although in almost all systems, C language integer and floating-point numbers are encoded so, but the C language standard itself does not have such a requirement, do not know their lifetime can encounter non-mainstream encoding.
If you do not fully grasp bit operating encoding and C language of these numbers, it is certainly not a complete experiment of. Experiment one is nice because you will repeatedly recall the basics, deep into the details of the experiments done to forget forget :)

premise

Despite the standard C language, but in the case Undefined Behavior or too much, especially for deep underlying bit operation, so the preset test: 32-bit signed integer using twos complement coding; displacement arithmetic right shift operation, high up the sign bit. Experiments also requires: macro can not be used; the use of a constant operation is not greater than an integer of 0xFF. Here's a by-function recording experiment.

bITAND

Use ~and |implement &, there is a very simple formula, but remember, the auxiliary thinking map with Wayne: The Complete Works indicates that all bits are 1, xand yrepresent a specific location for a child 1 set, imagine ~, |and &Wayne map, click on the launch of the sub-formulas.

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

getByte

xRight n * 8position, the last byte can be taken by the n * 8 == n << 3.

/*
 * getByte - Extract byte n from word x
 *   Bytes numbered from 0 (LSB) to 3 (MSB)
 *   Examples: getByte(0x12345678,1) = 0x56
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 6
 *   Rating: 2
 */
int getByte(int x, int n) {
    return (x >> (n << 3)) & 0xFF;
}

logicalShift

Experimental preset arithmetic shift to the right, then to xthe right nposition and then the mask will fill the high nposition to 0.

/*
 * logicalShift - shift x to the right by n, using a logical shift
 *   Can assume that 0 <= n <= 31
 *   Examples: logicalShift(0x87654321,4) = 0x08765432
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 20
 *   Rating: 3
 */
int logicalShift(int x, int n) {
    int mask = ~(((1 << 31) >> n) << 1);
    return (x >> n) & mask;
}

bitCount

This title like a long time, the idea is to normal xbit by bit to the right, take the lowest position with 1 mask, and then sum, however, exceeded the number of operators: D Then think of using x & 1to check xlast bit is 1 if Comparative loss, can be used x & 0x00010001, so that one can check two, front and rear final 16-bit result can be summarized, however, the number is exceeded operator: D the final xpoints of the 8 groups x & 0x11111111, each inspection 8, with 38 operator, finally reached. This is the largest number of all the problems with operators of a problem.

/*
 * bitCount - returns count of number of 1's in word
 *   Examples: bitCount(5) = 2, bitCount(7) = 3
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 40
 *   Rating: 4
 */
int bitCount(int x) {
    int mask = 0x11 + (0x11 << 8) + (0x11 << 16) + (0x11 << 24);

    int count = (x & mask) + ((x >> 1) & mask) +
        ((x >> 2) & mask) + ((x >> 3) & mask);

    return (count & 7) + ((count >> 4) & 7) + ((count >> 8) & 7) +
        ((count >> 12) & 7) + ((count >> 16) & 7) + ((count >> 20) & 7) +
        ((count >> 24) & 7) + ((count >> 28) & 7);
}

bang

Want to start making a fuss 0 above, after all, only bang(0) = 1, but that being the case. |Operation, dichotomy, gradually collected into a high-order low, such as x = x | (x >> 16), if the high-order 16-bit words. 1, the lower will be collected on a 16-bit, so-half, the last one collected, just 12 operating symbol.

/*
 * 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 | (x >> 16);
    x = x | (x >> 8);
    x = x | (x >> 4);
    x = x | (x >> 2);
    x = x | (x >> 1);
    return ~x & 1;
}

tmin

The simplest one question, to be familiar with two's complement.

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

fitsBits

If xnon-negative, taking into account the nmaximum non-bit two's complement negative number can be expressed as $ 0b0111 ... 111 $ (total n-1number 1), by masking the xlower bits n-1position 0, the upper check 32 - (n - 1)bits is 0 can be. If xnegative, it first to non-negative ~x, encoding ~xthe required encoding bits xare the same.

/*
 * fitsBits - return 1 if x can be represented as an
 *  n-bit, two's complement integer.
 *   1 <= n <= 32
 *   Examples: fitsBits(5,3) = 0, fitsBits(-4,3) = 1
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 2
 */
int fitsBits(int x, int n) {
    int minusOne = ~0;
    int mask = minusOne << (n + minusOne);
    return !((x ^ (x >> 31)) & mask);
}

divpwr2

x >> nThat is, \ (\ lfloor X / 2 ^ n-\ rfloor \) , the result is rounded down, but the problem requires rounding to 0, if the xnon-negative rounding down to 0 i.e. no problem rounding, if xas negative, need to xa plus offset value \ (n-2 ^ -. 1 \) , such that the x >> nrounding up.

/*
 * divpwr2 - Compute x/(2^n), for 0 <= n <= 30
 *  Round toward zero
 *   Examples: divpwr2(15,1) = 7, divpwr2(-33,4) = -2
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 15
 *   Rating: 2
 */
int divpwr2(int x, int n) {
    int signBit = (x >> 31) & 1;
    int bias = (signBit << n) + (~signBit + 1);
    return (x + bias) >> n;
}

negate

n-bit twos complement range is \ ([- ^ {n-2}. 1, \ ^ {n-2}. 1 -. 1] \) , is not symmetric about 0, so that when xwhen the minimum value -xis its own .

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

isPositive

Positive sign bit is the sign bit is 0 0,0, is a special case.

/*
 * 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) & (!(x >> 31));
}

isLessOrEqual

isLessOrEqualEquivalent to !isGreaterrealize isGreatera simple point: If the x ydifferent number, it xmust be non-negative ymust be negative; if x ythe same number, x - ywill not overflow, there must be x - y > 0, i.e. x - y - 1 >= 0, i.e. x + ~y >= 0, checks x + ~ythe sign bit.

/*
 * 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 xSign = x >> 31;
    int ySign = y >> 31;

    int hasSameSign = !(xSign ^ ySign);
    int diffSign = (x + ~y) >> 31;

    int isXPosYNeg = (!xSign) & ySign;
    int isGreater = isXPosYNeg | (hasSameSign & !diffSign);

    return !isGreater;
}

ilog2

This question allows the operator 90 is the number of all the questions the operator the most relaxed. ilog2The essence is to strive xindex of the highest bit 1, if xa high of 16, 1, and leave the low-order 16-bit; if xa high of 8 and 1, then do not control the low of 24, and so on. Implement or very clever :)

/*
 * ilog2 - return floor(log base 2 of x), where x > 0
 *   Example: ilog2(16) = 4
 *   Legal ops: ! ~ & ^ | + << >>
 *   Max ops: 90
 *   Rating: 4
 */
int ilog2(int x) {
    int high16, high8, high4, high2, high1;

    high16 = (!!(x >> 16)) << 4;
    x = x >> high16;

    high8 = (!!(x >> 8)) << 3;
    x = x >> high8;

    high4 = (!!(x >> 4) << 2);
    x = x >> high4;

    high2 = (!!(x >> 2) << 1);
    x = x >> high2;

    high1 = !!(x >> 1);
    return high1 + high2 + high4 + high8 + high16;
}

float_neg

And finally to float, and floating-point problem of operator requirements relaxed a little, you can also use recycled with the judgment statement. The first question, as long as IEEE754 familiar with on the line.

/*
 * float_neg - Return bit-level equivalent of expression -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 representations of
 *   single-precision floating point values.
 *   When argument is NaN, return argument.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 10
 *   Rating: 2
 */
unsigned float_neg(unsigned uf) {
    int isNaN = (((uf >> 23) & 0xFF) == 0xFF) && (uf << 9);
    return isNaN ? uf : ((1 << 31) ^ uf);
}

float_i2f

No skills, very violent. From the symbol bit exponent, the mantissa, the rounding, one by one. Note that float(x)is the even rounding.

/*
 * float_i2f - Return bit-level equivalent of expression (float) x
 *   Result is returned as unsigned int, but
 *   it is to be interpreted as the bit-level representation of a
 *   single-precision floating point values.
 *   Legal ops: Any integer/unsigned operations incl. ||, &&. also if, while
 *   Max ops: 30
 *   Rating: 4
 */
unsigned float_i2f(int x) {
    unsigned sign = x & (1 << 31);
    unsigned exp = 0;
    unsigned frac = 0;
    unsigned round = 0;

    unsigned absX = sign ? (~x + 1) : x;
    unsigned tmp = absX;
    while ((tmp = tmp >> 1))
        ++exp;

    frac = absX << (31 - exp) << 1;
    round = frac << 23 >> 23;
    frac = frac >> 9;

    if (round > 0x100) round = 1;
    else if (round < 0x100) round = 0;
    else round = frac & 1;

    return x ? (sign | ((exp + 0x7F) << 23) | frac) + round : 0;
}

float_twice

Still very violent, according to a floating-point number to a classification: special value, returned directly; normalized floating-point number, order number plus 1; non-standardized, the left one and keep the sign bit unchanged.

/*
 * float_twice - 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 float_twice(unsigned uf) {
    unsigned sign = 1 << 31;
    unsigned isNormalized = uf << 1 >> 24;
    unsigned isSpecial = isNormalized == 0xFF;

    if (isSpecial || uf == 0 || uf == sign)
        return uf;

    if (isNormalized)
        return uf + (1 << 23);

    return (uf << 1) | (uf & sign);
}

Guess you like

Origin www.cnblogs.com/my-tiga/p/12076604.html