<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Rohan Gopal N</title>
    <description>The latest articles on DEV Community by Rohan Gopal N (@rohangopaln).</description>
    <link>https://dev.to/rohangopaln</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4208569%2Fecfb4cb2-1d87-48a7-b7c1-0b0e7cd1652f.jpg</url>
      <title>DEV Community: Rohan Gopal N</title>
      <link>https://dev.to/rohangopaln</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rohangopaln"/>
    <language>en</language>
    <item>
      <title>How I Built a Custom x86 Operating System Kernel and Interactive Shell from Scratch</title>
      <dc:creator>Rohan Gopal N</dc:creator>
      <pubDate>Mon, 26 Oct 2026 14:02:32 +0000</pubDate>
      <link>https://dev.to/rohangopaln/how-i-built-a-custom-x86-operating-system-kernel-and-interactive-shell-from-scratch-10k4</link>
      <guid>https://dev.to/rohangopaln/how-i-built-a-custom-x86-operating-system-kernel-and-interactive-shell-from-scratch-10k4</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Many software engineers spend their entire careers operating behind layers of abstraction—writing high-level code that relies on runtimes, garbage collectors, standard libraries, and pre-packaged operating system APIs. While modern toolchains provide speed and productivity, they obscure a fundamental question: What actually happens when a computer turns on and loads an executable into memory?&lt;/p&gt;

&lt;p&gt;Driven by curiosity and inspired by the early days of personal computing, I set out to build Rohnux: a lightweight 32-bit x86 operating system built entirely from scratch in C and Assembly.&lt;/p&gt;

&lt;p&gt;In this article, I will explain how Rohnux works, how it transitions from bare metal to C code, and how I implemented an interactive shell with an in-memory file system.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Boot Sequence: Crossing the Bare-Metal Bridge
&lt;/h2&gt;

&lt;p&gt;When an x86 PC powers on, the system hardware initializes in Real Mode—a legacy 16-bit state. Modern kernels must transition to 32-bit Protected Mode to access linear memory and hardware control registers.&lt;/p&gt;

&lt;p&gt;Rather than writing a full bootloader from scratch, Rohnux relies on the Multiboot Specification, allowing it to be loaded by standard bootloaders such as GRUB.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Assembly Entry Point (src/boot.s)
&lt;/h2&gt;

&lt;p&gt;Because C requires an initialized stack pointer (ESP) to handle function calls, local variables, and parameters, our kernel's entry point must be written in assembly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nf"&gt;Declare&lt;/span&gt; &lt;span class="nv"&gt;constants&lt;/span&gt; &lt;span class="nv"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;Multiboot&lt;/span&gt; &lt;span class="nv"&gt;header&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="nf"&gt;.set&lt;/span&gt; &lt;span class="nb"&gt;AL&lt;/span&gt;&lt;span class="nv"&gt;IGN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;             &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nb"&gt;Al&lt;/span&gt;&lt;span class="nv"&gt;ign&lt;/span&gt; &lt;span class="nv"&gt;loaded&lt;/span&gt; &lt;span class="nv"&gt;modules&lt;/span&gt; &lt;span class="nv"&gt;on&lt;/span&gt; &lt;span class="nv"&gt;page&lt;/span&gt; &lt;span class="nv"&gt;boundaries&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="nf"&gt;.set&lt;/span&gt; &lt;span class="nv"&gt;MEMINFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;             &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nv"&gt;Provide&lt;/span&gt; &lt;span class="nv"&gt;memory&lt;/span&gt; &lt;span class="nv"&gt;map&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="nf"&gt;.set&lt;/span&gt; &lt;span class="nv"&gt;FLAGS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="nb"&gt;AL&lt;/span&gt;&lt;span class="nv"&gt;IGN&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nv"&gt;MEMINFO&lt;/span&gt;  &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nv"&gt;Multiboot&lt;/span&gt; &lt;span class="nv"&gt;flag&lt;/span&gt; &lt;span class="nv"&gt;field&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="nf"&gt;.set&lt;/span&gt; &lt;span class="nv"&gt;MAGIC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="mh"&gt;0x1BADB002&lt;/span&gt;       &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nv"&gt;Magic&lt;/span&gt; &lt;span class="nv"&gt;number&lt;/span&gt; &lt;span class="nv"&gt;letting&lt;/span&gt; &lt;span class="nv"&gt;bootloader&lt;/span&gt; &lt;span class="nv"&gt;find&lt;/span&gt; &lt;span class="nv"&gt;header&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="nf"&gt;.set&lt;/span&gt; &lt;span class="nb"&gt;CH&lt;/span&gt;&lt;span class="nv"&gt;ECKSUM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;MAGIC&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;FLAGS&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nb"&gt;Ch&lt;/span&gt;&lt;span class="nv"&gt;ecksum&lt;/span&gt; &lt;span class="nv"&gt;required&lt;/span&gt; &lt;span class="nv"&gt;by&lt;/span&gt; &lt;span class="nv"&gt;Multiboot&lt;/span&gt; &lt;span class="nb"&gt;sp&lt;/span&gt;&lt;span class="nv"&gt;ecification&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;

&lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nf"&gt;Multiboot&lt;/span&gt; &lt;span class="nv"&gt;Header&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="nf"&gt;.section&lt;/span&gt; &lt;span class="nv"&gt;.multiboot&lt;/span&gt;
&lt;span class="nf"&gt;.align&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nf"&gt;.long&lt;/span&gt; &lt;span class="nv"&gt;MAGIC&lt;/span&gt;
&lt;span class="nf"&gt;.long&lt;/span&gt; &lt;span class="nv"&gt;FLAGS&lt;/span&gt;
&lt;span class="nf"&gt;.long&lt;/span&gt; &lt;span class="nb"&gt;CH&lt;/span&gt;&lt;span class="nv"&gt;ECKSUM&lt;/span&gt;

&lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nf"&gt;Reserve&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="nv"&gt;KiB&lt;/span&gt; &lt;span class="nv"&gt;Stack&lt;/span&gt; &lt;span class="nv"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;the&lt;/span&gt; &lt;span class="nv"&gt;C&lt;/span&gt; &lt;span class="nv"&gt;Kernel&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="nf"&gt;.section&lt;/span&gt; &lt;span class="nv"&gt;.bss&lt;/span&gt;
&lt;span class="nf"&gt;.align&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="nl"&gt;stack_bottom:&lt;/span&gt;
&lt;span class="nf"&gt;.skip&lt;/span&gt; &lt;span class="mi"&gt;16384&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt; &lt;span class="nv"&gt;KiB&lt;/span&gt;
&lt;span class="nl"&gt;stack_top:&lt;/span&gt;

&lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nf"&gt;Kernel&lt;/span&gt; &lt;span class="nv"&gt;Entry&lt;/span&gt; &lt;span class="nv"&gt;Point&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
&lt;span class="nf"&gt;.section&lt;/span&gt; &lt;span class="nv"&gt;.text&lt;/span&gt;
&lt;span class="nf"&gt;.global&lt;/span&gt; &lt;span class="nv"&gt;_start&lt;/span&gt;
&lt;span class="nf"&gt;.type&lt;/span&gt; &lt;span class="nv"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nv"&gt;function&lt;/span&gt;
&lt;span class="nl"&gt;_start:&lt;/span&gt;
    &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="nv"&gt;stack_top&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nb"&gt;esp&lt;/span&gt;
    &lt;span class="nf"&gt;call&lt;/span&gt; &lt;span class="nv"&gt;kernel_main&lt;/span&gt;

    &lt;span class="nf"&gt;cli&lt;/span&gt;
&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nf"&gt;hlt&lt;/span&gt;
    &lt;span class="nf"&gt;jmp&lt;/span&gt; &lt;span class="mb"&gt;1b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Happens Here?
&lt;/h2&gt;

