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
73
74
75
76
77
78
79
80
// This is not working code.  This is just notes in the form of a C file, for tidiness.

// .current_byte:  00000000₂
write_bits(&writer, 0x05, 3);   // 00000101₂
                                //      ‾‾‾
// Inside write_bits(…):
// When reading bits from our parameter ('byte'), we take from the least significant
// (rightmost) side.  When writing to the file (or to .current_byte), we write to the
// most significant (leftmost) side.
//
// Need to get our 3 bits to the most significant (leftmost) side.
// byte ============= 00000101₂ == 0x05
// byte << 5 ======== 10100000₂
// byte << (8 - 3) == 10100000₂
//              ↑
//              num_bits_to_write
//
// New .current_byte:
//
// .current_byte | byte << (8 - 3)  == 00000000₂ | 10100000₂ == 10100000₂
// .current_byte == 10100000₂
    
write_bits(&writer, 0xf3, 3);   // 00000101₂
// Inside write_bits(…):
// .current_byte == 10100000₂    // 0xa0
// .byte ========== 11110011₂    // 0xf3
//
// We will start with an "okay" way
//
// We need to shift bits of 'byte' to the left... not all the way to the left, but to the
// position where they will be when written to .current_byte.
//
// .current_byte == 10100000₂    // 0xa0
//                     ─┬─
//                new bits go here
//
// byte ========== 11110011₂    // 0xf3
//                 ┌─┘  ┌─┘
// byte << 2 ===== 11001100₂    // 0xcc
// 
// How did we know it should be shifted by two?
//
// byte << (8 - num_bits_to_write - bits_written_to_current_byte_so_far)
//
// WRONG WAY:
// byte << 2 | .current_byte == 11001100₂ | 10100000₂  // WRONG!!!
//                           == 11101100₂              // WRONG!!!
//
// Problem is that we did not clear extra bits from the most significant (leftmost)
// side of byte.
//
// BETTER:  Use a bit mask (00011002₂) to select only the bits from 'byte' that
// you want to set.
//
// byte << 2 & 00011100₂ | .current_byte == (11110011₂ << 2) & 00011100₂ | 10100000₂
//                                       == (11001100₂ & 00011100₂) | 10100000₂
//                                       ==  00001100₂ | 10100000₂
// .current_byte ==========================  10101100₂
//
// Let's improve that calculation.  How did we get that bit mask?
//
// Easier to do the masking before the bit shift.
//
// byte == 11110011₂
// byte & 00000111₂ == 00000011₂   // only the bits we want to keep
//                          ‾‾‾
// byte & create_string_of_1s_at_right(3) ================== 00000011₂
// byte & create_string_of_1s_at_right(num_bits_to_write) == 00000011₂
//
// I am not suggesting that you include your warmup.c in your build (Makefile) for HW18.
// I'm just saying that you can use that same logic from the warmup for this.
//
// byte && 00000111₂ << 2 | .current_byte == 11110011₂ & 00000111₂ << 2 | 10100000₂
//                                        == 00000011₂ << 2 | 10100000₂
//                                                ‾‾‾
//                                        == 00001100₂      | 10100000₂
//                                              ‾‾‾
// .current_byte =========================== 10101100₂

/* vim: set tabstop=4 shiftwidth=4 fileencoding=utf-8 expandtab: */

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