While reading Hacking: The Art of Exploitation (a wonderful book!), I came across this function:
void binary_print(unsigned int value) {
unsigned int mask = 0xff000000; // Start with a mask for the highest byte.
unsigned int shift = 256*256*256; // Start with a shift for the highest byte.
unsigned int byte, byte_iterator, bit_iterator;
for(byte_iterator=0; byte_iterator < 4; byte_iterator++) {
byte = (value & mask) / shift; // Isolate each byte.
printf(" ");
for(bit_iterator=0; bit_iterator < 8; bit_iterator++) { // Print the byte's bits.
if(byte & 0x80) // If the highest bit in the byte isn't 0,
printf("1"); // print a 1.
else
printf("0"); // Otherwise, print a 0.
byte *= 2; // Move all the bits to the left by 1.
}
mask /= 256; // Move the bits in mask right by 8.
shift /= 256; // Move the bits in shift right by 8.
}
}
Here's a input-output table for the function:
= = = = = = = = = = = = = = = = = = = = = =
INPUT : OUTPUT
= = = = = = = = = = = = = = = = = = = = = =
0 : 00000000 00000000 00000000 00000000
2 : 00000000 00000000 00000000 00000010
1 : 00000000 00000000 00000000 00000001
1024 : 00000000 00000000 00000100 00000000
512 : 00000000 00000000 00000010 00000000
64 : 00000000 00000000 00000000 01000000
= = = = = = = = = = = = = = = = = = = = = =
By this I know that binary_print() converts decimal to binary.
But I don't understand how exactly the function finds the right answer. Specifically:
In short, I would like to understand the method binary_print() uses to do the conversion.
As a bit mask
(on 32 bits machines) 0xff000000
has all 1 bits for the highest byte. And shift
is initialized to 0x1000000
(i.e. 256*256*256).
byte = (value & mask)/shift
is using bit-and to extract the bits of the mask then shifting them to get a value between 0 and 0xff (fitting in an 8 bit byte).
Notice that for unsigned
numbers mask /= 256
is the same as mask = mask >> 8
(and the compiler generally optimizes the first to the second).
The best way to understand exactly what is happening could be to compile your code with all warnings and debugging info (e.g. gcc -Wall -g
) and to use the debugger (gdb
) to run your program step by step and display relevant state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With