Page 1 of 1
Protected mode from (Free)DOS
Posted: Wed Feb 20, 2013 12:31 pm
by ar5007eg
Trying to go to protected mode from a DOS .COM program. The following NASM code makes Bochs reboot:
Code: Select all
USE16
cli
xor ebx, ebx
mov bx, cs
shl ebx, 4
; Fixing GDT address on GDT header
add dword [GDT_H+2], ebx
; ebx = linear addr of PM
add ebx, PM
; setup stack for retf
push 0x8
push ebx
lgdt [GDT_H]
mov eax, cr0
or al, 1
mov cr0, eax
retf
GDT_H: dw 3*8-1
dd GDT
GDT: dw 0x0000, 0x0000, 0x0000, 0x0000
dw 0xFFFF, 0x0000, 0x9A00, 0x00CF
dw 0xFFFF, 0xFFFF, 0x9200, 0x00CF
USE32
PM:
jmp PM
PS:
- Addresses had to be fixed, since CS is nonzero in a DOS program.
- When debugging, everything goes fine until "retf". From there, it jumps to some random(?) address (f000:fff0)
Re: Protected mode from (Free)DOS
Posted: Wed Feb 20, 2013 1:14 pm
by Combuster
ar5007eg wrote:The following NASM code makes Bochs reboot
I suggest you start with reading the error messages produced by Bochs. Then probably add an ORG 0x0100 directive.
Re: Protected mode from (Free)DOS
Posted: Wed Feb 20, 2013 6:25 pm
by DLBuunk
Oh, and since you are executing the retf with a 16-bit stack segment, the stack-size is still 2 bytes, you'll be popping the upper part of ebx as code segment.
Re: Protected mode from (Free)DOS
Posted: Wed Feb 20, 2013 6:48 pm
by linguofreak
Also, there's a good chance that the cause of the reboot is that you're already in protected mode. FreeDOS has a memory manager (Jemm386 or JemmEx, if you're using FreeDOS 1.1) that provides a protected mode environment and runs DOS in a V86-mode virtual machine. While its running, you can't do a raw switch to protected mode (by writing to CR0), but have to use DPMI or VCPI services instead.
F000:FFF0 is the address that the computer starts fetching instructions from when (re)booted. Given that you say that everything goes find until "retf", and that the immediately prior instruction is "mov cr0, eax", I'll give million to one odds that "mov cr0, eax" is causing a triple-fault for the reason described in the previous paragraph.
Re: Protected mode from (Free)DOS
Posted: Wed Feb 20, 2013 7:19 pm
by ar5007eg
After putting ORG 0x100 and changing a few things it executes the "retf" instruction sucessfully, but jumps to (on my Bochs) 0x8:0x1FD5 when it should jump to 0x8:0x21FD5. When debugging, I see my "push ebx" instruction was translated to "push bx" (strangely, the opcode is still 53, not 6653). Besides, even if it were a push ebx, the "retf" instruction is poping 16-bit values, so I won't be able to jump to 0x21FD5 this way...
Any alternative in order to execute a "jmp 0x8:ebx"?
(thank you all for your comments)
@linguofreak No, I'm running with FreeDOS with the "Don't load anything" boot option on.
Re: Protected mode from (Free)DOS
Posted: Wed Feb 20, 2013 8:49 pm
by Owen
..."USE16" isn't a NASM directive. It's likely being interpreted as a label
Re: Protected mode from (Free)DOS
Posted: Thu Feb 21, 2013 2:03 am
by b.zaar
This is what I have been using in a boot loader with nasm. Should work from real mode DOS with the right GDT settings
Code: Select all
bits 16
initpm:
cli ;disable interrupts
in al,0x70
and al,0x7f
out 0x70,al ;disable NMI
; initialize pmode
lgdt [gdtptr]
mov edx,cr0
or edx,0x01
mov cr0,edx
jmp dword FLAT_CD:pmode
bits 32
pmode:
;set machine state
mov dx,FLAT_DD
mov ds,dx
mov es,dx
mov fs,dx
mov gs,dx
mov ss,dx
mov esp,0x00007c00
FLAT_CD equals 0x08 and FLAT_DD equals 0x10
Re: Protected mode from (Free)DOS
Posted: Thu Feb 21, 2013 6:30 am
by ar5007eg
My problem is that I can't use this instruction, since CS is unknown (but certainly non zero). I have to calculate the linear address of "pmode" at runtime ((cs << 4) + pmode) but I'm having trouble jumping to this runtime address because it's a 32-bit value.
Re: Protected mode from (Free)DOS
Posted: Thu Feb 21, 2013 6:46 am
by Combuster
If you use nasm, you can explicitly insert the overrides as needed:
For any dumber assembler, you'll probably have to DB the prefixes/opcodes.
Re: Protected mode from (Free)DOS
Posted: Thu Feb 21, 2013 6:59 am
by DLBuunk
ar5007eg wrote:
My problem is that I can't use this instruction, since CS is unknown (but certainly non zero). I have to calculate the linear address of "pmode" at runtime ((cs << 4) + pmode) but I'm having trouble jumping to this runtime address because it's a 32-bit value.
Perhaps self-modifying code would work?
Re: Protected mode from (Free)DOS
Posted: Thu Feb 21, 2013 7:02 am
by Combuster
At that distance it might trip the prefetch queue...
Besides, we already have a jmp far [address] to avoid the need for such bad tricks...
Re: Protected mode from (Free)DOS
Posted: Wed Feb 27, 2013 10:49 am
by ar5007eg
Thanks, it works now. I'm posting the code here just for reference.
Code: Select all
org 0x100
bits 16
cli
xor ebx, ebx
mov bx, cs
shl ebx, 4
; Fixing GDT address on GDT header
add dword [GDT_H+2], ebx
lgdt [GDT_H]
mov eax, cr0
or al, 1
mov cr0, eax
a32 add ebx, PM_START
a32 push 0x8
a32 push ebx
a32 o32 retf
GDT_H: dw 3*8-1
dd GDT
GDT: dw 0x0000, 0x0000, 0x0000, 0x0000
dw 0xFFFF, 0x0000, 0x9A00, 0x00CF
dw 0xFFFF, 0xFFFF, 0x9200, 0x00CF
bits 32
PM:
jmp PM