Why Hardware Instructions Are Kept Simple
A processor does not understand rich, expressive statements the way a human-readable programming language does. Instead, it executes a small, fixed vocabulary of very simple operations, known collectively as the Instruction Set. Keeping this set small and regular makes the hardware that decodes and executes instructions simpler, cheaper, and faster to build.
This principle is closely tied to the philosophy behind RISC (Reduced Instruction Set Computer) designs such as RISC-V, where each instruction performs one well-defined action rather than combining several operations into a single complex instruction.
Core Operations a Processor Performs
Despite the apparent complexity of software, nearly all computation reduces to a handful of operation categories.
Arithmetic Operationssuch as addition and subtraction, which manipulate numeric values directly.Data Transfer Operations, which move values between memory and the processor's fast internal storage.Logical Operations, which manipulate individual bits.Conditional Operations, which alter the normal sequential flow of execution based on a comparison.
A representative addition instruction in RISC-V assembly looks like this:
add a, b, cThis single line instructs the hardware to add the values held in b and c, then place the result into a. Notice that this instruction always specifies exactly one operation and a fixed, small number of operands — this regularity is intentional and is one of the eight core design ideas discussed earlier in this series.
Where Operands Live: Registers and Memory
An instruction needs somewhere to read its input values from and somewhere to write its result to. These locations are called Operands, and hardware provides two very different places to store them.
Registers: Fast but Limited Storage
Registers are small storage locations built directly into the processor. They are extremely fast to access but limited in number — a RISC-V processor, for example, provides exactly 32 general-purpose registers. Because there are so few registers, a compiler must carefully decide which values deserve to occupy this fast storage at any given moment.
Memory: Large but Slower Storage
When a program needs to work with more data than the available registers can hold — such as an entire array — that data is kept in Memory instead. Memory is organized as a large array of individually addressable Bytes, and moving data between memory and registers requires explicit data-transfer instructions.
A typical instruction that loads a value from memory into a register looks like this:
ld a, offset(b)Here, the processor calculates a memory address by adding a fixed offset to the address stored in register b, retrieves the value stored at that memory address, and places it into register a.
Why This Distinction Matters for Performance
Accessing a register takes far less time than accessing memory. Because of this gap, one of the central jobs of both compilers and programmers writing performance-critical code is minimizing unnecessary movement of data between memory and registers, keeping frequently used values in registers as much as possible.