注册 登录
编程论坛 Linux系统管理

一段简单的 bootloader 和 解释

madfrogme 发布于 2012-09-27 22:28, 5679 次点击
Developing a simple Bootloader

Lets take another look at our list:

Are stored with the Master Boot Record (MBR).
Are in the first sector of the disk.
Is the size of a single sector (512) bytes.
Are loaded by the BIOS INT 0x19 at address 0x7C00.

Open up any ordinary text editor (I am using Visual Studio 2005), but Notepad will suffice.
Heres the bootloader (Boot1.asm)...

;*********************************************
;    Boot1.asm
;        - A Simple Bootloader
;
;    Operating Systems Development Tutorial
;*********************************************
 
org        0x7c00                ; We are loaded by BIOS at 0x7C00
 
bits    16                    ; We are still in 16 bit Real Mode
 
Start:
 
    cli                    ; Clear all Interrupts
    hlt                    ; halt the system
   
times 510 - ($-$$) db 0                ; We have to be 512 bytes. Clear the rest of the bytes with 0
 
dw 0xAA55                    ; Boot Signiture


Some of this should not come to much of a surprise. Lets analize line by line:

org        0x7c00                ; We are loaded by BIOS at 0x7C00
Remember: The BIOS loads us at 0x7C00. The above code tells NASM to insure all addresses are relitave to 0x7C00. This means, the first instruction will be at 0x7C00.

bits    16                    ; We are still in 16 bit Real Mode

I explained how the x86 family is backward compatible with the old DOS systems. Because the old DOS systems were

16 bit, All x86 compatible computers boot into 16 bit mode. This means:

We are limited to 1 MB of memory.

We are limited to the 16 bit registers.

We will need to switch the computer into a 32 bit mode. We will do this later.

times 510 - ($-$$) db 0                ; We have to be 512 bytes. Clear the rest of the bytes with 0

In NASM, the dollar operator ($) represents the address of the current line.

$$ represents the address of the first instruction (Should be 0x7C00).

So, $-$$ returns the number of bytes from the current line to the start (In this case, the size of the program).

dw 0xAA55                    ; Boot Signiture

Remember that the BIOS INT 0x19 searches for a bootable disk.

 How does it know if the disk is bootable? The boot signiture.

If the 511 byte is 0xAA and the 512 byte is 0x55, INT 0x19 will load and execute the bootloader.

Because the boot signiture must be the last two bytes in the bootsector,

We use the times keyword to calculate the size different to fill in up to the 510th byte,

rather then the 512th byte.
3 回复
#2
madfrogme2012-10-13 10:47
注意stack 的建立的那几条語句,使用 puts() 函数

[SECTION    .data]   

EatMsg:    db    "Eat at Joe's",0

[SECTION    .bss]

[SECTION    .text]

extern    puts
global    main

main:
        push        ebp
        mov        ebp, esp
        push        ebx
        push        esi
        push        edi
;;;Everything befor this is boilerplate; use it for all ordinary apps
        
        push        EatMsg    ; Push address of message on the stack
        call          puts    ; Call glibc function for displaying strings
        add          esp, 4    ; Clean stack by adjusting ESP back 4 bytes

;;;Everything after this is boilerplate; use it for all ordinary apps
        
        pop        edi
        pop        esi
        pop        ebx
        mov       esp, ebp
        pop        ebp
        ret                ;Return control to linux

-------------------------------------------------------------------------
nasm -f elf -g -F stabs puts.asm
gcc -o puts puts.o


[ 本帖最后由 madfrogme 于 2012-10-13 11:49 编辑 ]
#3
madfrogme2012-10-14 14:06
一段简单的linker script

or this example, let's say that the code should be loaded at address 0x10000,

and that the data should start at address 0x8000000.

SECTIONS
{
  . = 0x10000;
  .text : { *(.text) }
  . = 0x8000000;
  .data : { *(.data) }
  .bss : { *(.bss) }
}

The first line inside the `SECTIONS' command of the above example

sets the value of the special symbol `.', which is the location counter.

The second line defines an output section, `.text'.

The colon is required syntax. Within the curly braces after the output section name,

you list the names of the input sections which should be placed into this output section.

The `*' is a wildcard which matches any file name.

The expression `*(.text)' means all `.text' input sections in all input files.

Since the location counter is `0x10000'

when the output section `.text' is defined,

the linker will set the address of the `.text' section in the output file to be `0x10000'.

the linker will place the `.bss' output section immediately after the `.data' output section in memory
#4
madfrogme2012-10-14 14:09
There are several ways to set the entry point.

The linker will set the entry point by trying each of the following methods in order,

and stopping when one of them succeeds:

the `-e' entry command-line option;

the ENTRY(symbol) command in a linker script;

the value of the symbol start, if defined;

the address of the first byte of the `.text' section, if present;

The address 0.
1