What causes “x.asm:(.text+0xd): undefined reference to `y'”?

心不动则不痛 提交于 2021-01-27 16:10:43

问题


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 in boot.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 assemble boot.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 to final.bin with LD, you can convert final.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 is 0x1badb002 not 0xbad. Since you haven't specified a video configuration in your Multiboot header FLAGS 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!