Compiling x86 and c with a makefile

I have been writing C for 2-3 years and have recently put together a build, but since I am using Windows, I have never had to use makefiles before since I just used Visual Studio. I am trying to use Cygwin and the i686 cross compiler to compile c and build files and then bundle them into a binary representing my operating system. I'm new to creating files, so I don't know how to do this. This is what I have so far for Makefile

:

CC = i686-elf-gcc
CC_FLAGS = -c -std=gnu99 -ffreestanding -O2 -Wall -Wextra -I./include
AS = i686-elf-as
LD = i686-elf-gcc -T linker.ld -o myos.bin
LD_FLAGS = -ffreestanding -O2 -nostdlib -lgcc
O_FILES = $(wildcard src/*.o)

all: $(O_FILES)
    $(LD) $(LD_FLAGS) $(O_FILES)

src/%.o: src/%.c
    $(CC) $(CC_FLAGS) -o $@ $<

src/%.o: src/%.asm
    $(AS) -o $@ $<

      

I am getting a message that the linker cannot find the input character _start

, so obviously nothing is compiling. How can I fix this?

My src/linker.ld

file that defines _start

as entry point:

ENTRY(_start)

SECTIONS
{
        . = 1M;

        .text BLOCK(4K) : ALIGN(4K)
        {
                *(.multiboot)
                *(.text)
        }

        .rodata BLOCK(4K) : ALIGN(4K)
        {
                *(.rodata)
        }

        .data BLOCK(4K) : ALIGN(4K)
        {
                *(.data)
        }

        .bss BLOCK(4K) : ALIGN(4K)
        {
                *(COMMON)
                *(.bss)
        }
}

      

The file src/boot.asm

I'm using that defines my label _start

:

# Declare constants for the multiboot header.
.set ALIGN,    1<<0             # align loaded modules on page boundaries
.set MEMINFO,  1<<1             # provide memory map
.set FLAGS,    ALIGN | MEMINFO  # this is the Multiboot 'flag' field
.set MAGIC,    0x1BADB002       # 'magic number' lets bootloader find the header
.set CHECKSUM, -(MAGIC + FLAGS) # checksum of above, to prove we are multiboot

.section .multiboot
.align 4
.long MAGIC
.long FLAGS
.long CHECKSUM

.section .bss
.align 16
stack_bottom:
.skip 16384 # 16 KiB
stack_top:

.section .text
.global _start
.type _start, @function
_start:
        mov $stack_top, %esp

        call kernel_main

        cli
1:      hlt
        jmp 1b

.size _start, . - _start

      

+3


source to share


1 answer


You will need to change yours Makefile

to something like this:

CC = i686-elf-gcc
AS = i686-elf-as
LD = i686-elf-gcc
AS_FLAGS =
LD_FLAGS = -ffreestanding -nostdlib -lgcc -Tlinker.ld
CC_FLAGS = -c -std=gnu99 -ffreestanding -O2 -Wall -Wextra -I./include

C_FILES := $(wildcard src/*.c)
ASM_FILES := $(wildcard src/*.asm)
O_FILES := $(C_FILES:.c=.o) $(ASM_FILES:.asm=.o)
KERNEL_BIN := myos.bin

all: $(KERNEL_BIN)

clean:
        rm -f $(KERNEL_BIN) $(O_FILES)

$(KERNEL_BIN): $(O_FILES)
        $(LD) $(LD_FLAGS) -o $@ $^

%.o: %.c
        $(CC) $(CC_FLAGS) -o $@ $<

%.o: %.asm
        $(AS) $(AS_FLAGS) -o $@ $<

      

This one Makefile

differs in that we create a list of ASM files and C files. I also cleaned up a bit LD_FLAGS

and added an additional rule for creating myos.bin

both clean

object and bin files.

In your current code, you will have Makefile variables with this in them after expansion:

C_FILES   = src/string.c src/tty.c src/kernel.c
ASM_FILES = src/boot.asm
O_FILES   = src/string.o src/tty.o src/kernel.o src/boot.o

      



O_FILES

was obtained by combining the two file lists and replacing the extensions .c

and .asm

with .o

. This is a list of all objects that should be generated from the source files.

The GNU Assembler usually uses files with extensions .s

(or .s

if you want to use the C preprocessor) rather than.asm


The reason the label was _start

not found is because the assembly files were not processed. This means that he boot.asm

did not become boot.o

and, therefore, was not connected at all.

+1


source







All Articles