Sie sind auf Seite 1von 8

Operating System - setcomputing.

com

file:///C:/Users/Dermot/Desktop/Temp/new 5.html

logo setcomputing Home Search Global News Base Conversions Bitwise Operations Assembler Server Status ASCII table Rsum About the Author articles Algorithms C/C++ C++ STL ASP/SQL Compiler Design

Unique Sessions: 9621 View ASP Source | Search

This tutorial will put you through building your own mini OS and outputting the hello world message. First thing we need to create a boot sector. Because CPU is loading in 16 bit mode, to create a boot sector we need to use assembler and a linker from bin86 package. There are of course alternatives, but the tutorial will be created using examples from this package. The syntax for this assembler combining common characteristics for Intel and AT&T and might seem a little strength, however you'll get used to it. 1. Boot sector (boot.s) I will not write the full source for the program, so that you will understand the basic idea better. First of all, we should define the general constants: START_HEAD = 0 - The device head, we will be using. START_TRACK = 0 - The track, we start reading from. START_SECTOR = 2 - The sector, we will start reading the OS from SYSSIZE = 10 - The size in sectors (1 sector = 512 byte) FLOPPY_ID = 0 -The ID of the drive (0 - is first, 1 is second) HEADS = 2 - Number of heads SECTORS = 18 - Number of sectors for a floppy ( 18 for 1.44 Mb) While booting the following will happen: The BIOS loader reads first sector of the floppy and will put it in 0000:0x7c00 and will move there the control. We'll get it and, first, we should move ourselves lower to the address 0000:0x600 move there and continue. All we really need to do is to boot the kernel ( sector 2-12 on the first track of the floppy with the address 0x100:0000, moving into protected mode and jumping to the first rows of the kernel. Because of this, we'll need to declare few more constants: BOOTSEG = 0x7c00 - We will put the booting BIOS sector here INITSEG = 0x600 - Here we will move it SYSSEG = 0x100 - Our kernel will go here DATA_ARB = 0x92 - The definer of data segment for descriptor CODE_ARB = 0x9A - The definer of code segment for descriptor First of all, we should move ourselves into more appropriate place: cli xor ax,ax mov ss,ax mov sp, #BOOTSEG mov si, sp mov ds, ax mov es, ax sti cld move di, #INITSEG mov cx, #0x100 repnz

1 of 8

21/07/2011 20:05

Operating System - setcomputing.com

file:///C:/Users/Dermot/Desktop/Temp/new 5.html

movsw jmpi go, #0 ; jump into new place of the boot sector , mark "go" Now we have to configure data segments (es,ds) go: mov ax, #0xF0 mov ss,ax mov sp, ax 0xF0:0xF0=0xFF0 mov ax, #0x60 ;we'll set data segments in 0x60 mov ds,ax mov es,ax Finally, we can output the message. Because we have the whole BIOS we can use the prepared function 0x13 of interrupt 0x10. We could of course cut it and write directly into Video memory, but we only have 512 bytes, which is not a lot. We'd rather spend it on something else. mov cx,#18 mov bp,#boot_msg call write_message The function write_message looks like this: write_message: push bx push ax push cx push dx push cx mov ah, #0x03; read the current cursor position, so that we don't output the message anywhere. xor bh,bh int 0x10 pop cx mov bx,#0x0007 ; parameters of outputted symbols: videopage 0, attribute 7 (black and grey) mov ax,#0x1301 ; outputting prompt and moving cursor int 0x10 pop dx pop cx pop ax pop bx ret

and message is like this: boot_msg: .byte 13,10 .ascii "Booting LaserOS..." .byte 0

2 of 8

21/07/2011 20:05

Operating System - setcomputing.com

file:///C:/Users/Dermot/Desktop/Temp/new 5.html

By this time we will have message "Booting LaserOS..." displayed on the screen. This is much better than hello world :). (BOOT.S) Now, as we have our loader, we move into protected mode and output program written in C. The kernel is 32 bit. It will be placed separately from the boot sector and built with gcc and gas. The syntax of assembler gas is compatible with AT&T standard, so it will be much simpler. But first we need to read kernel. Again, we'll use a prepared function 0x2 of interrupt 0x13.

recalibrate: mov ah, #0 mov dl, #FLOPPY_ID int 0x13 ; drive reinitialisation jc recalibrate call read_track ; calling kernel reading function jnc next_work ; if nothing bad happens, continue working bad_read ; if reding is not successful, output error mov bp,#error_read_msg mov cx, 7 call write_message inf1: jmp inf1 ; going to endless loop, so that we can be saved by "hand" rebooting only. The actual reading function is very simple. We should "memorise" parameters and the read the kernel in one go. The difficulties will begin when the kernel wont be able to fit in 17 sectors (i.e. 8.5 Kb); But this is in the future and now we shouldn't have troubles with that! read_track: pusha push es push ds mov di, #sysseg mov es, di ; the data buffer address xor bx,bx mov ch, #START_TRACK ; track 0 mov c1, #START_SECTOR ; start from sector 2 mov dl, FLOPPY_ID mov dh, #START_HEAD mov ah, #2 mov al, #SYSSIZE ; read 10 sectors int 0x13 pop ds pop es popa ret That's it, kernel is read successfully, and we can output one more message:)

3 of 8

21/07/2011 20:05

Operating System - setcomputing.com

file:///C:/Users/Dermot/Desktop/Temp/new 5.html

next_work: call kill_motor ; stop floppy drive mov bp,#load_msg ; output message mov cx,#4 call write_message this is the message, you want to output load_msg: .ascii "DONE" .byte 0 And here how you stop floppy: kill_motor: push dx push ax mov dx,#0x3f2 xor al,al out dx,al pop ax pop dx ret No, you should see the following on your monitor "Booting LaserOS...DONE" and the lame of your floppy drive should be off. Ok, now is the most important bit, jump into protected mode. First of all, we should turn on the address line A20. It means that we'll be using 32 bit data addressing. mov al, #0x01 ; the recording command for 8042 out #0x64, al mov al, #0xDF out #0x60, al

Show to everyone, that we are moving into protected mode, so that everyone knows how 31337 we are:).

protected_mode: mov bp,#load_msg mov cx, #25 call write_message the message load_msg: .byte 13,10 .ascii "Going to protected mode..." .byte 0 While the BIOS is still alive, we should save the cursor position and save it in (0000:0x8000). Kernel will use this data after.

4 of 8

21/07/2011 20:05

Operating System - setcomputing.com

file:///C:/Users/Dermot/Desktop/Temp/new 5.html

save_cursor: mov ah,#0x03 ; read cursor position xor bh, bh int 0x10 seg cs mov [0x8000], dx ; save into special hidden place Now, ATTENTION , restrict interrupts and load descriptors table.

cli igdt GDT_DESCRIPTOR ; load descriptors table description The descriptors table consists of 3 describers: zero ( should present always), code segment and data segment. .align 4 .word 0 GDT_DESCRIPTORS: .word 3*8-1 ; descriptors table size .long 0x600 + GDT ; location of descriptors table .align 2 GDT: .long 0,0 ; e.g. 0 : empty descriptor .word 0xFFFF, 0 ; number 8: code descriptor .byte 0, CODE_ARB, 0xC0, 0 .word 0xFFFF, 0 ; number 0x10 : data descriptor .byte 0, DATA_ARB, 0xCF, 0

Moving into protected mode may implemented in (at minimum) two ways. We will be using command lmsw, just like in Linux. mov ax, #1 lmsw ax ; later real mode : now we are in a protected mode jmpi 0x1000, 8 ; Long jump onto 32 bit kernel At the end of the assembly file you could also add: .org 511 .end_boot: .byte 0 As a result, your file will be exactly 512 byte. That's it, we are done!!! Now we say good buy to it and move onto kernel.

