This series of articles is devoted to low-level programming, that is, computer architecture, device operating systems, programming in assembly language and related areas. So far, two habrausers,
iley and
pehat, are engaged in writing. For many high school students, students, and professional programmers, these topics are very difficult to learn. There is a lot of literature and courses on low-level programming, but it’s difficult to make a complete and comprehensive picture. Having read one or two books on assembler and operating systems, it is difficult, at least in general terms, to imagine how this complex system of iron, silicon and many programs - a computer - actually works.
Everyone solves the problem of learning in their own way. Someone reads a lot of literature, someone tries to quickly go to practice and understand along the way, someone tries to explain to friends everything that he learns. And we decided to combine these approaches. So, in this course of articles, we will demonstrate step by step how to write a simple operating system. The articles will be of an overview nature, that is, they will not have comprehensive theoretical information, but we will always try to provide links to good theoretical materials and answer all the questions that arise. We do not have a clear plan, so many important decisions will be made along the way, taking into account your feedback.
Perhaps, we will deliberately start the development process into a dead end in order to allow you and yourself to fully understand all the consequences of a wrong decision, and also to hone some technical skills on it. So do not take our decisions as the only true and blindly believe us. We emphasize once again that we expect readers to be active in the discussion of articles, which should greatly influence the overall process of developing and writing subsequent articles. Ideally, I would like some readers to join the system over time.
We will assume that the reader is already familiar with the fundamentals of assembler and C languages, as well as the basic concepts of computer architecture. That is, we will not explain what a register is or, say, RAM. If you do not have enough knowledge, you can always refer to additional literature. A short list of references and links to sites with good articles are at the end of the article. It is also advisable to be able to use Linux, since all compilation instructions will be provided specifically for this system.
')
And now - more to the point. In the rest of the article we will write the classic program “Hello World”. Our Halloween world will be a little bit specific. It will not run from any operating system, but directly, so to speak, “on bare metal.” Before proceeding directly to writing the code, let's see how specifically we are trying to do it. And for this you need to consider the process of booting the computer.
So, take your favorite computer and press the biggest button on the system unit. We see a funny screensaver, the system unit happily squeals with the speaker and after some time the operating system loads. As you understand, the operating system is stored on the hard disk, and here the question arises: how did the operating system magically boot into RAM and start to run?
You should know: the system that exists on any computer is responsible for this, and the name to it is not, not Windows, that you use the language - it is called the BIOS. Its name is deciphered as the Basic Input-Output System, that is, the basic input-output system. The BIOS is on a small microcircuit on the motherboard and starts immediately after pressing the large ON button. BIOS has three main tasks:
- Detect all connected devices (processor, keyboard, monitor, RAM, video card, head, hands, wings, legs and tails ...) and check them for operability. The POST (Power On Self Test) program is responsible for this. If vital iron is not detected, then no software can help, and at this point the system speaker squeaks something ominous and it won't get to the OS at all. Let's not talk about the sad, suppose that we have a fully working computer, rejoice and proceed to consider the second function of the BIOS:
- Providing the operating system with a basic set of functions for working with hardware. For example, through the functions of the BIOS, you can display text on the screen or read data from the keyboard. Therefore, it is called the basic input-output system. Typically, the operating system accesses these functions through interrupts.
- Run the operating system loader. In this case, as a rule, the boot sector is read - the first sector of the storage medium (floppy disk, hard disk, compact disk, flash drive). Media polling order can be set in BIOS SETUP. The boot sector contains a program, sometimes called the primary loader. Roughly speaking, the task of the bootloader is to start the operating system. The process of loading the operating system can be very specific and strongly depends on its features. Therefore, the primary bootloader is written directly by the OS developers and, during installation, is written to the boot sector. When the boot loader starts, the processor is in real mode.
The sad news: the size of the initial loader should be only 512 bytes. Why so little? To do this, we need to become familiar with the device floppy. Here is an informative picture:

The picture shows the surface of the disk drive. Floppy has 2 surfaces. On each surface there are ring-shaped tracks (tracks). Each track is divided into small arched pieces, called sectors. So, historically, the floppy sector has a size of 512 bytes. The very first sector on the disk, the boot sector, is read by the BIOS in the zero memory segment at offset 0x7C00, and then control is transferred to this address. The bootloader usually loads into memory not the OS itself, but another bootloader program stored on the disk, but for some reason (most likely, this reason is the size) does not fit into one sector. And since, for the time being, the role of our OS is fulfilled by the banal Halloween world, our main goal is to make the computer believe in the existence of our OS, even if it is in one sector, and run it.
How does the boot sector? On a PC, the only requirement for the boot sector is the content in its last two bytes of the values ​​0x55 and 0xAA - the signatures of the boot sector. So, it is more or less clear what we need to do. Let's write the code! The code above is written for the
yasm assembler.
section .text
use16
org 0x7C00 ; 0x7C00
start:
mov ax, cs
mov ds, ax ;
mov si, message
cld ;
mov ah, 0x0E ; BIOS
mov bh, 0x00 ;
puts_loop:
lodsb ; al
test al, al ;
jz puts_loop_exit
int 0x10 ; BIOS
jmp puts_loop
puts_loop_exit:
jmp $ ;
message:
db 'Hello World!', 0
finish:
times 0x1FE-finish+start db 0
db 0x55, 0xAA ;
.
org 0x7C00
, ( , ) (
puts_loop, puts_loop_exit, message
). , 0x7C00.
mov ax, cs
mov ds, ax
(
ds
) (
cs
), , .
«Hello World!».
0x0E
0x10
. :
AH = 0x0E
( )
BH =
( , 0)
AL =
ASCII-
«
jmp $
» . , . , .
«
times 0x1FE-finish+start db 0
» ( ) . , .
, . , , —
yasm. Linux. :
$ yasm -f bin -o hello.bin hello.asm
hello.bin . (, fd ).
$ dd if=hello.bin of=/dev/fd
, , ,
qemu VirtualBox. « ».
:
$ dd if=/dev/zero of=disk.img bs=1024 count=1440
:
$ dd if=hello.bin of=disk.img conv=notrunc
qemu:
$ qemu -fda disk.img -boot a
qemu «Hello World!». . .
- :
- . . «Assembler DOS, Windows Unix»
- DOS
- :
- :
- :
- . « »
- . « IBM PC. »
- . «. »