⚙️

Assembly Language

2024 — Base64 Encoding/Decoding in x86-64 Assembly

About

Low-level implementation of Base64 encoding and decoding in x86-64 Assembly (NASM). Understanding computing at the hardware level — manipulating bits, bytes, and registers directly.

🎮 Live Demo

Try the same algorithm implemented in the assembly code:

Encoded (Base64):

QVMxNjQwNzM=

Decoded back:

AS164073

How Base64 works

Every 3 bytes (24 bits) are split into 4 groups of 6 bits. Each 6-bit value (0-63) maps to a character: A-Z (0-25), a-z (26-51), 0-9 (52-61), +/ (62-63). Padding with '=' if input isn't divisible by 3.

💻 Running on Linux

$ nasm -f elf64 base64_encode_linux.asm -o encode.o
$ ld encode.o -o encode
$ ./encode
Input:   AS164073
Encoded: QVMxNjQwNzM=

$ nasm -f elf64 base64_decode_linux.asm -o decode.o
$ ld decode.o -o decode
$ ./decode
Encoded: QVMxNjQwNzM=
Decoded: AS164073

Code Sample: Encoding 3 Bytes

; Load 3 bytes into rax, convert to 4 base64 chars
mov al, [input + rcx]        ; First byte
shl rax, 16
mov bl, [input + rcx + 1]    ; Second byte
shl rbx, 8
or rax, rbx
mov bl, [input + rcx + 2]    ; Third byte
or rax, rbx

; Extract 6-bit groups and lookup in table
mov r9, rax
shr rax, 18                  ; Bits 23-18 → char 1
and rax, 0x3F
mov al, [table + rax]        ; Lookup in Base64 table
mov [output + rdx], al

📊 Bit Manipulation

Converting "AS1" (3 bytes) to Base64 "QVMx" (4 chars):

Input bytes: 01000001 01010011 00110001 A=65, S=83, 1=49
6-bit groups: 010000 010101 001100 110001 16, 21, 12, 49
Base64 chars: QVMx table[16,21,12,49]

What I Learned

  • • Direct register manipulation (RAX, RBX, RCX, RDX, RSI, RDI)
  • • Bit shifting operations (SHL, SHR) for extracting bit groups
  • • Linux system calls (syscall) for I/O without libc
  • • Memory addressing modes and the x86-64 ABI
  • • How high-level operations map to machine instructions

Tech Stack

x86-64 Assembly NASM Linux Syscalls Bit Manipulation