How Computers Represent Numbers and Encode Instructions in Binary

Underneath every value a program manipulates and every instruction a processor executes lies a fixed-width string of bits. This article explains how signed and unsigned numbers are represented and interpreted differently from the same binary pattern, and how machine instructions themselves are encoded into rigid binary fields that hardware can decode at high speed.

Signed and Unsigned NumbersTwo's ComplementInstruction Encoding

~3 min read · Updated Sep 6, 2026

Why Numbers Need a Fixed Representation

Computer hardware stores every value using a fixed number of bits, commonly grouped into 32-bit or 64-bit chunks called Words. Because the number of bits is fixed, there is a hard limit on the range of values that can be represented, and the same bit pattern can mean different things depending on how it is interpreted.

Unsigned Numbers: Representing Only Non-Negative Values

An Unsigned Number uses every available bit to represent magnitude, with no bit reserved for sign. For an n-bit unsigned number, the representable range is:

Range: 0 to (2^n − 1)

Unsigned representation is commonly used for values that can never logically be negative, such as memory addresses.

Signed Numbers and Two's Complement

Most arithmetic in real programs requires negative values as well. The representation used almost universally in modern hardware is called Two's Complement.

In two's complement representation, the leftmost bit is called the Sign Bit: it is 0 for non-negative numbers and 1 for negative numbers, but unlike simple sign-magnitude representation, the remaining bits are not just a plain magnitude — the whole pattern is calculated in a way that makes addition and subtraction work correctly using the same hardware circuitry regardless of sign.

To negate a number in two's complement, every bit is inverted and then 1 is added to the result:

Step 1: Invert all bits of the number
Step 2: Add 1 to the inverted result

This method is chosen specifically because it allows the same adder circuit used for unsigned addition to correctly handle subtraction and negative numbers, avoiding the need for separate hardware.

How Machine Instructions Are Encoded

Just as numeric data is stored as fixed-width binary patterns, instructions themselves are encoded the same way. Each RISC-V instruction is packed into a fixed 32-bit word, divided into distinct Fields, each carrying a specific piece of information.

A typical arithmetic instruction format includes fields such as:

  • Opcode: identifies which basic operation category the instruction belongs to.
  • Destination Register (rd): specifies where the result will be stored.
  • Source Registers (rs1, rs2): specify where the input operand values come from.
  • Funct Fields: provide additional bits needed to fully distinguish the exact operation when the opcode alone is not specific enough.

This layered field structure is called the instruction's Format, and RISC-V defines a small number of standard formats so that decoding hardware can extract each field using the same fixed bit positions across many different instructions, keeping the decoding logic simple and fast.

Why Fixed-Width Encoding Matters

Keeping every instruction the same fixed width, with fields always located at predictable bit positions, allows the processor's decoding hardware to extract operands and identify the operation in a single, simple step rather than needing variable and complex parsing logic — directly supporting the earlier design principle of keeping the common case fast.

Written & researched by Dr. Shahin Siami

Related Articles

How Hardware Performs Division: Quotients, Remainders, and Edge Cases

Division is the most hardware-intensive of the basic arithmetic operations, involving repeated subtraction and comparison rather than a single-pass circuit. This article explains the conceptual long-division algorithm hardware follows, how quotient and remainder are produced together, and the special edge cases like division by zero that hardware must explicitly handle.

Continue

How Hardware Multiplies Numbers: From Simple Logic to Real Circuits

Multiplication is far more hardware-intensive than addition, since it fundamentally involves repeated addition and shifting. This article walks through the conceptual algorithm hardware uses to multiply binary numbers, explains why the result needs twice the bit width of the inputs, and covers how signed multiplication differs from the unsigned case.

Continue

How Hardware Performs Addition and Subtraction, and Detects Overflow

Arithmetic looks trivial in software but requires careful circuit design and explicit overflow handling in hardware. This article explains how a processor's adder circuit performs both addition and subtraction using the same hardware, and how overflow conditions are detected and handled for signed and unsigned numbers.

Continue

Arrays Versus Pointers at the Hardware Level

In C, arrays and pointers often look interchangeable, and many programmers treat them as if they were the same thing. At the hardware level, however, they compile down to noticeably different instruction sequences with different performance characteristics. This article compares the two approaches using RISC-V assembly to show exactly why pointer-based code is often faster.

Continue

From Source Code to a Running Process: Translation and a Full Sort Example

Turning a C program into something the operating system can actually run involves several distinct translation stages, each producing a different intermediate file. This article walks through that full pipeline from compiler to loader, then applies the concepts from this chapter to a complete, realistic example: translating a C sorting routine into RISC-V assembly step by step.

Continue

Wide Address Handling and Synchronization in RISC-V

A 32-bit instruction cannot fit a large constant or a far-away memory address directly inside it, and multiple processors sharing memory cannot safely update the same data without coordination. This article explains how RISC-V builds large immediate values and addresses out of smaller pieces, and how atomic instructions allow parallel programs to synchronize safely.

Continue