Skip to main content

From C to Assembly: Blinking an LED the Hard Way

 

From C to Assembly: Blinking an LED the Hard Way

~4 hours of digging, one blinking LED, and a much better mental model of what "compiling" actually means.

The Inspiration

I've been programming since 2017 — variables, control flow, HTTP, web apps, the usual path. But I kept coming back to something Linus Torvalds said: that the compiler writes 100% of the code. I wanted to actually understand what that meant before taking it for granted.

So I went looking for the layer beneath the code I usually write: binary → hexadecimal opcodes → assembly → C. I wanted to see the whole stack, not just use the top of it.

What I Tried

I already knew my way around the Arduino IDE for uploading compiled sketches. While researching, I found out you could write raw hex machine code directly for the Arduino — but the resources I found were too dense to follow. So I stepped back one level, to assembly.

Searching further, I found a YouTube channel with an Arduino-assembly series. I copied one of their examples — a basic LED blink written entirely in AVR assembly, called from a C wrapper — and flashed it to my Uno.

That's when things started clicking. To actually understand why the code worked, I read up on:

  • What the ALU and control unit do
  • The chip's data width and address width
  • How the ATmega328P's clock cycles are used to build a real time delay, using nothing but labeled code blocks acting as a loop

Seeing a for loop built from scratch — just labels, compares, and branches — out of raw instructions was the most satisfying part of the whole exercise.

The Code

The C side just declares the assembly routines as extern "C" and calls them from setup() and loop():



The actual work happens in the .S file — setting the pin direction with SBI DDRB, 4, toggling the LED with SBI/CBI PORTB, 4, and a hand-rolled delay loop using registers R20, R30, and R31:

Takeaway

A digitalWrite(LED, HIGH) is, underneath, a single bit flipped in a port register — and a delay() is just a loop counting down through however many clock cycles you need. Once you've built both by hand, the "high-level" versions stop feeling like magic and start feeling like a well-earned shortcut.

References

  1. Assembly Programming via Arduino Uno — akuzechie's blog
  2. Arduino Assembly YouTube playlist

Further reading from my own research session: ChatGPT conversation · Perplexity search

Comments

Popular posts from this blog

PHP can run AI models - no need Python

 Objective:     Run AI models only using php. Now this is possible with  https://github.com/CodeWithKyrian/transformers-php  this library. I have tried object detection and question answering using this library. Technology:       1.  PHP 8.2 Initialization:     Guide -  https://transformers.codewithkyrian.com/getting-started 1. Initialize project by composer init cmd. 2. Install transformer library by  composer require codewithkyrian/transformers cmd. 3. Enable ffi extention in php.ini       extension = ffi      ffi.enable = true 4. Enable opcache      opcache.jit = tracing 5. Increase memory limit      memory_limit = 512M I. Object detection: ( https://transformers.codewithkyrian.com/object-detection )     Object detection can improve web application perspective . Example:  Retail applications can speed up checkout by automatically recognizing ...

Don't assign value to reference variable.

Objective:          I just tried to create linked list in php.  Challenges:     In php array is sufficient for most data types (simple array, multi-dimensional array and key-value associative array). But, i just tried using  stdClass Object ( pre-defined interfaces and class ). Here, I created one stdClass with reference key and it reference to another class up to final and that final class  reference key is null. Here I used reference key as reference variable. Once i started assigning reference value to this key it assigning new value to it and old one erased. $a = new stdClass(); $a->name = "Trial"; $a->ref = null; for($i=1;$i <= 10;$i++){  $b = new stdClass();  $b->name = 'Demo mj '.$i;  $b->ref = null;  if($a->ref === null ){   $a->ref = &$b;  }else{   $current = $a->ref;   wh...