"Flat model" is simply unsegmented linear address space (3.2.1).
https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.pdf
This is processor's definition of flat model. And OS defines flat memory model, "tiny" memory model, as well.
(in my own experience, I never felt flatness in "tiny" model")
If I stand processor's definition - when you particularly say Real-mode flat model, I guess that's unprotected mode (= real mode) with linear widen address space (up to 4GB).
Once you entered protected mode, set GDT up, then you return to real mode. That's it.
- It depends. Today I answer 'NO' for 1st of the questions. Because one segment's extendable up to 32bit (4GB) in 386. If "rela mode flat model" means "tiny"-memory model and it's only on 16bit-processor, this answer was YES.
- Yes. A x86 16bit processor has linear address space up to 1MB (if A20line is asserted). But an address area where's accessible w/o segmentation is only 64KB because almost such processors don't support a segment descriptor. Note that 286, 16bit processor, can enter to protected mode.
- If I stand Intel's definition of "flat" model, a samples is memtest86+ https://www.memtest.org/ . freedos may be for real mode segmented model. PC-UNIXs are protected mode segment model. protected mode flat model's sample is ... some RTOS? I don't know.
memtest86+ head.s:
first 4 entries of GDT are 4GB-wide:
GDT, Global Descriptor Table is the table of segment descriptor, {BASE, PAGES, MODE}.
The entry's pointed by segment register, and now segment register is NOT a apart of effective address.
gdt:
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x0000000000000000 /* not used */
.quad 0x00cf9b000000ffff /* 0x10 main 4gb code at 0x000000 */
.quad 0x00cf93000000ffff /* 0x18 main 4gb data at 0x000000 */
returning to real mode. and all segment registers are unified.
.code16
/* Disable Paging and protected mode */
/* clear the PG & PE bits of CR0 */
movl %cr0,%eax
andl $~((1 << 31)|(1<<0)),%eax
movl %eax,%cr0
/* make intersegment jmp to flush the processor pipeline
* and reload %cs:%eip (to clear upper 16 bits of %eip).
*/
ljmp *(realptr - RSTART)
real:
/* we are in real mode now
* set up the real mode segment registers : %ds, %ss, %es, %gs, %fs
*/
movw %cs, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss