Skip to content

Bits, bytes, hexadecimal and masks

On the PIC18F4550 almost everything is configured by modifying individual bits inside 8-bit registers (one byte: 2⁸ = 256 states, 0 through 255). To review the digital-systems idea, start with What 8-bit means.

This page complements Basic architecture and Main registers: there you saw what WREG, STATUS, and SFRs are; here you learn how to read, write, and mask bits in assembly.

Mastering binary, hexadecimal, and masks is essential for the exam and lab work (especially Practice 1, which requires logic routines with the ALU).

ConceptDefinitionOn the PIC18
BitSmallest unit: 0 or 1Each pin, flag, or SFR bit
ByteGroup of 8 bitsOne register (WREG, LATB, STATUS…)
NibbleHalf byte = 4 bitsOne hex digit (0–F) or high/low nibble

Bits are numbered 0 through 7. Bit 0 is the LSB (least significant); bit 7 is the MSB (most significant):

Bit: 7 6 5 4 3 2 1 0
Value: 1 1 0 0 0 0 1 1 → decimal 195, hex 0xC3
Weight: 128 64 32 16 8 4 2 1 (powers of 2)

To get decimal: add the weights where the bit is 1. In the example: 128 + 64 + 2 + 1 = 195.

Writing B'11000011' is long; in hex one byte is only 2 digits (0xC3). Each hex digit is 4 bits (one nibble):

HexBinaryDecimal
000000
100011
910019
A101010
B101111
C110012
D110113
E111014
F111115
DecimalBinaryHex (0x)Hex (H suffix)Typical use
0000000000x0000HAll off
1000000010x0101HBit 0 only
15000011110x0F0FHFull low nibble
240111100000xF0F0HFull high nibble
170101010100xAAAAHAlternating pattern
255111111110xFFFFHAll bits set

Decimal → binary: divide by 2 and read remainders bottom to top, or subtract powers of 2 (128, 64, 32…).

Hex → binary: expand each hex digit to 4 bits. 0xC3C = 1100, 3 = 001111000011.

Binary → hex: group in 4 bits from the right. 110000111100 + 00110xC3.

Decimal → hex: divide by 16. Example: 195 ÷ 16 = 12 remainder 3 → 0xC3 or C3H.

The same byte can be written in several ways. All mean the same value:

StyleExampleTypical use
0x prefix0x00, 0xFF, 0xC3MPASM code, many tools
H suffix00H, FFH, C3HNotes, reports, exercise sheets
MPASM h suffix00h, 0FFh, 0C3hValid alternative in .ASM

H suffix rule: digits are hex; H at the end means base 16. 00H = zero; 0FH = 15; F0H = 240. Do not confuse 0FH (15) with F0H (240).

When you only need to change one bit of an SFR without touching the others, use bit instructions:

InstructionEffectExample
BSFSet bit to 1BSF LATB, 0 → RB0 high
BCFClear bit to 0BCF TRISB, 0 → RB0 as output
BTFSSSkip if bit is 1BTFSS PORTB, 3 → read button
BTFSCSkip if bit is 0BTFSC STATUS, Z → skip if Z=1

You already saw this in Architecture — SFR and Registers — GPIO:

; Configure RB0 as output and turn LED on
BCF TRISB, 0 ; TRISB bit 0 = 0 → output
BSF LATB, 0 ; LATB bit 0 = 1 → LED on

To toggle a bit without reading the whole byte:

; Toggle RB0
MOVLW B'00000001' ; mask bit 0 only
XORWF LATB, F ; XOR bit by bit → toggles that bit

A mask is a bit pattern showing which positions you want to affect. ALU logic operations apply the mask bit by bit on WREG and another operand.

AND keeps 1 only where both operands have 1. Use it to mask (keep certain bits) or clear bits by putting 0 in the mask:

; Read only the high nibble of PORTB (bits 7..4)
MOVF PORTB, W
ANDLW B'11110000' ; 0xF0 — bits 4-7 pass; 0-3 become 0
; Clear bits 4-7 of LATC without touching 0-3
MOVLW B'00001111' ; mask: keep low nibble
ANDWF LATC, F ; high bits → 0

IOR sets 1 where either operand has 1. Use it to turn on bits without clearing others:

; Turn on bits 0 and 3 of LATB (rest unchanged)
MOVLW B'00001001' ; bits 0 and 3 set
IORWF LATB, F

In MPASM the instruction is IORWF / IORLW.

XOR yields 1 where bits differ. Uses:

  • Toggle selected bits (see above).
  • Compare if two values are equal (result 0 → flag Z = 1 in STATUS).
MOVLW D'5'
XORWF counter, W ; if counter == 5 → W = 0 → Z = 1
BTFSS STATUS, Z
GOTO not_five ; if counter != 5 → jump to destination
; counter == 5 ...
GOTO cmp_done
not_five:
; counter != 5 ...
cmp_done:

