LD Vx, byte — Loading Immediate Values

6XNN loads the value NN directly into register Vx. It is one of the most used opcodes — nearly every program uses it to set up initial values.

Encoding

6XNN
│││└─ NN: 8-bit value to load
││└── X: register index (0–F)
└──── opcode category 6

Example: 0x6A42 means "load the value 0x42 into register VA (register 10)".

Decode and execute

#![allow(unused)]
fn main() {
0x6 => {
    let x  = ((opcode & 0x0F00) >> 8) as usize;
    let nn = (opcode & 0x00FF) as u8;
    self.v[x] = nn;
}
}

Two extractions:

Register index X — lives in bits 11–8 (the second nibble):

0x6A42 → mask 0x0F00 → 0x0A00 → shift right 8 → 0x0A = 10

Cast to usize because it will index into self.v[...].

Value NN — lives in bits 7–0 (the lower byte):

0x6A42 → mask 0x00FF → 0x0042 → as u8 → 0x42

Cast to u8 because registers are 8-bit.

Test

#![allow(unused)]
fn main() {
#[test]
fn test_ld_vx_byte() {
    let mut cpu = Cpu::new();
    // 0x6A42 = LD VA, 0x42
    cpu.memory.load_rom(&[0x6A, 0x42]);
    cpu.step();
    assert_eq!(cpu.v[0xA], 0x42);
}
}

Where this is used

In the test program in main.rs:

0x60, 0x00,  // LD V0, 0  — digit index starts at 0
0x61, 0x00,  // LD V1, 0  — x position starts at 0
0x62, 0x00,  // LD V2, 0  — y position starts at 0

Before the loop even starts, three registers are initialized with 6XNN.


Rust concepts used here: The mask-then-shift pattern is Bitwise Operations. The as usize and as u8 casts are Type Casting. This opcode establishes the extraction pattern that every subsequent opcode reuses.