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 usizeandas u8casts are Type Casting. This opcode establishes the extraction pattern that every subsequent opcode reuses.