Writing a Simple Operating System — from Scratch

(Jeff_L) #1

CHAPTER 3. BOOT SECTOR PROGRAMMING (IN 16-BIT REAL


MODE) 13


Just for completeness, Figure 3.3 shows the raw machine code of this boot sector.
These are the actual bytes that are telling the CPU exactly what to do. If you are
surprised by the amount of effort and understanding that is involved in writing such a
barely --- if at all --- useful program, then remember that these instructions map very
closely to the CPU’s circuitry, so necessarily they are very simple, but also very fast.
You are getting to know your computer now, as it reallyis.


3.4 Hello, World!


Now we are going to attempt a slightly more advanced version of the ’hello’ program,
that introduces a few more CPU fundamentals and an understanding of the landscape
of memory into which our boot sector gets plonked by BIOS.


3.4.1 Memory, Addresses, and Labels


We said earlier how the CPU fetches and executes instructions from memory, and how it
was BIOS that loaded our 512-byte boot sector into memory and then, having finished
its initialisations, told the CPU to jump to the start of our code, whereupon it began
executing our first instruction, then the next, then the next, etc.
So our boot sector code is somewhere in memory; but where? We can imagine the
main memory as long sequence of bytes that can individually be accessed by an address
(i.e. an index), so if we want to find out what is in the 54th byte of memory, then 54 is
our address, which is often more convenient to express in hexadecimal:0x36.
So the start of our boot-sector code, the very first machine code byte, is at some
address in memory, and it was BIOS that put us there. We might assume, unless we
knew otherwise, that BIOS loaded our code at the start of memory, at address0x0. It’s
not so straightforward, though, because we know that BIOS has already being doing
initialisation work on the computer long before it loaded our code, and will actually
continue to service hardware interrupts for the clock, disk drives, and so on. So these
BIOS routines (e.g. ISRs, services for screen printing, etc.) themselves must be stored
somewhere in memory and must be preserved (i.e. not overwritten) whilst they are
still of use. Also, we noted earlier that the interrupt vector is located at the start of
memory, and were BIOS to load us there, our code would stomp over the table, and upon
the next interrupt occurring, the computer will likely crash and reboot: the mapping
between interrupt number and ISR would effectively have been severed.
As it turns out, BIOS likes always to load the boot sector to the address0x7c00,
where it is sure will not be occupied by important routines. Figure 3.4 gives an example
of the typical low memory layout of the computer when our boot sector has just been
loaded [?]. So whilst we may instruct the CPU to write data to any address in memory,
it may cause bad things to happen, since some memory is being used by other routines,
such as the timer interrupt and disk devices.


3.4.2 ’X’ Marks the Spot


Now we are going to play a game called “find the byte”, which will demonstrate memory
referencing, the use of labels in assembly code, and the importance of knowing where
BIOS loaded us to. We are going to write an assembly program that reserves a byte of

Free download pdf