10 ms·
Show HN: A simple way to write standalone C programs for i386
- jmpman 7y agoAwesome. I’ve wondered the same. Thanks for the tutorial.
- ngcc_hk 7y agoToday is not the best day as a HongKonger. But that is a good source and I put aside when I have the heart and soul as a 386 hacker. God bless. Good work.
- saagarjha 7y agoThe code was surprisingly short and readable. If you have a minute, I’d suggest taking a peek; it’s pretty well designed.
- frank_nitti 7y agoVery refreshing approach, as someone deeply interested in this topic but without the time to dive in to the docs myself
- tus88 7y ago> they only work in the real-address mode So it's not for i386, it's for XT by the sounds of it.
- Crinus 7y agoXT implies 8086 and there are more real address mode instructions than those available in 8086. AFAIK real address mode can use pretty much any 32bit instructions with a prefix, which is what this project is doing. (this incompatibility bit me a bit many years ago when i was writing a small real mode OS in assembly - i used a bunch of instructions i thought were available in 8086 but when i tried the OS on a real XT machine it would lock up :-P)
- qx89l4 7y agoTargeting 8086-level of instructions was actually my first idea. It wasn't possible with gcc/clang, but Turbo C is freeware these days, so... ;) In case you're interested, see https://github.com/luke8086/nf/ https://github.com/luke8086/nf/
- oso2k 7y agoHave you tried running `nf` or `boot2c` against NuXT [0] or Nano8088 [1]? [0] https://monotech.fwscart.com/NuXT_-_MicroATX_Turbo_XT_-_955MHz_832K_RAM_XT-CF_SVGA_Floppy_Serial/p6083514_19777986.aspx https://monotech.fwscart.com/NuXT_-_MicroATX_Turbo_XT_-_955M... [1] https://monotech.fwscart.com/Nano_8088_-_Turbo_XT_SBC_CompactFlash_832K_RAM_PS2_keyboard_64K_ROM/p6083514_19478757.aspx https://monotech.fwscart.com/Nano_8088_-_Turbo_XT_SBC_Compac...
- qx89l4 7y agoHadn't heard of them, thanks for the links!
- ofrzeta 7y agoYou could also use OpenWatcom, I think. https://github.com/open-watcom/open-watcom-v2 https://github.com/open-watcom/open-watcom-v2
- Crinus 7y agoAs someone mentioned below you could also use OpenWatcom, if for no other reason than it should have a slightly better optimizer (though from my tests i haven't seen much of a difference between the two, at least for code i tried to optimize a lot myself). AFAIK one of the OWv2 contributors is working on a 16bit OS so the 16bit support should be excellent. OWv2 is also available as a Linux binary so you could use it for crosscompiling in a similar way to GCC.
- qx89l4 7y agoGood point, OpenWatcom is obviously miles ahead of Turbo C, but it's also much more complex. I tinkered with it for a while, and ended up using the latter for its simplicity. DOSBox can be easily installed on any system, you can save the entire C: in a git repo and it'll probably keep working in any number of years from now :) Meanwhile, OWC doesn't have packages in popular Linux distros, only a custom binary installer, and on MacOS it doesn't even have that.
- rwmj 7y agoNo, he's using -m16 -march=i386 which creates 32 bit code that boots in 16 bit mode using the 32 bit size prefix on most instructions, and that will only work on 80386 and above.
- jacobush 7y agoThis is so insane, I had no idea such a thing was possible: 16 vs 32 bit It is possible to use 32-bit instructions in the real-address mode, they just need to be marked with address-size and operand-size prefixes. The -m16 option for clang/gcc, and .code16 directive in GNU assembler, do exactly that. The resulting code is 32-bit, only marked everywhere with those prefixes. It's not compatible with actual 16-bit CPUs. "Unfortunately the 32-bit addresses still cannot exceed the boundary of the segment (65535), otherwise they'll trigger an exception. QEMU doesn't emulate this behaviour, so it's useful to occasionally test with Bochs."
- deleted 7y ago[deleted]
- dexen 7y ago>> they only work in the real-address mode Presumably it would work just fine in the "Unreal mode"[1] - one which is very similar to real, with the added benefit of being 32bit address space, and 32bit instructions by default [1] https://en.wikipedia.org/wiki/Unreal_mode https://en.wikipedia.org/wiki/Unreal_mode
- qx89l4 7y agoI'm not sure if defaulting to 32-bit instructions would still allow calling BIOS, but good point! In this case the design goal was to show the easiest way to jump into C and start building the actual application, so I just tried to avoid any trickery (even enabling the A20 line)
- PixelOfDeath 7y agoYou just set your chosen segment register(s) in protect mode, jump back to real mode, and then can use this segment register(s) in combination with the 32bit prefix to make a 32 bit memory access. All other segment registers are untouched and you can call into the bios just fine.
- dusted 7y agoThat's neat :)
- rwmj 7y agoWe actually wrote an optionrom in C for qemu a few years back. The main challenge was making it work on all the different C compilers that qemu supports because it makes some assumptions about the layout of the final binary which are not necessarily true for modern optimizing compilers. Anyhow if ever use qemu on x86 with the -kernel option then you are running this code. https://git.qemu.org/?p=qemu.git;a=blob;f=pc-bios/optionrom/linuxboot_dma.c https://git.qemu.org/?p=qemu.git;a=blob;f=pc-bios/optionrom/...
- qx89l4 7y agoI feel your pain, so sorry that you still need to support the .code16gcc hack! My first approach was actually to avoid GCC/clang altogether, and use Turbo C instead. It came with its own set of problems, but the output was much more predictable. In case you're interested, you can find the code at https://github.com/luke8086/nf https://github.com/luke8086/nf
- oso2k 7y agotkchia [0] has been working on getting gcc to emit 16-bit clean code (no 32-bit code prefixes) along with ancillary tooling like binutils, a couple different libc's, and some of the things you'd expect from a 16-bit x86 C compiler like far pointers and DOS-specific libc functions [0]. The use case is to build the FreeDOS Kernel and ELKS 16-bit Linux Kernel from a 32-bit or 64-bit Linux system. [0] https://github.com/tkchia/gcc-ia16 https://github.com/tkchia/gcc-ia16 [1] https://github.com/tkchia/build-ia16/releases https://github.com/tkchia/build-ia16/releases
- ape4 7y ago640KB ought be enough memory for anyone - Bill Gates
- pacaro 7y ago"I've said some stupid things and some wrong things, but not that. No one involved in computers would ever say that a certain amount of memory is enough for all time." An actual Bill Gates quote
- ape4 7y agoIf you could get a TCP/IP stack working, it could be used for a simple IoT device.
- Udo 7y agoI wonder what a minimal version of this would look like for x64 UEFI machines. Does anyone know whether such a project exists?
- dantle 7y agoIt's pretty easy. With CL.exe (Microsoft's Visual Studio compiler) just use the /SUBSYSTEM:EFI_APPLICATION flag. You may have to manually specify the entry point. Note that there's no default cstdlib, so if you want to use the EFI APIs (e.g. for a "printf" function or other things from the article), you'll need to tell the compiler about the header definitions (as you would any C API).
- peteradio 7y agoComes with snake.
- ColanR 7y agoIf the available RAM were somehow expanded to the full amount available in hardware, it seems like this could be an interesting type of HPC system. No bloat, simple execution.
- Accujack 7y agoMillennial discovers DOS. Film at 11. ;)
- blacksmith_tb 7y agoIt's running only on BIOS, no operating system.
- Accujack 7y agoThat's literally what DOS is... a loading program that itself ran from a boot sector and provided services layered on top of BIOS calls.
- qx89l4 7y agoI "discovered" DOS 25 years ago, not sure what's your point?
- blacksmith_tb 7y agoSorry, I read your comment as "he's running this on DOS" not "he's made something that runs at the same level as DOS".
- nodefourtytwo 7y agoIsn't that a unikernel [0]? I've been wanting to try Hermitcore [1] for a while. [0] https://en.wikipedia.org/wiki/Unikernel https://en.wikipedia.org/wiki/Unikernel [1] https://github.com/hermitcore/libhermit https://github.com/hermitcore/libhermit