Записать загрузчик в C
Я новичок в написании загрузчиков. Я написал загрузчик 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"
);
}
Ответы
Ответ 1
Я бы предложил вам посмотреть http://wiki.osdev.org/Rolling_Your_Own_Bootloader, а также раздел Bootloader: http://www.brokenthorn.com/Resources/OSDevIndex.html
Есть отличные учебные пособия, чтобы заставить себя стать самим загрузчиком. Также вы можете присоединиться к каналу #osdev в freenode, чтобы присоединиться к обсуждению, если вам нужна дополнительная информация.
Ответ 2
Позвольте мне предположить много вещей здесь: вы хотите запустить свой загрузчик в системе x86, у вас есть gcc toolchain, установленный в поле * nix.
При написании загрузчика необходимо учитывать некоторые моменты:
- ограничение 510 байтов для VBR, еще меньшее для MBR из-за таблицы разделов (если ваша система нуждается в ней)
- реальный режим - 16-битные регистры и сегрегированная адресация
- загрузчик должен быть плоским двоичным кодом, который должен быть связан для запуска на физическом адресе 7c00h
- ссылки на внешнюю "библиотеку" (duh!)
теперь, если вы хотите, чтобы gcc вывел такой двоичный файл, вам нужно сыграть с ним некоторые трюки.
- gcc по умолчанию разбивает 32-битный код. Чтобы иметь код вывода gcc, который будет запускаться в реальном режиме, добавьте
__asm__(".code16gcc\n")
вверху каждого файла C.
-
gcc выводит скомпилированные объекты в ELF. Нам нужен бит, который статически связан в 7c00h. Создайте файл 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 */
}
}
-
напишите свой код загрузчика в 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
-
Поскольку у вас уже есть встроенные загрузчики с ASM, я думаю, что остальное вам очевидно.
-
взято из моего блога: http://dc0d32.blogspot.in/2010/06/real-mode-in-c-with-gcc-writing.html
Ответ 3
Загрузочный загрузчик написан в ASM.
При компиляции кода C (или С++ или любого другого) компилятор "преобразует" ваш человекообразный код в машинный код. Поэтому вы не можете быть уверены в результатах.
Когда компьютер загружается, BIOS выполняет код с определенного адреса.
Этот код должен быть выполнен непосредственно.
Вот почему вы будете использовать сборку.
Это единственный способ иметь не измененный код, который будет выполняться как написанный процессором.
Если вы хотите запрограммировать код на C, вам все равно придется закодировать загрузчик ASM, который будет правильно загружать машинный код, сгенерированный используемым вами компилятором.
Вам нужно понять, что каждый компилятор будет генерировать разные машинные коды, которым может потребоваться предварительная обработка перед выполнением.
BIOS не позволит вам предварительно обработать ваш машинный код. Загрузка ПК - это просто переход к месту памяти, то есть машинный код, расположенный в этом месте, будет выполняться непосредственно.
Ответ 4
Поскольку вы используете GCC, вы должны прочитать информационные страницы о разных "целевых средах". Скорее всего, вы захотите использовать флаг -ffreestanding. Также мне пришлось использовать флаги -fno-stack-protector, чтобы избежать некоторой уродливой магии компилятора.
Затем вы получите ошибки компоновщика, говорящие, что memset и т.д. не найдены. Поэтому вы должны реализовать свою собственную версию и связать их.
Ответ 5
Я пробовал это несколько лет назад - варианты, возможно, изменились.
Вам нужно запустить gcc
с помощью -ffreestanding
(не ссылаться), а затем связать с помощью ld
с флагами -static
, -nostdlib