Написать загрузчик в C - PullRequest
       12

Написать загрузчик в C

19 голосов
/ 16 августа 2011

Я новичок в написании загрузчиков. Я написал загрузчик helloworld в asm, и Сейчас я пытаюсь написать один на C. Я написал загрузчик helloworld на C, но не могу его скомпилировать.

Это мой код. Что я делаю неправильно? Я полностью ошибаюсь?

void print_char();
int main(void){
char *MSG = "Hello World!";
int i;

__asm__(
    "mov %0, %%SI;"
    :
    :"g"(MSG)
);
for(i=0;i<12;i++){
    __asm__(
        "mov %0, %%AL;"
        :
        :"g"(MSG[i])
    );
    print_char();
}

return 0;
}

void print_char(){
__asm__(
    "mov $0X0E, %AH;"
    "mov $0x00, %BH;"
    "mov $0x04, %BL;"
    "int $0x10"
);
}

Ответы [ 5 ]

17 голосов
/ 16 августа 2011

Я бы посоветовал вам взглянуть на http://wiki.osdev.org/Rolling_Your_Own_Bootloader, а также на раздел Bootloader: http://www.brokenthorn.com/Resources/OSDevIndex.html

Существуют отличные учебники, которые помогут вам начать создавать свой собственный загрузчик.Также вы можете присоединиться к каналу #osdev в freenode, чтобы присоединиться к обсуждению, если вам нужна дополнительная информация.

11 голосов
/ 23 мая 2012

Позвольте мне предположить здесь много вещей: вы хотите запустить свой загрузчик в системе x86, у вас есть набор инструментов gcc, установленный на * nix box.

Есть несколько моментов, которые необходимо учитывать при написании загрузчика:

  1. ограничение в 510 байт для VBR, еще меньше для MBR из-за таблицы разделов (если вашей системе это требуется)
  2. реальный режим - 16-битные регистры и seg: off адресация
  3. загрузчик должен быть плоским двоичным файлом, который должен быть связан для запуска по физическому адресу 7c00h
  4. нет внешних ссылок на библиотеку (дух!)

Теперь, если вы хотите, чтобы gcc выводил такой двоичный файл, вам нужно поиграть с ним.

  1. gcc по умолчанию разделяет 32-битный код. Чтобы иметь выходной код gcc, который будет работать в реальном режиме, добавьте __asm__(".code16gcc\n") вверху каждого файла C.
  2. gcc выводит скомпилированные объекты в ELF. Нам нужна корзина, которая статически связана в 7:00. Создайте файл linker.ld со следующим содержанием

    ENTRY(main);
    SECTIONS
    {    
        . = 0x7C00;    
        .text : AT(0x7C00)
        {
            _text = .;
            *(.text);
            _text_end = .;
        }
        .data :
        {
            _data = .;
            *(.bss);
            *(.bss*);
            *(.data);
            *(.rodata*);
            *(COMMON)
            _data_end = .;
        }    
        .sig : AT(0x7DFE)    
        {        
            SHORT(0xaa55);
        }    
        /DISCARD/ :
        {
            *(.note*);
            *(.iplt*);
            *(.igot*);
            *(.rel*);
            *(.comment);
            /* add any unwanted sections spewed out by your version of gcc and flags here */    
        }
    }
    
  3. написать код загрузчика в bootloader.c и собрать загрузчик

    $ gcc -c -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -o bootloader.o bootloader.c
    $ ld -static -Tlinker.ld -nostdlib --nmagic -o bootloader.elf bootloader.o
    $ objcopy -O binary bootloader.elf bootloader.bin
    
  4. Поскольку вы уже создали загрузчики с ASM, я думаю, все остальное для вас очевидно.

- взято из моего блога: http://dc0d32.blogspot.in/2010/06/real-mode-in-c-with-gcc-writing.html

5 голосов
/ 16 августа 2011

Загрузчик написан на ASM.

При компиляции кода C (или C ++, или чего-либо еще), компилятор «преобразует» ваш читаемый человеком код в машинный код. Так что вы не можете быть уверены в результате.

Когда компьютер загружается, BIOS выполнит код с определенного адреса. Этот код должен быть исполняемым напрямую.

Вот почему вы будете использовать сборку. Это единственный способ получить неизмененный код, который будет выполняться как написано процессором.

Если вы хотите кодировать на C, вам все равно придется кодировать загрузчик ASM, который будет отвечать за правильную загрузку машинного кода, сгенерированного используемым вами компилятором.

Вы должны понимать, что каждый компилятор генерирует разные машинные коды, которые могут нуждаться в предварительной обработке перед выполнением.

BIOS не позволит вам предварительно обработать ваш машинный код. Загрузка с ПК - это просто переход в область памяти, то есть машинный код, расположенный в этой области, будет выполняться напрямую.

2 голосов
/ 16 августа 2011

Поскольку вы используете GCC, вам следует прочитать информационные страницы о различных «целевых средах».Скорее всего, вы хотите использовать флаг -ffreestanding .Также мне пришлось использовать -fno-stack-protector flags, чтобы избежать некрасивой магии компилятора.

Затем вы получите ошибки компоновщика, говорящие, что memset иподобное не найдено.Таким образом, вы должны реализовать свою собственную версию и связать их.

1 голос
/ 16 августа 2011

Я пробовал это несколько лет назад - параметры могли измениться.

Вы должны запустить gcc с -ffreestanding (не связывать), а затем связать, используя ld с флагами -static, -nostdlib

...