I'm writing a small OS with a 16-bit bootloader and a 32-bit kernel in C.
Everything worked fine with just screen-related code.
But as soon as I add the keyboard-related files (IDT setup, IRQs, keyboard handler…), the kernel stops working — even if none of the functions are called.
Simply compiling those files seems to break everything.
If I remove them, it works again.
Could this be a linker issue, memory alignment problem, or corrupted binary?
Is it possible that unused globals or sections shift _start or break execution?
GitHub:
👉 https://github.com/arnaudderison/picos
Kernel stops executing after adding keyboard-related code, even if unused
Re: Kernel stops executing after adding keyboard-related code, even if unused
This normally means that you are not loading the whole kernel. Are you sure you are loading enough sectors?
-
MichaelPetch
- Member

- Posts: 857
- Joined: Fri Aug 26, 2016 1:41 pm
- Libera.chat IRC: mpetch
Re: Kernel stops executing after adding keyboard-related code, even if unused
A quick glance at your Makefile and linker.ld file suggest one potential problem that could produce the results you are seeing. You have a kernel_entry.asm file that gets compiled to kernel_entry.o . Since you are jumping to 0x00001000 in your bootloader you need to ensure the code in kernel_entry.o appears first in kernel.bin. Often this is done in the Makefile by specifying kernel_entry.o first before other .o files. Your makefile however doesn't guarantee any order that the object files are linked as it is whatever order the file system and `make` returns. Likely kernel_entry.o isn't first. Some other code from another .o is appearing first.
One quick way of testing this is to modify the linker.ld script to place the `.text` section of kernel_entry.o first before all other code. Try testing with something like:Another option is to list kernel_entry.o first during linking with something like this change to your Makefile:This works even though kernel_entry.o will appear twice on the linker command line. LD will not generate duplicate code and data when encountering the same object more than once.
`ENTRY` in the linker script doesn't apply to BINary executables. The metadata is stripped out of the binary including the entry point. This leaves you needing to make sure that the kernel bootstrap code appears first in the resulting binary file.
One quick way of testing this is to modify the linker.ld script to place the `.text` section of kernel_entry.o first before all other code. Try testing with something like:
Code: Select all
ENTRY(_start)
SECTIONS {
. = 0x1000;
.text : {
build/kernel/kernel_entry.o(.text)
*(.text)
}
.data : {
*(.data)
}
.bss : {
*(.bss COMMON)
}
rodata : {
*(.rodata*)
}
}Code: Select all
kernel.bin: $(OBJ_ASM) $(OBJ_S) $(OBJ_C) linker.ld
$(LD) $(LDFLAGS) -o $@ $(BUILD_DIR)/kernel_entry.o $(OBJ_ASM) $(OBJ_S) $(OBJ_C)
$(OBJCOPY) -O binary $@ $@`ENTRY` in the linker script doesn't apply to BINary executables. The metadata is stripped out of the binary including the entry point. This leaves you needing to make sure that the kernel bootstrap code appears first in the resulting binary file.
