2.2: Bitwise Logical Operations Topics: Introduction: logical operations in C/C++ logical operations in MIPS In 256 lecture, we looked at bitwise operations in C/C++ and MIPS. We ll look at some simple programs to illustrate these operations in this exercise. Steps: Earlier, we copied logical.cc from the instructor s directory: /* logical.cc: demonstrates bitwise logical operations in C/C++ */ #include <iostream> using namespace std; int main() { int x = 0x456789ab, y = 0x9abcdef0, z; int w1 = 0xaaaaaaaa; unsigned int w2 = 0xaaaaaaaa; cout << "x = " << hex << x << " y = " << hex << y << endl; z = ~x; cout << "~x = " << hex << z << endl; z = x & y; cout << "x & y = " << hex << z << endl; z = x y; cout << "x y = " << hex << z << endl; z = x ^ y; cout << "x ^ y = " << hex << z << endl; cout << "\nw1 = " << hex << w1 << " w2 = " << w2 << endl; z = w1 << 3; cout << "w1 << 3 = " << hex << z << endl; z = w1 >> 3; CSc 256 Lab Manual 1
cout << "w1 >> 3 = " << hex << z << endl; z = w2 >> 3; cout << "w2 >> 3 = " << hex << z << endl; } All it does is perform some logical operations and print the results. Let s compile and run it: unixlab% g++ logical.cc -o logical unixlab%./logical x = 456789ab y = 9abcdef0 ~x = ba987654 x & y = 2488a0 x y = dfffdffb x ^ y = dfdb575b w1 = aaaaaaaa w2 = aaaaaaaa w1 << 3 = 55555550 w1 >> 3 = f5555555 w2 >> 3 = 15555555 unixlab% Let s go through the results and make sure we understand how the operations work. x is initialized to 0x456789ab, which in binary is 0100 0101 0110 0111 1000 1001 1010 1011 y is initialized to 0x9abcdef0, which in binary is 1001 1010 1011 1100 1101 1110 1111 0000 ~x means the bitwise not of x. We complement each bit of x to get ~x = 1011 1010 1001 1000 0111 0110 0101 0100 In hexadecimal, this is 0xba987654, which agrees with what the program printed. x & y means the bitwise and of x and y: x & y = 0000 0000 0010 0100 1000 1000 1010 0000 In hexadecimal, this is 0x002488a0, which agrees with what the program printed. (Leading zeros are usually not printed.) CSc 256 Lab Manual 2
x y means the bitwise or of x and y: x y = 1101 1111 1111 1111 1101 1111 1111 1011 In hexadecimal, this is 0xdfffdffb, which agrees with what the program printed. x ^ y means the bitwise xor of x and y: x ^ y = 1101 1111 1101 1011 0101 0111 0101 1011 In hexadecimal, this is 0xdfdb575b, which agrees with what the program printed. Finally, we come to the shift operations. w1 and w2 are both initialized to 0xaaaaaaaa, except w1 is a signed int and w2 is an unsigned int. 0xaaaaaaaa in binary is 1010 1010 1010 1010 1010 1010 1010 1010 w1 << 3 means w1 shift left 3 bits: w1 << 3 = 0101 0101 0101 0101 0101 0101 0101 0000 In hexadecimal, this is 0x55555550, which agrees with what the program printed. w1 >> 3 means w1 shift right 3 bits; since w1 is a signed int, the sign bit is extended: w1 >> 3 = 1111 0101 0101 0101 0101 0101 0101 0101 In hexadecimal, this is 0xf5555555, which agrees with what the program printed. w2 >> 3 means w2 shift right 3 bits; since w2 is an unsigned int, bits of zero are padded into the most significant bits: w2 >> 3 = 0001 0101 0101 0101 0101 0101 0101 0101 In hexadecimal, this is 0x15555555, which agrees with what the program printed. Logical.s is the MIPS version of logical.c. Since spim does not allow us to print integers in hexadecimal, we'll use the print command in spim to show integers in hex. # logical.s: demonstrates bitwise logical operations in MAL.data CSc 256 Lab Manual 3
.text.globl bk main: li $s0, 0x456789ab li $s1, 0x9abcdef0 li $s2, 0xaaaaaaaa bk: not $t0,$s0 and $t0,$s0,$s1 or $t0,$s0,$s1 xor $t0,$s0,$s1 sll $t0,$s2,3 srl $t0,$s2,3 sra $t0,$s2,3 li $v0,10 syscall We'll invoke spim, set a breakpoint at bk, and run the program: lo "logical.s" bre bk run Breakpoint encountered at 0x00400038 pr $s0 Reg 16 = 0x456789ab (1164413355) Reg 17 = 0x9abcdef0 (-1698898192) Reg 18 = 0xaaaaaaaa (-1431655766) We step through the next instruction not $t0, $s0. The bitwise not of 0x456789ab is 0xba987654: step [0x00400038] 0x02004027 nor $8, $16, $0 $t0,$s0 pr $t0 Reg 8 = 0xba987654 (-1164413356) ; 13: not We step through the next instruction and $t0, $s0, $s1. The bitwise and of 0x456789ab and 0x9abcdef0 is 0x002488a0: step [0x0040003c] 0x02114024 and $8, $16, $17 ; 14: and pr $t0 $t0,$s0,$s1 CSc 256 Lab Manual 4
Reg 8 = 0x002488a0 (2394272) We step through the next instruction or $t0, $s0, $s1. The bitwise or of 0x456789ab and 0x9abcdef0 is 0xdfffdffb: step [0x00400040] 0x02114025 or $8, $16, $17 $t0,$s0,$s1 pr $t0 Reg 8 = 0xdfffdffb (-536879109) ; 15: or We step through the next instruction xor $t0, $s0, $s1. The bitwise xor of 0x456789ab and 0x9abcdef0 is 0xdfdb575b: step [0x00400044] 0x02114026 xor $8, $16, $17 $t0,$s0,$s1 pr $t0 Reg 8 = 0xdfdb575b (-539273381) ; 16: xor We step through the next instruction sll $t0, $s2 3. 0xaaaaaaaa shift left logical by 3 bits is 0x55555550: step [0x00400048] 0x001240c0 sll $8, $18, 3 ; 18: sll $t0,$s2,3 pr $t0 Reg 8 = 0x55555550 (1431655760) We step through the next instruction srl $t0, $s2 3. 0xaaaaaaaa shift right logical by 3 bits is 0x15555555: step [0x0040004c] 0x001240c2 srl $8, $18, 3 ; 19: srl $t0,$s2,3 pr $t0 Reg 8 = 0x15555555 (357913941) We step through the next instruction sra $t0, $s2 3. 0xaaaaaaaa shift right arithmetic by 3 bits is 0xf5555555 (same as srl, but extend sign bit): step [0x00400050] 0x001240c3 sra $8, $18, 3 ; 20: sra $t0,$s2,3 CSc 256 Lab Manual 5
pr $t0 Reg 8 = 0xf5555555 (-178956971) Summary: In this exercise, we traced through some bitwise logical operations in C/C++ and MAL. Bitwise operations are very useful for extracting bitfields (or groups of data bits) from within a word or larger piece of storage. We ll see some of these uses later in the course. CSc 256 Lab Manual 6