1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

typedef unsigned char uchar;

uchar get_bit(uchar ch, int bit_idx) {
    return ch >> (7 - bit_idx) & 1;
}
// Ex:  get_bit(10011100₂, 3) should return 1.
//                 ▲

uchar set_bit(uchar ch, int bit_idx, uchar new_value) {
    if(new_value) {                         //                                   bit_idx==2
        // Set bit (to 1)                   //                                      ↓
        return ch | (1 << (7 - bit_idx));   // bitwise-or with a byte like this:  00100000
    }
    else {
        // Unset bit (to 0)                   //                                    bit_idx==2
        assert(new_value == 0);               //                                       ↓
        return ch & (~ (1 << (7 - bit_idx))); // bitwise-and with a byte like this:  11011111
    }
    // ~▒ means bitwise-NOT of ▒.  It flips every 0 to 1, and 1 to 0.
    // ~00100000₂ == 11011111₂
    // Note: The notation for binary bits in the comments is not valid C code and is for illustration.
    //
    //    1 is the same as 00000001₂
    //
    // 0x01 == 00000001₂ ==   1
    // 0x80 == 10000000₂ == 128
}

/*
uchar get_bits(uchar ch, int start_bit, int end_bit) { // end_bit is inclusive
    uchar result = 0x00;
    int start_bit_idx = end_bit - start_bit + 1;
    for(int bit_idx = start_bit, result_bit_idx = start_bit_idx; bit_idx <= end_bit; bit_idx++, result_bit_idx++) {
        uchar bit_value = get_bit(ch, bit_idx);
        result = set_bit(result, result_bit_idx, bit_value);
        printf("bit_idx==%d  result_bit_idx==%d  bit_value==%d  result==0x%02x\n",
                bit_idx,     result_bit_idx,     bit_value,     result);
    }
    return result;
}

uchar get_bits(uchar ch, int start_bit, int end_bit) { // end_bit is inclusive
    return (ch << start_bit) >> (8 - (end_bit - start_bit + 1));
}
*/

uchar get_bits(uchar ch, int start_bit, int end_bit) { // end_bit is inclusive
    ch <<= start_bit;
    int num_bits = end_bit - start_bit + 1;
    ch >>= 8 - num_bits;
    return ch;
}

int main(int argc, char* argv[]) {
    assert( get_bit(0xcb, 1) == 1 ); // 0xcb == 11001011₂
    assert( get_bit(0xcb, 3) == 0 ); // 0xcb == 11001011₂
    assert( set_bit(0x00, 0, 1) == 0x80 ); // 10000000₂
    assert( set_bit(0xcb, 2, 1) == 0xeb ); // 0xcb == 11001011₂, 0xeb == 11101011₂
    assert( set_bit(0xeb, 2, 0) == 0xcb ); // 0xcb == 11001011₂, 0xeb == 11101011₂

    assert( get_bits(0x9c, 3, 6) == 0x0e);
    // get_bits(10011100₂, 3, 6) ==> 00001110₂
    //             ‾‾‾‾                  ‾‾‾‾

    return EXIT_SUCCESS;
}
/* vim: set tabstop=4 shiftwidth=4 fileencoding=utf-8 noexpandtab: */

© Copyright 2022 Alexander J. Quinn         This content is protected and may not be shared, uploaded, or distributed.