Inverts all bits: 01, 10. On PIC18 with WREG:

MOVF LATB, W
XORLW B'11111111' ; equivalent to NOT of W (0xFF)
MOVWF temp ; temp = complement of LATB

Or with COMF on a file register:

COMF temp, F ; temp = NOT temp

Shift bits with or without carry — Practice 1 asks for rotate without carry:

InstructionDirectionWhat it does
RLCFLeftMSB goes to C; rotate through carry
RRCFRightLSB goes to C; rotate right
RLNCFLeftRotate without carry — bit that falls off re-enters
RRNCFRightRotate without carry to the right

Example — rotate temp left without carry:

RLNCF temp, F

Many lab reports ask you to split a byte into two nibbles (displays, BCD, tables):

; temp = 0xC3 → high_nibble = 0xC0, low_nibble = 0x03
MOVF temp, W
ANDLW B'11110000' ; 0xF0 — bits 7..4 only
MOVWF high_nibble
MOVF temp, W
ANDLW B'00001111' ; 0x0F — bits 3..0 only
MOVWF low_nibble

To swap high and low nibbles:

SWAPF temp, F ; swap high ↔ low nibble

The UNEXPO lab requires software routines for add, subtract, multiply, divide, plus OR, AND, XOR, complement, and rotate using the PIC18 ALU. Logic ops usually go through WREG:

; AND between PORTB and a mask in W
MOVF PORTB, W
ANDLW B'00001111' ; W = PORTB AND 0x0F
; OR between LATC and W
MOVLW B'10000000'
IORWF LATC, F ; LATC = LATC OR W
; XOR between temp and W
MOVLW B'10101010'
XORWF temp, F

See Architecture — STATUS: after AND, OR, or XOR, check Z (result zero?) and N (sign of bit 7).

Integrated example — configure several pins

Section titled “Integrated example — configure several pins”

You want RB0–RB3 as outputs and RB4–RB7 as inputs in one step (mask on TRISB: 1 = input):

MOVLW B'11110000' ; bits 4-7 = 1 (input); 0-3 = 0 (output)
MOVWF TRISB ; write full byte

Or bit by bit (clearer when learning, longer in code):

; Outputs RB0-RB3
BCF TRISB, 0
BCF TRISB, 1
BCF TRISB, 2
BCF TRISB, 3
; Inputs RB4-RB7
BSF TRISB, 4
BSF TRISB, 5
BSF TRISB, 6
BSF TRISB, 7

Ejercicio · Parcial

Convert 0xC3 to binary and explain BCF

0xC3 = 11000011 (decimal 195). Active bits: 0, 1, 6, and 7.

If PORTB was 0xC3 and you run BCF PORTB, 6:

  • Only bit 6 becomes 0; the rest unchanged.
  • Result: 1100001110000011 = 0x83 (decimal 131).

Why use BCF instead of writing all of PORTB? You avoid accidentally changing pins you did not mean to touch.

  • Mixing notation: 0x0F = 0FH = 15, but 0xF0 = F0H = 240 — nibble order matters.
  • Bit vs pin: bit 3 of LATB is pin RB3; numbering starts at 0.
  • AND vs OR: AND clears bits where the mask is 0; OR sets bits where the mask is 1.
  • Inverted mask on TRIS: in TRISx, 1 = input and 0 = output — when designing masks, remember what each bit means.
  • Writing PORTx for outputs: write LATx (or BSF/BCF on LATx); read inputs with PORTx. See Registers — PORT vs LAT.
  • Forgetting -LW vs -WF: ANDLW uses a literal → WREG; ANDWF uses a register → WREG or the register (F).

How many distinct unsigned values does one byte represent?

256 values, 0 through 255 (2⁸ combinations).

What does ANDLW 0x0F do after MOVF PORTB, W?

Leaves only the low nibble of PORTB in WREG; bits 4–7 become 0.

What is an OR mask used for?

To set specific bits without clearing those already at 1.

How do you tell if two bytes are equal using XOR?

XORWF between them; if the result is 0, flag Z in STATUS is 1.

Interactive exam

Bits and hexadecimal

Based on: Clase Tema 2 y 3 (1).pdf

0 of 0 answered

The hexadecimal value 0x0F in binary is:
To turn on specific bits without clearing those already at 1 you use...
How many distinct unsigned values can an 8-bit register represent?
The hexadecimal value 0xC3 in binary is:
After MOVF PORTB,W and ANDLW 0x0F, WREG contains:
LATB is 0xC3. You run BCF LATB, 6. LATB becomes:
To turn on ONLY bit 0 of LATB without touching the others, the most direct instruction is:
XORWF between two equal bytes leaves STATUS flag Z at:
The SWAPF instruction on a byte:
On TRISB, writing MOVLW B'11110000' and MOVWF TRISB configures: