03 — Number Systems¶
Assembly works directly with binary data. Decimal is a human convenience; the CPU only knows bits. You must be comfortable converting between bases and understanding how negative numbers and characters are encoded.
Positional Number Systems¶
Every positional number system has a base (radix). The value of each digit is multiplied by the base raised to its position.
| Base | Name | Digits Used | Prefix in NASM |
|---|---|---|---|
| 2 | Binary | 0, 1 | 0b or b suffix |
| 8 | Octal | 0–7 | 0o or o suffix |
| 10 | Decimal | 0–9 | (none) |
| 16 | Hexadecimal | 0–9, A–F | 0x or h suffix |
Binary (Base 2)¶
Each digit is a bit. Groupings: - 4 bits = nibble - 8 bits = byte - 16 bits = word - 32 bits = doubleword (dword) - 64 bits = quadword (qword)
Binary to Decimal¶
Decimal to Binary¶
Repeatedly divide by 2, collect remainders bottom-up:
42 ÷ 2 = 21 R 0
21 ÷ 2 = 10 R 1
10 ÷ 2 = 5 R 0
5 ÷ 2 = 2 R 1
2 ÷ 2 = 1 R 0
1 ÷ 2 = 0 R 1
↑ read upward: 101010₂
Hexadecimal (Base 16)¶
Hex is the most important base for assembly. One hex digit = exactly 4 bits = one nibble.
| Hex | Decimal | Binary |
|---|---|---|
| 0 | 0 | 0000 |
| 1 | 1 | 0001 |
| ... | ... | ... |
| 9 | 9 | 1001 |
| A | 10 | 1010 |
| B | 11 | 1011 |
| C | 12 | 1100 |
| D | 13 | 1101 |
| E | 14 | 1110 |
| F | 15 | 1111 |
Hex to Binary (instant conversion)¶
Replace each hex digit with its 4-bit binary:
A 64-bit register in hex¶
This is why hex is preferred — it's compact and maps directly to bytes.
Powers of 2 (Memorize These)¶
| 2ⁿ | Value | Hex |
|---|---|---|
| 2⁸ | 256 | 0x100 |
| 2¹⁰ | 1,024 (1K) | 0x400 |
| 2¹² | 4,096 (4K = page size) | 0x1000 |
| 2¹⁶ | 65,536 (64K) | 0x10000 |
| 2²⁰ | 1,048,576 (1M) | 0x100000 |
| 2³² | 4,294,967,296 (4G) | 0x100000000 |
| 2⁶³ | ~9.2 × 10¹⁸ | 0x8000000000000000 |
Signed Integers: Two's Complement¶
x86 uses two's complement to represent negative numbers. This lets the same ADD/SUB hardware handle both signed and unsigned arithmetic.
The Rule¶
For an N-bit number: - If the most significant bit (MSB) is 0 → positive (same as unsigned) - If the MSB is 1 → negative
Range¶
| Size | Unsigned Range | Signed Range |
|---|---|---|
| 8-bit | 0 to 255 | -128 to 127 |
| 16-bit | 0 to 65,535 | -32,768 to 32,767 |
| 32-bit | 0 to 4,294,967,295 | -2,147,483,648 to 2,147,483,647 |
| 64-bit | 0 to 2⁶⁴-1 | -2⁶³ to 2⁶³-1 |
Computing Two's Complement (negation)¶
To negate a number: flip all bits, then add 1
Verification: 42 + (-42) = 0
Why Two's Complement?¶
- Only one representation of zero (unlike sign-magnitude)
- Addition hardware works identically for signed and unsigned
- Subtraction is just
a + (-b)
Bit Manipulation Essentials¶
These operations are used constantly in assembly:
| Operation | Effect | Example |
|---|---|---|
x & mask |
Keep only masked bits | 0xFF & 0x0F → 0x0F |
x \| mask |
Set bits | 0xF0 \| 0x0F → 0xFF |
x ^ mask |
Toggle bits | 0xFF ^ 0x0F → 0xF0 |
~x |
Flip all bits | ~0x00 → 0xFF |
x << n |
Multiply by 2ⁿ | 1 << 3 → 8 |
x >> n |
Divide by 2ⁿ (unsigned) | 16 >> 2 → 4 |
The Flags Register (RFLAGS)¶
After arithmetic and logic operations, the CPU updates flags in the RFLAGS register. These control conditional jumps.
| Flag | Name | Set When |
|---|---|---|
| CF | Carry Flag | Unsigned overflow / borrow |
| ZF | Zero Flag | Result equals zero |
| SF | Sign Flag | Result is negative (MSB=1) |
| OF | Overflow Flag | Signed overflow |
| PF | Parity Flag | Result has even number of 1-bits |
| AF | Auxiliary Carry | Carry from bit 3 (BCD arithmetic) |
Example: sub rax, rax → result is 0 → ZF=1, SF=0, CF=0, OF=0
ASCII and Character Encoding¶
Characters in memory are just numbers. ASCII assigns a number to each printable character.
'A' = 0x41 = 65
'a' = 0x61 = 97 (lowercase = uppercase + 0x20)
'0' = 0x30 = 48 (digit '0' is not value 0!)
'\n'= 0x0A = 10 (newline)
In NASM, character literals can be written directly:
Number Literals in NASM¶
mov rax, 42 ; decimal
mov rax, 0x2A ; hexadecimal
mov rax, 0b00101010 ; binary
mov rax, 0o52 ; octal
mov rax, 'A' ; character (ASCII 65)
Practice Problems¶
- Convert
0xBEEFto decimal and binary. - What is
-1in 8-bit two's complement? In 64-bit? - What is
0x80000000as a signed 32-bit integer? - Given
rax = 0xFF, what israx & 0x0F?rax | 0x100? - What ASCII character is at position
0x48?
Answers
0xBEEF= 48879; binary =1011 1110 1110 1111-1(8-bit) =0xFF;-1(64-bit) =0xFFFFFFFFFFFFFFFF0x80000000= -2,147,483,648 (minimum signed 32-bit int)0xFF & 0x0F=0x0F;0xFF | 0x100=0x1FF0x48='H'