150 likes | 158 Views
Learn about representing information as bits, binary/hexadecimal systems, byte representations, numbers, characters and strings, bit-level operations in C, and more.
E N D
Bits and Bytes COMP 21000 Comp Org & Assembly Lang Topics • Why bits? • Representing information as bits • Binary / Hexadecimal • Byte representations • Numbers • Characters and strings • Instructions • Bit-level manipulations • Boolean algebra • Expressing in C
Bit-Level Operations in C Operations &, |, ~, ^ Available in C • Apply to any “integral” data type • long, int, short, char, unsigned • View arguments as bit vectors • Arguments applied bit-wise Examples (Char data type) • ~0x41 --> 0xBE ~010000012 --> 101111102 • ~0x00 --> 0xFF ~000000002 --> 111111112 • 0x69 & 0x55 --> 0x41 011010012 & 010101012 --> 010000012 • 0x69 | 0x55 --> 0x7D 011010012 | 010101012 --> 011111012
Contrast: Logic Operations in C Contrast to Logical Operators • &&, ||, ! • View 0 as “False” • Anything nonzero as “True” • Always return 0 or 1 • Early termination Examples (char data type) • c = ‘A’ then !c is !0x41 --> 0x00 • c = ‘\0’ then !c is !0x00 --> 0x01 • c = ‘A’ the !!c is !!0x41 --> 0x01 • 0x69 && 0x55 --> 0x01 • 0x69 || 0x55 --> 0x01 • p && *p++ (avoids null pointer access) • Or p && (*p = 10) also protects Works because of short-circuit evaluation in C
Shift Operations Left Shift: x << y • Shift bit-vector x left y positions • Throw away extra bits on left • Fill with 0’s on right Right Shift: x >> y • Shift bit-vector x right y positions • Throw away extra bits on right • Logical shift • Fill with 0’s on left • Arithmetic shift • Replicate most significant bit on right • Useful with two’s complement integer representation Argument x 01100010 << 3 00010000 00010000 00010000 Log. >> 2 00011000 00011000 00011000 Arith. >> 2 00011000 00011000 00011000 Argument x 10100010 << 3 00010000 00010000 00010000 Log. >> 2 00101000 00101000 00101000 Arith. >> 2 11101000 11101000 11101000 Which right shift does C do? Depends on the compiler! Often: int do ASR While unsign does LSR
Effect of LSL Each shift doubles the number. If the carry bit is 1 after a shift, then overflow (if the number is unsigned). Decimal: shift multiplies by 10. 35 << 350 Binary: 0 1 0 1 0 = 1 x 23 + 0 x 22 + 1 x 21 + 0 x 20 1 0 1 0 0 = 1 x 24 + 0 x 23 + 1 x 22 + 0 x 21+ 0 x 20 = 2 x (1 x 23 + 0 x 22 + 1 x 21 + 0 x 20)
Effect of LSR Each shift halves the number. Round down (because you drop the least significant bit) Decimal: shift divides by 10. 350 >> 35 Binary: 1 0 1 0 0 = 1 x 24 + 0 x 23 + 1 x 22 + 0 x 21+ 0 x 20 0 1 0 1 0 = 1 x 23 + 0 x 22 + 1 x 21 + 0 x 20 = (1 x 24 + x 23 + 0 x 22 + 1 x 21 + 0 x 20) ÷ 2
Truncating Casting to a shorter form truncates the number. int x = 53191; short sx = (short) x; /* -12345 */ int y = sx; /* -12345*/ On a typical 32-bit machine: • Casting int to short truncate 32-bit to 16-bits • When cast back to 32 bits, do sign extension (see next lecture) so value doesn’t change.
Masks Can use bit patterns as masks Example Mask = 0xFFFFFF00 when used with the ‘&’ operator filters out (i.e., zeros out) the last byte Mask = 0x000000FF when used with the ’ |’ operator places 1’s in the last byte, rest is unaffected.
Masks note that we can assign hex values to an integer. Just another way of representing int! Can use bit patterns as masks Example int x = 0xFFFFFFF0; // this will be the mask. int y = 31; // this is stored as 0…011111 int z = y & x; // z now contains 16 or 0…010000
Masks note that we can assign hex values to an integer. Just another way of representing int! Can use bit patterns as masks Example int x = 0x0000000F; // this will be the mask. int y = 16; // this is stored as 0…010000 int z = y | x; // z now contains 31 or 0…011111
Masks Can perform a mod by a power of 2 with a mask Examples: x % 2 = 0 (x is even) or 1 (x is odd) 1111 = 1 x 23 + 1 x 22 + 1 x 21 + 1 x 20 : all places except the last are divisible by 2. So if the last bit is 0, mod is 0. If last bit is 1, mod is 1 x % 4 1111 = 1 x 23 + 1 x 22 + 1 x 21 + 1 x 20 : all places except the last two are divisible by 4. So if the last two bits are 0, mod is 0. Otherwise the mod is whatever value the last two bits have
Masks Can perform a mod by a power of 2 with a mask Examples: x % 8 = 0 1111 = 1 x 23 + 1 x 22 + 1 x 21 + 1 x 20 : all places except the last three are divisible by 8. So if the last three bits are 0, mod is 0. . Otherwise the mod is the value in the last three bits so x % 2 == x & 00000001 (or 0x01) x % 4 == x & 00000011 (or 0x03) x % 8 == x & 00000111 (or 0x07)
Converting (revisited) #include <stdlib.h> #define LOWDIGIT 07 #define DIG 20 void octal_print(register int x) { register inti = 0; char s[DIG]; if ( x < 0 ){ /* treat negative x */ putchar ('-'); /* output a minus sign */ x = - x; } do{ /* mod performed with & */ s[i++] = ((x & LOWDIGIT) + '0'); } while ( ( x >>= 3) > 0 ); /* divide x by 8 via shift */ putchar('0'); /* octal number prefix */ do{ putchar(s[--i]); /* output characters on s */ } while ( i > 0 ); putchar ('\n'); }
Converting to binary void printBits(unsigned int word, int nBits){ for (int i=nBits-1;i>=0;i--){ printf("%u", !!(word&(1<<i))); } printf("\n"); }
A^B B A^B (A^B)^B = A (A^B)^A = B A B A Cool Stuff with Xor • Bitwise Xor is form of addition • With extra property that every value is its own additive inverse A ^ A = 0 void funny(int *x, int *y) { *x = *x ^ *y; /* #1 */ *y = *x ^ *y; /* #2 */ *x = *x ^ *y; /* #3 */ } *x *y Begin A B 1 2 3 End