Real Mode: Difference between revisions

From OSDev.wiki
Jump to navigation Jump to search
[unchecked revision][unchecked revision]
Content added Content deleted
(Fixed pseudocode (it was totally broken), added a note to the example code.)
Line 146: Line 146:


=== External Links ===
=== External Links ===
* [http://www.osdever.net/tutorials/rm_addressing.php?the_id=50 The Workings of: x86-16/32 RealMode Addressing]
* [http://www.osdever.net/tutorials/rm_addressing.php?the_id=50 The Workings of: x86-16/32 RealMode Addressing] (2003) / [http://therx.sourceforge.net/osdev/files/ia32_rm_addr.pdf The workings of IA32 real mode addressing and the a20 line] (2004)


[[Category:X86 CPU]]
[[Category:X86 CPU]]

Revision as of 05:57, 8 February 2009

Real mode is the initial 16 bit operating mode of all x86 Intel processors (and clones). Its presence in modern x86 CPUs is required for backwards compatibility with pre-80386 processors and applications.

"negatives"

  • less than 1M of RAM is available for use
  • there is no hardware based memory protection (GDT), or virtual memory
  • there is no way to restrict the instructions that any user program can execute
  • the default CPU operand length is only 16 bits
  • AX, CX, and DX are no longer "general purpose" registers -- they cannot be used for addresses
  • the memory addressing modes are different and more complicated
  • modern compilers cannot generate code that is compatible with Real mode
    • (so you either have to find a very old compiler, or use Assembly)

"positives"

  • the BIOS functions implemented in the system's BIOS all work
  • the BIOS has drivers to handle all the hardware for you

All modern operating systems (Windows, Linux) run in Protected Mode, due to the many limitations and problems that Real mode presents. Older OSes (DOS) and programs ran in Real mode because it was the only operating mode available at the time. For information on switching from Real mode to Protected mode, see the Protected Mode article.

Note: There is a mode called Virtual 8086 Mode which allows OSes running in Protected mode to emulate the Real mode segmented model for individual applications. This can be used to allow a Protected mode OS to still have access to BIOS functions, when needed.

Real Mode Memory Addressing

In Real mode, there is a little over 1M of "addressable" memory (including the High Memory Area). See Detecting Memory (x86) and Memory Map (x86) to determine how much is actually usable. The usable amount will be much less than 1M. Memory access is done using segmentation via a segment:offset system.

There are six 16 bit segment registers: CS, DS, ES, FS, GS, and SS. When using segment registers, addresses are given with the following notation, where Segment is a value in a segment register, and Offset is a value in a valid address register (ie. not AX, CX, or DX):

   12F3:4B27
    ^     ^
Segment  Offset

Segments and Offsets are related to physical addresses by the equation:

PhysicalAddress = Segment * 16 + Offset

Thus, 12F3:4B27 corresponds to the physical address 0x17A57. Any physical address can be represented in multiple ways, with different Segments and Offsets. For example, physical address 0x210 can be 0020:0010, 0000:0210, or 0021:0000.

The Real Mode Stack

SS and SP are 16-bit segment:offset registers that specify a 20-bit physical address (described above), which is the current "top" of the stack. The stack stores 16 bit words, grows downward, and must be aligned on a word boundary. It is used every time a program does a PUSH, POP, CALL, INT, or RET opcode, and also when the BIOS handles any hardware interrupt (which happens 18 times a second, at least).

High Memory Area

If you set DS (or any segment register) to a value of 0xffff, it points to an address that is 16 bytes below 1M. If you then use that segment register as a base, with an offset of 0x10 to 0xffff, you can access physical memory addresses from 0x100000 to 0x10ffef. This (almost 64K) area above 1Mb is called the High Memory Area, in Real mode.

SIB Modes

In Assembly language, SIB modes are the complicated memory addressing modes, such as [ES:ecx + eax*8 - 0x1000000]. In Real mode, the selection of "encodable" SIB modes is much more limited than in Protected Mode:

  • [BX + val]
  • [SI + val]
  • [DI + val]
  • [BP + val]
  • [BX + SI + val]
  • [BX + DI + val]
  • [BP + SI + val]
  • [BP + DI + val]
  • [val]

Notes: You can still specify any segment for each mode. -32768 <= val <= 32767

Switching from Protected to Real mode

As noted above, it is possible for a Protected mode OS to use "V86" (Virtual 8086) mode to access BIOS functions. However, V86 mode has its own complications and difficulties. Some OS designers think that it is simpler and cleaner to temporarily return to Real mode on those occasions when it becomes necessary to access a BIOS function. This requires creating a special Ring 0 program, and placing it in a physical memory address that can be accessed in Real mode.

The OS needs to pass an information packet about which BIOS function to execute, with specified data.

The program needs to:

  1. turn off interrupts,
  2. turn off paging
  3. perform a "far jump" to set CS with real-mode like values
  4. reload the other segment registers with real-mode values
  5. turn off protected mode
  6. point IDTR to the real mode IVT
  7. set up a Real mode stack,
  8. set up the the registers needed for the bios call
  9. execute the requested BIOS function,
  10. save all the "return values" from the BIOS function in memory somewhere
  11. turn Protected mode back on,
  12. do a "far jump" to set CS to a legal value,
  13. if needed (depending on your kernel):
    • reload segment registers
    • re-enable paging
    • point IDTR back to the protected mode IDT and enable interrupts
  14. get back the return values
  15. and "exit"

x86 Examples

[bits 16]

idt_real:
	dw 0x3ff	; 256 entries, 4b each = 1K
	dd 0		; Real mode IVT @ 0x0000

savcr0:
	dd 0	; storage location for pmode CR0

Entry16:
        ; we are already in 16-bit mode here!
	cli			;Disable interrupts
; Need 16bit pmode gdt entries!
	mov eax, DATASEL16	;16 bit pmode data selector
	mov ds, eax
	mov es, eax
	mov fs, eax
	mov gs, eax
;Disable paging works because it must be a 1:1 mapping
	mov eax, cr0
	mov [savcr0], eax	; save pmode CR0
	and eax, 0x7FFFFFFe	; Disable paging bit & enable 16-bit pmode
	mov cr0, eax
	jump 0:GoRMode		; Perform Far jump to set CS
GoRMode:
	mov sp, 0x8000		; pick a stack pointer
	mov ax, 0		; Reset segment registers to 0
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	lidt [idt_real]
	sti		; Restore interrupts -- be careful, unhandled int's will kill it

See Also

Articles

External Links