Created attachment 16335 [details] asmorder.c Firstly, I realize here that I'm operating well outside any C standards or guarantees of any sort. But this stuff is useful for some people. If you want to write a PC BIOS option ROM in C, you can do it in gcc using asm statements at the module level of the C file, at the start and end. These asm statements contain the option ROM header and trailing and effectively "bracket" the C code in the middle. (See attached example). This can be compiled using: gcc -m16 -c asmorder.c ld -m elf_i386 -Ttext 0 -e _start -s -o asmorder.img asmorder.o objcopy -O binary -j .text asmorder.img asmorder.bin to produce the option ROM (I missed out a step for computing the checksum of the ROM but it's not relevant for this discussion). If you disassemble the object file, you'll see that the order of the start & end asm statements is preserved, and the size of the file in the header is computed correctly: objdump -d asmorder.o However this does not work if you substitute clang for gcc. The problem is that clang reorders the module level asm statements, putting them all at the start of the file, and so the option ROM format isn't recognized. In short, gcc converts: asm("some stuff"); some_C_functions; asm("more stuff"); into: some stuff assembler of some_C_functions more stuff but clang turns it into: some stuff more stuff assembler of some_C_functions Note I'm not using any optimization. It would be nice if clang didn't do that, at least for asm statements appearing at the beginning and end of the file. gcc-6.0.0-0.20.fc24.x86_64 (also works in gcc 4 & 5) clang-3.8.0-1.fc24.x86_64
This is an old, known difference between GCC and LLVM, although -fno-toplevel-reorder is long gone in GCC. In LLVM, functions, globals, aliases, and asms are all maintained in separate lists, so it is difficult to emit them in source order. The good news is that your issue really seems to be .code16 related, which we are actively working to support as a compiler pragma. *** This bug has been marked as a duplicate of bug 6364 ***
(In reply to comment #1) > The good news is that your issue really seems to be .code16 related, which > we are actively working to support as a compiler pragma. Could you expand on what you mean by this?
> The good news is that your issue really seems to be .code16 related, > which we are actively working to support as a compiler pragma. It's not, it really requires the prolog and epilog to be at the beginning and the end respectively. Anyway, -fno-toplevel-reorder is definitely still there in GCC. I'm not sure why you said here that it's "gone" and in PR6364 that it's "deprecated".
(In reply to comment #3) > > The good news is that your issue really seems to be .code16 related, > > which we are actively working to support as a compiler pragma. > > It's not, it really requires the prolog and epilog to be at the beginning > and the end respectively. It's easy to achieve this in other ways, though, such as a linker order file. > Anyway, -fno-toplevel-reorder is definitely still there in GCC. I'm not > sure why you said here that it's "gone" and in PR6364 that it's "deprecated". My bad, it does exist: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html I actually did search for it, but it took me a while to remember the right name. :) Anyway, the status is that we need to do *something* to enable writing a BIOS. We are not an assembly emitting compiler, though, so it may not look exactly like what GCC has with -fno-toplevel-reorder.
A linker script or similar is a bit overengineered for a single 200-line file. If we have a guarantee that the block at the beginning stays there, that's already something. We have a small postprocessing pass to fill in a checksum; we can modify that to remove the need for the final asm block.