I am writing real mode function, which should be normal function with stackframes and so, but it should use %sp instead of %esp. Is there some way to do it?
-
What OS is is supposed to run under? GCC doesn't support MS-DOS. – Seva Alekseyev Sep 27 '13 at 17:12
-
2Here is a minimal runnable example that prints hello world with the BIOS in 16-bit mode from C: https://github.com/cirosantilli/x86-bare-metal-examples/tree/b4e4c124a3c3c329dcf09a5697237ed3b216a318#c-hello-world – Ciro Santilli OurBigBook.com Dec 04 '18 at 08:26
4 Answers
GCC 5.2.0 (and possible earlier versions) support 16-bit code generation with the -m16
flag. However, the code will almost certainly rely on 32-bit processor features (such as 32-bit wide registers), so you should check the generated assembly carefully.
From the man
pages:
The -m16 option is the same as -m32, except for that it outputs the ".code16gcc" assembly directive at the beginning of the assembly output so that the binary can run in 16-bit mode.

- 5,785
- 1
- 22
- 22
-
2But don't forget what Michael Petch mentioned at: https://stackoverflow.com/questions/19055647/how-to-tell-gcc-to-generate-16-bit-code-for-real-mode#comment53870969_19064127 that this only uses the 16 bit prefix versions of instructions, not the bare 16 code. – Ciro Santilli OurBigBook.com Dec 03 '18 at 19:52
Firstly, gcc could build 16bit code, because the linux kernel is go through realmode to protectmode, so it could even build 16bit c code.
Then, -m16 option is supported by GCC >= 4.9 and clang >= 3.5
gcc will ignore asm(".code16"),you can see it by -S output the assembly code surround by #APP #NO_APP
the linux kernel do the trick to compile 16bit c with a code16gcc.h(only have .code16gcc) pass to gcc compile params directly.
see Build 16-bit code with -m16 where possible, also see the linux kernel build Makefile
if you direct put the asm(".code16gcc"), see Writing 16-bit Code, it's not real 16bit code, call
, ret
, enter
, leave
, push
, pop
, pusha
, popa
, pushf
, and popf
instructions default to 32-bit size

- 479
- 6
- 8
GCC does not produce 8086 code. The GNU AS directive .code16gcc
can be used to assemble the output of GCC to run in a 16-bit mode, put asm(".code16gcc")
at the start of your C source, your program will be limited to 64Kibytes.
On modern GCC versions you can pass the -m16
argument to gcc
which will produce code to run in a 16-bit mode. It still requires a 386 or later.

- 3,551
- 1
- 14
- 23
-
Documented at: https://sourceware.org/binutils/docs/as/i386_002d16bit.html#i386_002d16bit – Ciro Santilli OurBigBook.com Sep 04 '15 at 22:48
-
9Using .code16gcc (I'm still not sure one can call it a stable feature) will produce code that runs in 16 bit real mode, however it uses an instruction prefix that is only available on 386+ . This means if you are targeting 8086/8088 (real hardware or emulator) then the code will likely fail to work properly. If you intend to bootstrap entry into 32-bit protected mode then write a small 16-bit assembler stub that sets everything up, enters protected mode and then calls to a 32 bit "C" function that is the start of your program. – Michael Petch Oct 08 '15 at 19:23
-
You can of course hand code 16-bit assembler in GCC as inline assembly using __asm__ directive. – Michael Petch Oct 08 '15 at 19:29
As far as I know, GCC does not support generation of code for 16-bit x86. For legacy bootloaders and similar purposes, you should write a small stub in assembly language to put the cpu in 32-bit mode and pass off execution to 32-bit code. For other purposes you really shouldn't be writing 16-bit code.

- 208,859
- 35
- 376
- 711