Page 1 of 1

Switching back to real mode from protected mode for int 13h

Posted: Thu Mar 31, 2011 4:30 am
by charliesome
I'm working on my little protected mode OS, and I've decided the best way to implement disk I/O for now is to switch back to real mode and use int 13h.

It works perfectly on real hardware, but under Bochs and QEMU it just hangs. I've boiled what I'm doing down into a snippet of assembly - it seems that Bochs doesn't like to do int 13h if the CPU has previously entered protected mode. Again, this works as expected on real hardware:

Code: Select all

use16
org 0x7c00

cli
lgdt [gdtr]
mov eax, cr0
or al, 1
mov cr0, eax

jmp 0x08:protected

protected:
	use32
	; should be in protected mode eh
	mov eax, 0x10
	mov ds, eax
	mov es, eax
	mov fs, eax
	mov gs, eax
	mov ss, eax
	mov sp, 0xffff

	call 0x18:move_to_real
	
	hlt

move_to_real:	
	mov eax, 0x20
	mov ds, eax
	mov es, eax
	mov fs, eax
	mov gs, eax
	mov ss, eax
	
	mov eax, cr0
	and al, ~1
	mov cr0, eax
	
	use16
	jmp 0:real
	
real:
	use16
	mov ax, 0
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	
	; the actual disk read
	mov ah, 2
	mov al, 1
	mov ch, 0
	mov cl, 1
	mov dh, 0
	mov bx, 0x500
	int 0x13
	
	mov eax, cr0
	or al, 1
	mov cr0, eax

	jmp 0x08:.protected
	.protected
	use32
	mov eax, 0x10
	mov ds, eax
	mov es, eax
	mov fs, eax
	mov gs, eax
	mov ss, eax
	ret

gdtr:
	dw 5*8 - 1
	dd gdt

gdt:
; null
	dw 0x0000
	dw 0x0000
	db 0x00
	db 0x00
	db 0x00
	db 0x00
; code (0x08)
	dw 0xffff
	dw 0x0000
	db 0x00
	db 0x9A
	db 0xf | 11000000b
	db 0x00
; data (0x10)
	dw 0xffff
	dw 0x0000
	db 0x00
	db 0x92
	db 0xf | 11000000b
	db 0x00
; 16 bit code (0x18)
	dw 0xffff
	dw 0x0000
	db 0x00
	db 0x9A
	db 0xf
	db 0x00
; 16 bit data (0x20)
	dw 0xffff
	dw 0x0000
	db 0x00
	db 0x92
	db 0xf
	db 0x00
;

times 510-($-$$) db 0
db 0x55
db 0xaa
Is there something I'm doing wrong here, or is this a legitimate Bochs bug?

Thanks :)

Re: Switching back to real mode from protected mode for int

Posted: Thu Mar 31, 2011 4:38 am
by Chandra
You didn't enable the interrupts.

I think it worked under real hardware because the BIOS occasionaly enables the interrupts for some BIOS calls (and you're lucky, actually) but this maynot be the case with Bochs or Qemu.

Re: Switching back to real mode from protected mode for int

Posted: Thu Mar 31, 2011 5:02 am
by charliesome
Oof, I can't believe I missed such a silly thing! It appears to work now in that example I posted above.

However, I did enable interrupts in my real code and it still hangs. Is there anything else I should watch out for?

Re: Switching back to real mode from protected mode for int

Posted: Thu Mar 31, 2011 5:11 am
by Chandra
charliesome wrote:However, I did enable interrupts in my real code and it still hangs. Is there anything else I should watch out for?
Hangs? Does Bochs hang?

If it hangs, it probably means that Bochs(or other emulator) is executing hlt instruction.
Explore the Bochs debug window and see if reports "Warning: hlt instruction with IF!=0!"
When you're done, post some newer info.

Regards!

Re: Switching back to real mode from protected mode for int

Posted: Thu Mar 31, 2011 5:37 am
by Love4Boobies
charliesome wrote:I'm working on my little protected mode OS, and I've decided the best way to implement disk I/O for now is to switch back to real mode and use int 13h.
You mean you've decided that's the easiest way, not the best way. There are huge disadvantages to using the BIOS, esp. for video and storage.

Re: Switching back to real mode from protected mode for int

Posted: Thu Mar 31, 2011 6:47 am
by Combuster
Besides that, you fail the top three bootloader errors. You use an undefined SS, DS, and SP at boot, and worse, you use a different undefined stack when you go back to realmode.

Consider yourself lucky it even worked on real hardware.