liveBook · Manning

Hardware register

As explained in Rust in Action: Systems programming concepts and techniques

A CPU register is a small, processor-local storage location holding an operand, address, instruction state, or status value.

A hardware register holds data that a CPU can access directly. Operations usually need their operands in registers. In a CHIP-8 emulator, registers are represented as `u8` values inside a `CPU` struct: the Rust array models the processor’s registers rather than creating physical ones. section 5.7.1

Add two registers

Start with two registers holding 5 and 10. The opcode `0x8014` selects register 0, register 1, and addition. Executing it adds the value in register 1 to register 0, leaving 15 in register 0. section 5.7.1

Listing 5.20 Reading the opcode
 impl CPU {
   fn read_opcode(&self) -> u16 {                      #1
     self.current_operation                            #1
   }                                                   #1
 
   fn run(&mut self) {
     // loop {                                         #2
       let opcode = self.read_opcode();
 
       let c = ((opcode & 0xF000) >> 12) as u8;        #3
       let x = ((opcode & 0x0F00) >>  8) as u8;        #3
       let y = ((opcode & 0x00F0) >>  4) as u8;        #3
       let d = ((opcode & 0x000F) >>  0) as u8;        #3
 
       match (c, x, y, d) {
           (0x8, _, _, 0x4) => self.add_xy(x, y),      #4
           _  =>  todo!("opcode {:04x}", opcode),      #5
       }
     // }                                              #6
   }
 
   fn add_xy(&mut self, x: u8, y: u8) {
     self.registers[x as usize] += self.registers[y as usize];
   }
 }

Follow the decoded `x` and `y` values into `add_xy`: they are register indexes, while the array elements are the values being added. section 5.7.1

A larger CPU model has 16 general-purpose registers, so one hexadecimal digit can select a register. It also tracks `position_in_memory`, a special-purpose value normally called the program counter. The execution loop reads an opcode from memory, advances that position, then performs the selected operation. The last general-purpose register can serve as a carry flag for arithmetic overflow. section 5.7.3 section 5.7.3

Registers also participate in control flow: comparing their values can determine whether the CPU changes its position in memory. Thus registers hold more than arithmetic operands; their contents can affect which instruction runs next. section 5.7.5

How Rust in Action: Systems programming concepts and techniques covers it

How deep it goes
Works from a two-register addition model through opcode selection, 16 registers, a program counter, and a carry flag, without describing physical circuitry.
Examples
Uses a two-register addition opcode, a 16-register CPU struct, and overflow handling with the last register as a carry flag.
What it assumes
Introduces CPU terminology and opcode decoding while using Rust structs, arrays, and `u8` values.
What you can do after
Build it from scratch: represent registers in a CHIP-8 emulator and use them when decoding and executing arithmetic instructions.
How it connects
Connects registers to opcodes, operands, integer overflow, the program counter, and control flow.

Also explained in

Compare how 4 books explain hardware register →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Rust in Action: Systems programming concepts and techniques. The section links point to the parts of the book it draws on.