&lt;p&gt;Multiboot Signature: GRUB scans the compiled binary for the 0x1BADB002 magic number. If verified, it confirms the binary is a valid kernel.&lt;/p&gt;

&lt;p&gt;Stack Allocation: We reserve 16 KiB in uninitialized memory (.bss) and point %esp to stack_top.&lt;/p&gt;

&lt;p&gt;Execution Handoff: Assembly transfers control to kernel_main(), our main entry point written in C.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Memory Layout: The Linker Script (src/linker.ld)
&lt;/h2&gt;

&lt;p&gt;To ensure GRUB puts code and data where the kernel expects them, we use a custom linker script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;ENTRY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;SECTION&lt;/span&gt;&lt;span class="nv"&gt;S&lt;/span&gt;
&lt;span class="err"&gt;{&lt;/span&gt;
    &lt;span class="o"&gt;/*&lt;/span&gt; &lt;span class="nf"&gt;Begin&lt;/span&gt; &lt;span class="nv"&gt;placing&lt;/span&gt; &lt;span class="nv"&gt;sections&lt;/span&gt; &lt;span class="nv"&gt;at&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nv"&gt;MB&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;standard&lt;/span&gt; &lt;span class="nv"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;x86&lt;/span&gt; &lt;span class="nv"&gt;kernels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*/&lt;/span&gt;
    &lt;span class="nf"&gt;.&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nv"&gt;M&lt;/span&gt;&lt;span class="c1"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;.text&lt;/span&gt; &lt;span class="nb"&gt;BL&lt;/span&gt;&lt;span class="nv"&gt;OCK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;AL&lt;/span&gt;&lt;span class="nv"&gt;IGN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;KEEP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;.multiboot&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;.text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;.rodata&lt;/span&gt; &lt;span class="nb"&gt;BL&lt;/span&gt;&lt;span class="nv"&gt;OCK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;AL&lt;/span&gt;&lt;span class="nv"&gt;IGN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;.rodata&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;.data&lt;/span&gt; &lt;span class="nb"&gt;BL&lt;/span&gt;&lt;span class="nv"&gt;OCK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;AL&lt;/span&gt;&lt;span class="nv"&gt;IGN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;.data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;.bss&lt;/span&gt; &lt;span class="nb"&gt;BL&lt;/span&gt;&lt;span class="nv"&gt;OCK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;AL&lt;/span&gt;&lt;span class="nv"&gt;IGN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nv"&gt;K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;COMMON&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;.bss&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The linker script places our kernel at physical address 0x00100000 (1 MiB), leaving low memory intact for hardware and system structures. It guarantees that the .multiboot section sits at the beginning of the file.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Writing the Bare-Metal C Kernel (src/kernel.c)
&lt;/h2&gt;

&lt;p&gt;In bare-metal C programming, standard C library functions (printf, malloc, strcmp) are unavailable. Everything must be implemented manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Direct VGA Hardware Access
&lt;/h2&gt;

&lt;p&gt;To print characters to the display, Rohnux writes 16-bit units (8-bit ASCII character + 8-bit color code) directly to the VGA Text Buffer located at address 0xB8000:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;VGA_MEMORY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mh"&gt;0xB8000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;VGA_WIDTH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;VGA_HEIGHT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;terminal_putentryat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;VGA_WIDTH&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;VGA_MEMORY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  PS/2 Keyboard Driver &amp;amp; Polling Loop
&lt;/h2&gt;

&lt;p&gt;To capture keystrokes without an active Interrupt Descriptor Table (IDT), Rohnux uses hardware port polling. The kernel checks status port 0x64 to verify if data is available, then reads raw scan codes from data port 0x60:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kr"&gt;inline&lt;/span&gt; &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="nf"&gt;inb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint16_t&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;__asm__&lt;/span&gt; &lt;span class="k"&gt;volatile&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"inb %1, %0"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"=a"&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Nd"&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="nf"&gt;keyboard_read_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Check if data buffer is full&lt;/span&gt;
            &lt;span class="kt"&gt;uint8_t&lt;/span&gt; &lt;span class="n"&gt;scancode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x60&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scancode&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0x80&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Key-press event (ignore release)&lt;/span&gt;
                &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_ascii_char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;scancode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. The Rohnux Interactive Shell &amp;amp; RAM File System
&lt;/h2&gt;

&lt;p&gt;Once raw character inputs and screen outputs were functional, I developed a lightweight command interpreter and an in-memory Virtual File System (RAM FS).&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-in System Commands
&lt;/h2&gt;

&lt;p&gt;Rohnux currently supports the following standard commands:&lt;/p&gt;

&lt;p&gt;help — Prints the system help menu.&lt;/p&gt;

&lt;p&gt;about — Displays OS version metadata.&lt;/p&gt;

&lt;p&gt;clear — Wipes the VGA video buffer.&lt;/p&gt;

&lt;p&gt;ls — Lists active files and directories.&lt;/p&gt;

&lt;p&gt;mkdir  — Allocates a dynamic directory entry in memory.&lt;/p&gt;

&lt;p&gt;touch  — Creates a dynamic file entry in memory.&lt;/p&gt;

&lt;p&gt;Shell Processing Loop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;kernel_main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;terminal_initialize&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;init_fs&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;print_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"=========================&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;print_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"      ROHNUX v0.2        &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;print_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"=========================&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;print_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Type 'help' for commands.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;rohnux&amp;gt; "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;cmd_buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;buf_idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keyboard_read_char&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cmd_buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;buf_idx&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;execute_command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd_buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;buf_idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;print_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;rohnux&amp;gt; "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sc"&gt;'\b'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Handle Backspace&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf_idx&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;buf_idx&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;terminal_backspace&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;126&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// Printable Characters&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf_idx&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;cmd_buffer&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;buf_idx&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
                &lt;span class="n"&gt;print_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Building and Booting the ISO Image
&lt;/h2&gt;

&lt;p&gt;To test Rohnux on bare metal or inside a hypervisor, the build pipeline compiles all object files, links them into a Multiboot binary, and generates a bootable ISO using GRUB:&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Compile assembly entry point and kernel source
&lt;/h1&gt;

&lt;p&gt;gcc -m32 -ffreestanding -c src/boot.s -o build/boot.o&lt;br&gt;
gcc -m32 -ffreestanding -fno-pie -fno-stack-protector -O2 -c src/kernel.c -o build/kernel.o&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Link objects into binary executable
&lt;/h1&gt;

&lt;p&gt;ld -m elf_i386 -T src/linker.ld -o build/rohnux.bin build/boot.o build/kernel.o&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Create ISO image with GRUB rescue tools
&lt;/h1&gt;

&lt;p&gt;cp build/rohnux.bin iso/boot/rohnux.bin&lt;br&gt;
grub-mkrescue -o build/rohnux.iso iso&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Boot inside QEMU emulator
&lt;/h1&gt;

&lt;p&gt;qemu-system-i386 -cdrom build/rohnux.iso&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion and Future Roadmap
&lt;/h2&gt;

&lt;p&gt;Building Rohnux v0.2 provided deep insights into hardware initialization, video buffers, port I/O, and low-level execution models. Moving from zero lines of code to a bootable, self-contained OS with an interactive shell highlights the power of systems programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next for Rohnux v0.3?
&lt;/h2&gt;

&lt;p&gt;Interrupt Descriptor Table (IDT): Replacing hardware polling with real asynchronous IRQ hardware interrupts.&lt;/p&gt;

&lt;p&gt;Memory Management: Implementing a physical page allocator and kernel heap (kmalloc/kfree).&lt;/p&gt;

&lt;p&gt;ATA Hard Disk Driver: Reading and writing persistent data to storage devices rather than holding files in RAM.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>linux</category>
      <category>cli</category>
      <category>coding</category>
    </item>
  </channel>
</rss>
