cbit-manipulationbitwise-operatorsriscvshift

Converting a specific range of binary bits in a char array that contains 4 byte binary instruction


A relatively trivial question today

Suppose I have a the following code:

     int extract_bits_21_to_25(unsigned char* instruction) {
    int instruction_to_int = *(int*)instruction;
    int bits_21_to_25 = (instruction_to_int >> 20) & 0x1F;
    return bits_21_to_25;
}



        unsigned char* reverse(unsigned  char* instruction){
            int length = strlen(instruction);
            for (int i = 0; i < length / 2; i++) {
                char temp = instruction[i];
                instruction[i] = instruction[length - i - 1];
                instruction[length - i - 1] = temp;
            }
            return instruction;
        }
    
         
    
    
    int main(int argc, char *argv[]) {
        
            unsigned char dummy_instruction[4] = {0x13,0x01,0xF0,0x7F};
    unsigned char* big_endian = reverse(dummy_instruction);
            int instruction_to_int = *(int*)big_endian;
            int bits_21_to_25 = (instruction_to_int >> 21) & 0xFF;

            printf("%d",bits_21_to_25);
    
            return 0;
        }

When I convert the instruction to big endian I get 0x7F, 0xF0, 0x01, 0x13

Now this in binary is: 01111111 11110000 00000001 00010011

I wish to extract bits 21 to 25 which is 00010, I also wish to convert this to a integer, which is 2

How do I go about doing this My code above does not work for some reason.


Solution

  • A safe way to read integers from character array is taking each bytes in a loop.

    unsigned int read_4byte(const unsigned char* data) {
        unsigned int ret = 0;
        // for (int i = 0; i < 4; i++) { // for big endian
        for (int i = 3; i >= 0; i--) { // for little endian
            ret = (ret << 8) | data[i];
        }
        return ret;
    }
    

    Your "bits 21 to 25" looks like actually bt 7 to 11 (counted from LSB, 0-origin).

    You can use this function to extract bits in your counting (counted from MSB, 1-origin).

    unsigned int get_bits(unsigned int source, int from, int to) {
        int length = to - from + 1;
        int bit_offset = 32 - to;
        unsigned int mask = length == 0 ? 0 : (((1u << (length - 1)) - 1) << 1) | 1;
        return (source >> bit_offset) & mask;
    }
    

    Usage example:

    unsigned int instruction_to_int = read_4byte(dummy_instruction);
    int bits_21_to_25 = get_bits(instruction_to_int, 21, 25);