Is there a way to make a manually-defined io device in QEMU?

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Octocontrabass
Member
Member
Posts: 5218
Joined: Mon Mar 25, 2013 7:01 pm

Re: Is there a way to make a manually-defined io device in Q

Post by Octocontrabass »

SomeGuyWithAKeyboard wrote:Is there any way to make it only use 32 bit references?
What do you mean? You wrote the 16-bit references into that code. The assembler is only doing what you told it to do.
SomeGuyWithAKeyboard wrote:If not maybe I can find a way to put each address to each subroutine in .auxFunctions into an interrupt vector or something since I'm not getting anywhere doing it the link way.
That's a terrible idea.
SomeGuyWithAKeyboard wrote:I seem to run into less problems using plain ol' out of the box g++ on Linux than I do with any cross compiler.
I wonder about that.
SomeGuyWithAKeyboard wrote:Does using "-mgeneral-regs-only" prevent it from generating FPU instructions?
Yes.
SomeGuyWithAKeyboard
Member
Member
Posts: 27
Joined: Thu Aug 25, 2022 3:54 pm

Re: Is there a way to make a manually-defined io device in Q

Post by SomeGuyWithAKeyboard »

Octocontrabass wrote:
SomeGuyWithAKeyboard wrote:Is there any way to make it only use 32 bit references?
What do you mean? You wrote the 16-bit references into that code. The assembler is only doing what you told it to do.
OOHHHH! I get it now. The issue isn't that the c++ code can't access those functions because they're too far away or higher in memory than the first 64kb. The issue is that the address of the variables referenced by those assembly subroutines have higher memory addresses than 64kb. In my case I needed to load a few pointers into edx and and dx. It's not even related to linking.
nullplan
Member
Member
Posts: 1644
Joined: Wed Aug 30, 2017 8:24 am

Re: Is there a way to make a manually-defined io device in Q

Post by nullplan »

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.
Carpe diem!
Post Reply