HOW TO WRITE OS FROM SCRATCH



Tutorial #1


    Here we will try to write very simple and small OS which just displays string: "Hello world!!!" on your screen. First, I should tell that certain programming skills are required here: the very minimum knowledge of the assembler language and Linux command line skills. So if you have never programmed before in assembler you still can proceed reading this tutorial, but be prepared to lots of unknown words and expressions.

This tutorial is the first in the series where I will try to explain and to write step-by-step one very simple operating system with monolithic kernel, but which's gonna have support for such things as protected mode, multitasking, paging,....

The first one is very simple and shows that nothing super complex is in this area and everybody willing to create his (or her) operating system is able to do it. This very very small bunch of code just writes "Hello world!!!" message at your screen after your computer reboots. The only plus is that computer runs completely on your code from the most start. No other operating systems is used here to launch this example - so it is the very minimum operating system!!!!

    This tutorial is divided in two parts:
  1. Introduction to the Linux assembler (AT&T syntax).
  2. The very first OS.

Introduction to the Linux assembler.

    Here I will try to give very short explanation for the syntax of the assembler language used under Linux, as some part of the code in these tutorials will be in assembler language. People who know what AT&T syntax is can skip this section.

   First, please consider these two notations:

   Intel assembler (TASM compiler for Windows)

   mov eax,[ebx+4]
   mov edx,4000h
   add eax,edx
   cmp eax,5000h
   jge do_jump


   AT&T assembler (AS compiler for Linux)

   movl 4(%ebx),%eax
   movl $0x4000,%edx
   addl %edx,%eax
   cmpl $0x5000,%eax
   jge do_jump


    As you see the code for Intel assembler is a bit different, than code for AT&T assembler, but these two versions actually do the same operations. The only difference is a bit different syntax.
    Here are the main differences for AT&T syntax:
  • Registers naming -- the percent sign (%) is added to each regsiter name .
    For example: %eax, %ebx, %ecx, %edx, ....
  • Commands' suffixes -- each command in AT&T syntax usually has suffix, depending on its operands:
    suffix b -- if operands are of size of one byte.
    suffix w -- if operands are of size of one word (two bytes).
    suffix l -- if operands are of size of 4 bytes (machine word for i386+).
    For example:
    movb $0x20,%al
    movw $0x2000,%ax
    movl $0x20000000,%eax
  • Operands order -- standard Intel's right-to-left notation is reversed in AT&T syntax,
    so the equivalent for Intel's: mov eax,ebx is movl %ebx,%eax.
  • Immediate operands -- for AT&T immediate operands are prefixed with the dollar sign ($). Equivalent for Intel's: mov eax,4000h is movl $0x4000,%eax.
  • Other forms of operands -- here are some examples of operands' forms:
    -- to move a value from a specific address(no dollar sign used): movl 50000,%eax
    -- to move a value from a specific variable: movl myvar,%edx
    -- to move an address of a specific variable: movl $myvar,%edx
  • Base addressing -- for Intel: mov eax,[ebx+4], for AT&T: movl 4(%ebx),%eax.....
    AT&T: OFFSET(BASE,INDEX,SCALE).
  • Segment-offset pair (for long jumps) -- for Intel: jmpf 8000h:1000h, for AT&T: ljmp $0x8000,$0x1000.

To make something clear out of all of these, please take a look at the following example:

.code16
.text
read_floppy_bootsector:
   movw $0x8000,%ax
   movw %ax,%es
   movb $0x02,%ah
   movb $0x01,%al
   xorw %dx,%dx
   movb $0x01,%cl
   movb $0x00,%cl
   movw $0x0000,%bx
   int $0x13

ret

    Here we just read the floppy bootsector at the 0x80000 (0x8000:0x0000) address, using BIOS interrupt.
   For now this is all about AT&T assembler. Next you can read how you can use it.



Your first simple OS.

    For this tutorial you will need the following:

  • one 1.44Mb diskette.
  • GCC compiler (all Linux or BSD distributives should have this one). People who got only Microsoft Windows on their PC can also try this as GCC version for Windows also exists and can be downloaded from here: GCC for Windows. Though the package of GCC for Windows comes with command-line UNIX utilities, it is highly recommended for you to have Linux or BSD installed as all commands used here will be from the UNIX shell.

    Please take a look at the following code:

    .code16
    .text

    jmp kernel_entry

    kernel_entry:
       cli
       movw $0x7c0,%ax
       movw %ax,%ds
       movw %ax,%ss
       movw $0x1000,%sp
       sti

    /* Here we use BIOS interrupt to write our message.
    Interrupt 0x10, function 0x0e.
    In %al - character to write, in %ah - 0x0e. */

       movw $hello_msg,%si

    print_string:
       movb (%si),%al

       cmpb $0x00,%al
       je kernel_exit

       movb $0x0e,%ah
       xorw %bx,%bx
       int $0x10

       incw %si
       jmp print_string

    /* Here we just fall into the infinite loop. */

    kernel_exit:
       hlt
       jmp kernel_exit

    hello_msg:
       .asciz "Hello world!!!" /* Zero-padded string. */
    boot_signature:
       .word 0xaa55 /* The boot signature for PC BIOS. */

    If you are a bit lost in this code - don't worry because for now you don't have to understand anything. In this tutorial you will only try to compile and to use it.

    So you can rewrite this code on your own or get the source file from here: tut1.S. Then you should enter the following commands in your shell command line:


       gcc -c -ffreestanding -o kernel.o tut1.S
       ld -o kernel.bin --oformat binary -Ttext 0x0000 kernel.o

     With all these commands you have just compiled and linked your own and very first operating system. Now please insert one 1.44Mb diskette into your floppy drive and enter the following command:

         cat kernel.bin > /dev/fd0

     You should have now your operating system installed on the diskette. Now leave the diskette in the drive and reboot your computer. After reboot you should see the message: "Hello world!!!". This is it!!! Your computer runs only on your code!!!

     Well, that's all for the first tutorial. Details, what has been done here and why and how all these works is explained in the second tutorial.


---------------------------------------------------------------------------------------------------------------------------------------------------------------------
          "HOW TO WRITE OS FROM SCRATCH" -- tutorial series. Copyright (c) 2003 Oleg Puzanov aka NUKEE.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------