How do computers actually understand the code we write?
It’s interesting how some people code for several years without ever learning these essentials. And often take it for granted.
How can a simple text command somehow control millions of screen pixels in a specific area with such incredible precision?
How can text trigger interactions with systems and servers thousands of miles away in the blink of an eye, using raw electricity?
Let’s dive into a fundamental overview of how it all works.
Why coding matters
You see at their core, computers are nothing but a gigantic network of complex interconnected circuits.
Everything your computer does comes from having electric current flow through the circuit.
The core of computing is using these currents as vessels for real-world data.
In digital computing, there are only two states of current: On (1) or Off (0). Just like in a light switch.
We use these two states to pass messages (instructions) to the complex circuit (processor/CPU).
Because of the brilliant way we design the circuit, passing different instructions to the processor makes it “do” different things (a whole other subject on its own)
In a 1-bit processor, you only have 2 possible instructions — 1 or 0 (binary).
But to make a full-fledged computer we need room for much more than two instructions.
That’s why in practice, we use batches of 1s and 0s to represent as many instructions as we need.
Possible instructions
1-bit processor: 1 and 0
2-bit processor: 11, 10, 01, 00
n-bit processor: 2^n possible instructions
We can represent them with a string of 1s and 0s. Or with hexadecimal numbers. Or with more human-friendly notation.
// They're all the same instruction
// These represent batches of electric signals in the real-world
1011100000000001000000000000000000000000
// Hex form
B8 01 00 00 00
// Human-friendly -- Assembly language
MOV EAX, 1
An instruction is like the smallest indivisible unit of any abstract action your computer can take — an atomic action.
On their own, they do incredibly basic things — adding binary numbers, moving current state from one part of the circuit to another, etc.
But the real power of computing comes when processors execute a massive amount of instructions together (millions and billions).
Luckily this isn’t a problem today as we have household processors of up to 3 GHz today — processing 3 billion instructions in a second (!).
When we code, we combine these instructions in unique ways to make amazing things happen.
Text to 1s and 0s
You could write a program by passing the electric currents directly to the processor as instructions.
You wouldn’t need any operating system or input device.
But unfortunately, you’d need sequences of thousands and millions of instructions to do anything meaningful with your computer.
It will take you several weeks and months to do something as simple as displaying a bunch of characters on the screen (like this).
That’s why we created expressive languages that could do in one line what takes dozens or hundreds of machine instructions.
Then we created programs to convert from those expressive languages to Assembly language and eventually to the machine instructions (a whole other subject on its own)
Programs that we call compilers.
Unlike our normal human languages, these expressive languages are incredibly precise with zero room for ambiguity.
So with compilers, we go from [C++] code like this:
int a = 2;
int b = 3;
int sum = a + b;
To Assembly code like this:
a:
.long 2
b:
.long 3
sum:
.zero 4
__static_initialization_and_destruction_0():
push rbp
mov rbp, rsp
mov edx, DWORD PTR a[rip]
mov eax, DWORD PTR b[rip]
add eax, edx
mov DWORD PTR sum[rip], eax
nop
pop rbp
ret
_GLOBAL__sub_I_a:
push rbp
mov rbp, rsp
call __static_initialization_and_destruction_0()
pop rbp
ret
And eventually to the set of machine instructions — what we all call programs or apps.
But the CPU doesn’t run this machine code directly.
The generated machine code is different for every operating system — that’s why .exe
files can only run on Windows, and .apk
can only run on Android.
When the program runs, it’s the OS that sends the actual low-level instructions for the specific processor, according to whatever is in the program.
When you connect this processor to external devices like network adapters, speakers, monitors, and more, these instructions can transmit specialized signals to these peripherals, and incredible things happen.
Final thoughts
The magic lies in the unseen dance of circuits and logic.
Each line we write sparks a journey from human intent to digital action, as electricity interprets our commands through the language of 1s and 0s.
This profound synergy transforms our abstract ideas into a tangible, interactive digital realm, revealing the intricate beauty of computing’s core.