SomeGuyWithAKeyboard wrote:
I actually made a command line system with c++ and g++ but it doesn't work on my 486 for some reason despite working on qemu even with -cpu 486-v1.
Usually when code works on QEMU but not on bare metal, it's because QEMU doesn't enforce segment limits. It could also be something else, such as missing initialization. Try Bochs - it has a log that will show you if the problem is segment limit violations.
SomeGuyWithAKeyboard wrote:
It also doesn't work on newer stuff because newer bioses are smart enough to see my bootloader, be like "nah, I ain't booting from that non-standardized trash" and just act like the drive isn't bootable.
If you're trying to boot from USB, your drive needs to either be partitioned like a bootable hard disk or FAT-formatted like a floppy disk. Your current code is neither of those things. (If you're trying to boot from a CF card in a CF-to-IDE adapter, your CF card might identify itself in a way that's incompatible with the BIOS.)
SomeGuyWithAKeyboard wrote:
From my understanding, in nasm using global allows you to access an assembly subroutine from c/c++ (if all your linking is set up correctly) and extern is for accessing c/c++ functions from assembly, if your linking stuff is set up correctly.
Not exactly.
Using global makes a symbol available to the linker, so other object files can reference that symbol. Using extern pulls the symbol from the linker, which usually (but not always) comes from another object file. A symbol is a name that the linker will replace with a number when it links your binary together. The number is usually an address, but it's possible to define symbols in your linker script that are not addresses.
SomeGuyWithAKeyboard wrote:
After some digging and further studying of the watcom documentation, I'm not entirely sure if watcom can compile to elf or not.
Which version are you using? ELF support is a relatively new feature. It also probably isn't the default object file format - you'll have to tell it you want ELF.
SomeGuyWithAKeyboard wrote:
If it truly is possible to use gcc or g++ to make limited real mode code, that might be a rabbit hole worth going doing instead but if it has to jump into protected mode, it probably won't work on the target hardware.
It is truly possible, but there are limitations. Your code (and probably stack?) is limited to a 64kB segment. Your data is not limited to 64kB, but you'll need to set up a #GP handler to enter unreal mode to access any address outside the 64kB real mode segment limit. CS, DS, ES, and SS must all contain the same value. The generated code is really just 32-bit code with appropriate prefixes to run in 16-bit mode. GCC emits code that requires a 386 at minimum; Clang emits code that requires a 486 at minimum. You'll probably need to realign your stack before calling any functions compiled with GCC/Clang.
SomeGuyWithAKeyboard wrote:
Name mangling is always a pain when I try to do things this way, I have to name my assembly side references things like _Z10helloWorldv. No one on internet posts ever mentions running into this annoyance so I wonder why I have to do that.
Most people declare functions with extern "C" to prevent name mangling.