(START.C) Unfortunately, the kernel must also start from assembler. However now it wont be so much of it. We should set the correct values of segments for data. (es, ds, fs, gs) Saving there the value of respective data descriptor.

5 of 8

21/07/2011 20:05

Operating System - setcomputing.com

file:///C:/Users/Dermot/Desktop/Temp/new 5.html

cld cli movl $(___KERNEL_DS),%eax movl %ax,%ds movl %ax,%es movl %ax,%fs movl %ax,%gs No we check, whether address line A20 is turned on correctly with a simple writing methd. For the experiment to be successful we should zero flags xorl %eax,%eax 1: incl %eax mov %eax,0x000000 cmpl %eax,0x100000 je 1b pushl $0 popfl

Now we call the function, written in C.

call SYMBOL_NAME (start_my_kernel)

And that's it inf: jmp inf

Now we are almost back to what we started from. Almost, because we now need to create printf "by hands". Because there are no interrupts, we will be writing directly into video memory. I will "borrow" the code for this part from Linux (arch/i386/boot/compressed) with minor changes. For assembling you'll need The following macros: inb(), outb(), inb_p(), out_p(). Look up in Linux. Now, so that built in function of glibc don't confuse us, we cancel them #undef memcpy set some of our own functions: static void puts(const char *); static char vidmem =(char)0xb8000; /*video memory address*/ static int vidport; /*videoport*/ static int lines,cols; /* number of lines and colors on a screen*/ static int curr_x,curr_y; /*current cursor position*/

Now, we will start program in a normal (high level) language with some more assembly of

6 of 8

21/07/2011 20:05

Operating System - setcomputing.com

file:///C:/Users/Dermot/Desktop/Temp/new 5.html

course:). The function ov moving cursor into (x,y). The is done via I/O into videoport. void gotoxy(int x, int y) { int pos; pos=(x+cols*y)*2 outb_p(14,vidport); outb_p(0xff & (pos>>9),vidport+1); outb_p(15,vidport); outb_p(0xff &(pos>>1),vidport+1); } Screen scrolling function. Works using direct writing into video memory. static void puts(const char*s) { int x,y; char c; x=curr_x; y=curr_y while((c=*s++)!=`\0`){ if(c==`\n`){ x=0; if(++y>=lines){ scroll(); y--; } } else{ vidmem[(x+cols*y)*2]=c; if(++x>=cols){ x=0; if(++y>=lines){ scroll(); y--; } } } } gotoxy(x,y); }

Function copy from one part of memory to another. Void* memcpy( void*__dest,__const void*___src,unsigned int__n) { int I; char*d=(char*)dest,*s=(char*)__src; for(I=o;I<__n,I++) d[i] =s[i] } Function, making long nice sound. Very usefull for debugging.

7 of 8

21/07/2011 20:05

Operating System - setcomputing.com

file:///C:/Users/Dermot/Desktop/Temp/new 5.html

Make_sound() { __asm__(" movb $0xB6, %al\n\t outb %al,$0x43\n\t movb $0x0D, %al\n\t outb %al,$0x43\n\t movb $0x11,%al\n\t outb %al,$0x42\n\t inb $0x61,%al\n\t orb $3,%al\n\t outb %al,\n\t outb %al,$0x61\n\t "); }

And here is the main function. Int start_my_kernel() { /*setting general parameters*/ vidmem=(char*)0xb8000; vidport=0x3b4; lines=25; cots=80; /* reading the saved cursor coordinates*/ curr_x=*(unsigned char *)(0x8000); curr_y=*(unsigned char *)(0x80001); /*show the following*/ puts("LaserOS Loaded\n"); /*Go into endless loop*/ while(1); }

2002 Setcomputing.com. | Terms of Use | Information/help

top

8 of 8

21/07/2011 20:05

Das könnte Ihnen auch gefallen