Dropping to Real Mode
Posted: Thu May 17, 2007 2:05 am
OK, I'm trying to drop back to real mode from my kernel (so I can do BIOS calls). Unfortunately, it doesn't work... LD gives me the following error:
The assembly code which causes this is assembled with NASM in ELF format:
I'm stumped. Any ideas?
Code: Select all
C:\***\realmode.o(.text+0x16): relocation truncated to fit: R_386_16 t
ext
C:\***\realmode.o(.text+0x32): relocation truncated to fit: R_386_16 t
ext
C:\***\realmode.o(.text+0x3d): relocation truncated to fit: R_386_16 _
gp
C:\***\realmode.o(.text+0x48): relocation truncated to fit: R_386_16 t
ext
Code: Select all
; 32-bit
bits 32
; globals
global _enter_rm
; external stuff
extern _gp
; enters real mode, does stuff, comes back to pmode
_enter_rm:
; don't allow any interrupts!
cli
; push everything
pushad
; jump to the 16-bit code segment
jmp 0x18:do16
; 16-bit now!
bits 16
do16:
; load the new segments
mov ax,0x20
mov ds,ax
mov ss,ax
; get the new segments initialized
nop
; push the CS:IP for the real mode task
push 0x18
lea bx,[realmode]
push bx
; enter real mode
mov eax,cr0
and al,0xFE
mov cr0,eax
; far jump
retf
; Real mode task
realmode:
; load real-mode segments
mov ax,cx
mov ds,ax
mov ss,ax
nop
mov es,ax
mov fs,ax
mov gs,ax
; load the real-mode idt
lidt [ridtr]
; set ds and es
push cs
pop ds
push ds
pop es
; allow interrupts now
sti
; do what needs to be done in real mode
; no more interrupts
cli
; load the pmode GDT again
lgdt [_gp]
; set the PE bit in the CR0 field
mov eax,cr0
or al,1
mov cr0,eax
; jump to the flush part
jmp 0x08:flush2
; back to 32-bit now
bits 32
; load new segment descriptors
flush2:
; 0x10 is the data segment
mov ax,0x10
mov ds,ax
mov ss,ax
nop
mov es,ax
mov fs,ax
mov gs,ax
; pop everything
popad
; return
ret
; real-mode IDTR - this points to the IVT
ridtr: dw 0xFFFF ; limit=0xFFFF
dd 0 ; base=0