#gcc #сборка #os #osdev #ld
Я пытался написать примитивную ОС по урокам "Bare Bones" на osdev wiki. Проблема
заключается в том, что даже на самом начале ld выдает ошибку, что главная функция ядра,
_kmain, не определена. Итак, вот код:
kernel.cpp
void _kmain() {
return;
}
boot.asm
; This file is loaded by GRUB, Protected Mode is already enabled
; Multiboot constants
MBALIGN equ 1<<0
MEMINFO equ 1<<1
FLAGS equ MBALIGN | MEMINFO
MAGIC equ 0x1BADB002
CHECKSUM equ -(MAGIC+FLAGS)
; Multiboot header
section .multiboot
align 4 ; Yes, I know, it's not necessary
dd MAGIC
dd FLAGS
dd CHECKSUM
; Bootloader stack (we'll use another stack for OS, of course)
section .bootstrap_stack, nobits
align 4
stack_bottom:
resb 16384 ; 16K of stack, seems enough for a bootloader
stack_top:
section .text
global _start
_start:
mov esp, stack_top ; Stack grows in a backwards direction
extern _kmain
call _kmain
cli ; If _kmain returns, we will halt the computer
.halt:
hlt
jmp .halt
Makefile
ASM=nasm
ASM_FLAGS=-felf32
CC=/home/alexander/opt/cross/bin/i686-elf-g++
CFLAGS=-ffreestanding -Wall -Wextra
LINKER=/home/alexander/opt/cross/bin/i686-elf-gcc
LFLAGS=-ffreestanding -nostdlib -lgcc -T linker.ld
all: boot.o kernel.o
$(LINKER) $(LFLAGS) -o kernel.bin $^
boot.o:
$(ASM) $(ASM_FLAGS) boot.asm -o boot.o
kernel.o:
$(CC) $(CFLAGS) -c kernel.cpp -o kernel.o
screen.o:
$(CC) $(CFLAGS) -c screen.cpp -o screen.o
clean:
rm *.o
rmbaks:
rm *~
linker.ld
ENTRY(_start)
SECTIONS {
. = 1M;
.text BLOCK(4K) : ALIGN(4K) {
*(.multiboot)
*(.text)
}
.rdata BLOCK(4K) : ALIGN(4K) {
*(.rdata)
}
.data BLOCK(4K) : ALIGN(4K) {
*(.data)
}
.bss BLOCK(4K) : ALIGN(4K) {
*(COMMON)
*(.bss)
*(.bootstrap_stack)
}
}
Вывод после запуска make:
nasm -felf32 boot.asm -o boot.o
/home/alexander/opt/cross/bin/i686-elf-g++ -ffreestanding -Wall -Wextra -c kernel.cpp
-o kernel.o
/home/alexander/opt/cross/bin/i686-elf-gcc -ffreestanding -nostdlib -lgcc -T linker.ld
-o kernel.bin boot.o kernel.o
boot.o: In function `_start':
boot.asm:(.text+0x6): undefined reference to `_kmain'
collect2: error: ld returned 1 exit status
make: *** [all] Ошибка 1
P.S. В screen.cpp всякие полезные функции для работы с дисплеем, но он не используется.
Ответы
Ответ 1
На самом деле все просто упирается в компилятор. У Вас g++ (а не gcc). По умолчанию g++ формирует имена функций (те, что мы можем увидеть командой nm kernel.o) с учетом типа функции и параметров. Так, вместо ожидаемого _kmain, в .o получается _Z6_kmainv. Если Вы все еще хотите продолжать упражнения с С++, то придется явно сказать компилятору, что нужны имена функций в "сишном стиле". Для этого достаточно написать прототипы функций в специальном блоке: extern "C" { void _kmain(void); // это наш случай }; Если хотите, чтобы код без изменений (конечно, остальные его части тоже должны быть совместимы как с Си, так и с C++) компилировался также и gcc, то придется добавить немного директив препроцессора (к счастью он одинаков для g++/gcc) #ifdef __cplusplus extern "C" { #endif void _kmain(void); ... #ifdef __cplusplus }; #endif
Комментариев нет:
Отправить комментарий