Protected mode from (Free)DOS

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
ar5007eg
Posts: 13
Joined: Wed Feb 20, 2013 12:25 pm

Protected mode from (Free)DOS

Post 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)
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Protected mode from (Free)DOS

Post 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.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
DLBuunk
Member
Member
Posts: 39
Joined: Sun May 18, 2008 9:36 am
Location: The Netherlands

Re: Protected mode from (Free)DOS

Post 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.
linguofreak
Member
Member
Posts: 510
Joined: Wed Mar 09, 2011 3:55 am

Re: Protected mode from (Free)DOS

Post 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.
ar5007eg
Posts: 13
Joined: Wed Feb 20, 2013 12:25 pm

Re: Protected mode from (Free)DOS

Post 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.
User avatar
Owen
Member
Member
Posts: 1700
Joined: Fri Jun 13, 2008 3:21 pm
Location: Cambridge, United Kingdom
Contact:

Re: Protected mode from (Free)DOS

Post by Owen »

..."USE16" isn't a NASM directive. It's likely being interpreted as a label
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Protected mode from (Free)DOS

Post 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
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
ar5007eg
Posts: 13
Joined: Wed Feb 20, 2013 12:25 pm

Re: Protected mode from (Free)DOS

Post by ar5007eg »

Code: Select all

jmp   dword FLAT_CD:pmode
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.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Protected mode from (Free)DOS

Post by Combuster »

If you use nasm, you can explicitly insert the overrides as needed:

Code: Select all

a32 push value
(...)
a32 o32 retf
For any dumber assembler, you'll probably have to DB the prefixes/opcodes.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
DLBuunk
Member
Member
Posts: 39
Joined: Sun May 18, 2008 9:36 am
Location: The Netherlands

Re: Protected mode from (Free)DOS

Post by DLBuunk »

ar5007eg wrote:

Code: Select all

jmp   dword FLAT_CD:pmode
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?
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Protected mode from (Free)DOS

Post 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...
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
ar5007eg
Posts: 13
Joined: Wed Feb 20, 2013 12:25 pm

Re: Protected mode from (Free)DOS

Post 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
Post Reply