Logical Operations: Manipulating Bits Directly
Not every operation a processor performs deals with numbers as whole quantities. Sometimes software needs to manipulate specific bits within a value, which is done using Logical Operations.
ANDproduces a 1 in each bit position only where both operands have a 1, commonly used to clear specific bits, an operation calledMasking.ORproduces a 1 in each bit position where at least one operand has a 1, commonly used to set specific bits.Shift Left (sll)andShift Right (srl)move all bits of a value by a fixed number of positions, which is also an efficient way to multiply or divide by powers of two.
An example of a logical AND instruction in RISC-V assembly:
and a, b, cThis instruction performs a bitwise AND between the values in registers b and c, storing the result in a.
Making Decisions: How Branching Works at the Hardware Level
A program rarely executes in one straight, unconditional line. Loops, if-statements, and function calls all require the processor to conditionally jump to a different point in the instruction sequence, a capability provided by Conditional Branch instructions.
The two fundamental branch instructions in RISC-V compare two register values directly:
beq a, b, Label
bne a, b, Labelbeq (branch if equal) jumps to the specified label only if the two register values are equal, while bne (branch if not equal) jumps only if they differ. If the condition is false, execution simply continues with the next sequential instruction.
Building Loops and If-Statements from Branches
High-level constructs like if, while, and for do not exist at the hardware level. A compiler translates them into a sequence of comparisons and conditional branches.
Example: a simple high-level if-statement and its conceptual translation:
High-level:
if (i == j) f = g + h;
Translated concept:
bne i, j, Exit
add f, g, h
Exit:Here, if i and j are not equal, execution jumps directly past the addition to the label Exit, skipping it. If they are equal, the branch is not taken and the addition executes normally.
Unconditional Jumps
Not all changes in execution flow depend on a condition. An Unconditional Jump instruction always transfers control to a specified location, regardless of any comparison, and is used to implement constructs such as the end of a loop body jumping back to its start.
Why This Small Set of Instructions Is Enough
Every complex control structure found in high-level programming languages — nested loops, switch statements, early returns — can be constructed by combining just these few primitives: comparison, conditional branching, and unconditional jumping. This is a direct demonstration of the "make the common case simple and let software build complexity on top" philosophy underlying instruction set design.