SomeGuyWithAKeyboard wrote:In my case I needed to load a few pointers into edx and and dx. It's not even related to linking.
Yeah it is. When you write "mov $symbol, %dx", you are instructing the assembler to issue an instruction that will reference a 16-bit symbol. The assembler will create an instruction and leave space for a 16-bit immediate in it, and write a note to the linker to fill those 16 bits with the value of the symbol. And then the linker notices that the symbol is too large. A bit weird that that's only a warning, not an error.
If you write "mov $symbol, %edx", then the assembler leaves space for a 32-bit immediate instead. The former instruction could work if the symbol had a value below 64k. However, binutils support for 16-bit relocations is spotty and buggy, because it is rarely used anymore, so most of the time you want to avoid those.
I would suggest you separate your bootloader and kernel into separate files. The bootloader's job is to find the kernel file and load it into memory. It can do that by concatenating the files when you make your disk image, but you don't have to link them together in this way. This would avoid 16-bit linking issues, and lend a bit more modularity to proceedings. You can still concatenate your kernel onto your bootloader, and have the bootloader locate the kernel by looking beyond its own end on the disk. One issue is going to be to locate the entry point of the kernel. I solve this by having the kernel image be an ELF file with a normal ELF header, including entry point. Bootloader's job is to initialize memory mappings and jump there.