问题
For a long time I had not programmed with C and Assembler (about 2 years). Now I have decided to start again but I would like to do something much more complicated. I thought about creating a simple kernel. Now I found this source code on the internet:
boot.asm:
global loader
extern kernel_main
MAGIC equ 0xbad
FLAGS equ 0x3
CHECKSUM equ -(MAGIC+FLAGS)
section .text
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
loader:
call kernel_main
cli
quit:
hlt
jmp quit
kernel.c:
void print(char *text) {
char *memory = (char*)0xb8000;
while(*text) {
*memory++ = *text++;
*memory++ = 0x3;
}
}
void kernel_main() {
print("My cat sometimes smells like cafe. I love it.");
}
linker.ld:
ENTRY(loader)
SECTIONS {
. = 0x100000;
.text : { *(.text) }
}
Note: I compiled the C file with "GCC" and the Assembler file with "NASM".
If I try this command:
ld -T linker.ld -elf_i386 -o final.bin boot.o kernel.o
It says: "boot.asm:(.text+0xd): undefined reference to `kernel_main'". How can I fix this? Im working on windows and do not want to run a VM with Linux or anything. Thanks in advance!
Edit: This is my GCC command:
gcc -m32 -o kernel.o srckernel.c -nostdlib -nostartfiles -nodefaultlibs
This is my NASM command:
nasm -f elf32 -o boot.o boot.asm
回答1:
There are a number of things wrong. I will assume given the error:
boot.asm:(.text+0xd): undefined reference to
kernel_main
that you are not using an ELF cross compiler and that you are using a GCC compiler that generates native Windows executables (ie. Cygwin and MinGW). I highly recommend the use of an i686 (or x86_64) ELF cross compiler for OS Development especially on Windows.
Your primary problems are:
The option
-elf_i386
was probably meant to be-melf_i386
however that is even incorrect. With a GCC that targets windows you will want to use-mi386pe
to output as Win32 PE/COFF format. The Windows GCC linker usually doesn't know how to generate ELF executables. I also recommend using the-N
option when using LD to output i386pe format. Change your linker command to be:ld -N -T linker.ld -mi386pe -o final.bin boot.o kernel.o
With Win32 PE/COFF objects1: functions that use the CDECL calling convention have to have an underscore (_) prepended to them.
kernel_main
needs to be_kernel_main
. You need to change these lines inboot.asm
from:extern kernel_main call kernel_main
to:
extern _kernel_main call _kernel_main
You don't show how you compile
kernel.c
and how you assembleboot.asm
but they should look similar to:nasm -f win32 boot.asm -o boot.o gcc -g -c -m32 -ffreestanding kernel.c -o kernel.o
When you do manage to generate
final.bin
it is a Windows PE executable. The Multiboot specification requires ELF executables. After linking tofinal.bin
with LD, you can convertfinal.bin
to ELF format with:objcopy -O elf32-i386 final.bin final.elf
final.elf
should now be usable as a Multiboot ELF executable.There is an issue with your Multiboot header in
boot.asm
. The Multiboot magic value is0x1badb002
not0xbad
. Since you haven't specified a video configuration in your Multiboot headerFLAGS
should not have Bit 1 set,FLAGS
should be 0x1 instead of 0x3. Change your Multiboot header from:MAGIC equ 0xbad FLAGS equ 0x3
to:
MAGIC equ 0x1badb002 FLAGS equ 0x1
With the changes noted above I was able to generate an ELF executable called final.elf
. When run with QEMU using the command:
qemu-system-i386 -kernel final.elf
The output I get is:
Footnotes:
- 1The extra underscore on function names doesn't apply when generating Win64 PE32+ objects.
来源:https://stackoverflow.com/questions/57274231/what-causes-x-asm-text0xd-undefined-reference-to-y