Page 1 of 2

Bochs - Bootloader error

Posted: Wed Nov 07, 2007 12:30 pm
by AlfaOmega08
When i have compiled and linked my kernel, i have tried to start it on Bochs...
After the bootloader has deactivated interupts and NMI, activated the A20 line, loaded the GDT and switched to PMode, it loads the segments registers DS, ES and SS to 0x10. Then it try to read the sectors from the floppy that contains the kernel. When it load the content of AX in ES it crashes with this bochs error:
00028801846i[BIOS ] Booting from 0000:7C00
00028963558e[CPU0 ] fetch_raw_descriptor: GDT: index (1007)200 > limit (17)
00028963558i[CPU0 ] protected mode
00028963558i[CPU0 ] CS.d_b = 32 bit
00028963558i[CPU0 ] SS.d_b = 16 bit
00028963558i[CPU0 ] EFER = 0x00000000
00028963558i[CPU0 ] | RAX=0000000000000010 RBX=0000000000007e00
00028963558i[CPU0 ] | RCX=0000000000001000 RDX=0000000000000000
00028963558i[CPU0 ] | RSP=0000000000007c00 RBP=0000000000000000
00028963558i[CPU0 ] | RSI=00000000ffff88ca RDI=0000000000080000
00028963558i[CPU0 ] | R8=0000000000000000 R9=0000000000000000
00028963558i[CPU0 ] | R10=0000000000000000 R11=0000000000000000
00028963558i[CPU0 ] | R12=0000000000000000 R13=0000000000000000
00028963558i[CPU0 ] | R14=0000000000000000 R15=0000000000000000
00028963558i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00028963558i[CPU0 ] | SEG selector base limit G D
00028963558i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00028963558i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00028963558i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00028963558i[CPU0 ] | SS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00028963558i[CPU0 ] | ES:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00028963558i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00028963558i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00028963558i[CPU0 ] | MSR_FS_BASE:0000000000000000
00028963558i[CPU0 ] | MSR_GS_BASE:0000000000000000
00028963558i[CPU0 ] | RIP=0000000000007e8f (0000000000007e8f)
00028963558i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00028963558i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00028963558i[CPU0 ] >> mov es, cx : 8EC1
00028963558e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
My code is:

Code: Select all

%define BODY_SEC_LENGTH ((BodyEnd - Body) / 512) + 1
%include "kernelSize.inc"

BITS 16
ORG 0x7C00

Boot:
	XOR	AX, AX           ;Loads the segment registers
	MOV	DS, AX
	MOV	ES, AX
	MOV	SS, AX
	MOV	SP, 7C00h
	
	MOV	AX, 200h + BODY_SEC_LENGTH
	MOV	CX, 2
	XOR	DX, DX
	MOV BX, 7E00h
	INT	13h              ;Read the bootloader from sector 2
	
	JMP	0000h:7E00h ;Jump to the bootloader code
	
	times (510 - ($ - Boot)) DB 0  ;filler
	DW	0AA55h                     ;bootloader magic number

Body:
	PUSH	WORD MsgWelcome
	CALL	Print
	
	CLI                    ;disable interrupts
	IN	AL, 70h
	OR	AL, 80h
	OUT	70h, AL   ;disable NMI

	CALL	A20Enable  ;enable A20 line

	PUSH	WORD MsgGDT
	CALL	Print
	LGDT	[GDTInfo]  ;loads GDT

	PUSH	WORD MsgPE
	CALL	Print

	MOV EAX, CR0
	OR	AL, 1
	MOV	CR0, EAX          ;switch to PM

	JMP DWORD 8:Main32    ;Jump to PM code

A20Enable:
	PUSH	AX
	
	PUSH	WORD MsgA20
	CALL	Print

	CALL	KbdWaitOutput

	MOV	AL, 0D0h
	OUT	64h, AL
	CALL	KbdWaitInput

	XOR	AX, AX
	IN	AL, 60h
	OR	AL, 2

        PUSH	AX
	CALL	KbdWaitOutput
	MOV	AL, 0D1h
	OUT	64h, AL
	
	CALL	KbdWaitOutput
	
	POP	AX
	OUT	60h, AL
	
	POP	AX
	RET

KbdWaitOutput:
	IN	AL, 64h
	TEST	AL, 2
	JNZ SHORT KbdWaitOutput
	RET

KbdWaitInput:
	IN	AL, 64h
	TEST	AL, 1
	JZ SHORT KbdWaitInput
	RET

Print:
%define	Message BP + 4
	PUSH	BP
	MOV	BP, SP
	
	PUSH	AX
	PUSH	BX
	PUSH	SI
	
	MOV	SI, WORD [Message]
	MOV	AH, 0Eh
	XOR	BX, BX
NextChar:
	LODSB
	TEST	AL, AL
	JZ	SHORT Done
	INT	10h
	JMP	SHORT NextChar

Done:
	POP	SI
	POP	BX
	POP	AX
	
	MOV	SP, BP
	POP	BP
	
	RET	2

%undef	Message

BITS 32
Main32:
        MOV	AX, 10h      ;Loads segment registers
	MOV	DS, AX
        MOV	ES, AX
	MOV	SS, AX

ReadFloppy:
	MOV	SI, KRNL_SIZE
	XOR	BX, BX
        MOV	AX, 1000h              :HERE IS THE PROBLEM
        MOV	ES, AX                   ;WHILE MOVING AX TO ES
	MOV	CX, 3
	XOR	DX, DX

Again:
	PUSH	AX
	PUSH	BX
	MOV	AX, 0E00h + '.'  
	MOV	BX, 7
	INT	10h
	POP	BX
	POP	AX
	
	MOV	AX, 0201h
	INT	13h                    ;Read the kernel from the floppy
	JC	SHORT Error

	MOV	AX, ES
	ADD	AX, 32
	MOV	ES, AX

	DEC	SI
	JZ	SHORT ReadOK

	INC	CX
	CMP	CL, 18
	JBE	SHORT Again
	MOV	CL, 1
	INC	DH
	CMP	DH, 2
	JNE	SHORT Again
	MOV	DH, 0
	INC	CH
	JMP	SHORT Again

Error:
	MOV	AX, 0E00h + 'e'
	MOV	BX, 7
	INT 10h
	XOR	AX, AX
	INT	16h
	INT	19h

ReadOK:
	MOV	EDX, 3F2h
	MOV	AL, 0Ch
	OUT	DX, AL          ;Shut down the floppy motor

        MOV     AX, 1000h    ;Start the kernel
        JMP       AX

        JMP	$
	
	CLI
	HLT

GDT:
	DD	0, 0

	DW  0FFFFh
	DW  0
	DB  0
	DB  9Ah
	DB  0CFh
	DB  0

	DW	0FFFFh
	DW  0
	DB  0
	DB  92h
	DB  0CFh
	DB  0
GDTEnd:

GDTInfo:
	DW	GDTEnd - GDT - 1
	DD	GDT

FloppyOff:
	MOV	DX, 3F2h
	MOV	AL, 0Ch
	OUT	DX, AL
	RET

MsgWelcome:
	times 80 DB '-'
	DB "Boot process", 13, 10
	times 80 DB '-'
	
	DB 0

MsgA20		DB "A20...", 10, 13, 0
MsgGDT		DB "GDT...", 10, 13, 0
MsgPE		DB "PM...", 13, 10, 0
	
BodyEnd:
length EQU ((((BodyEnd-Boot) / 512) + 1) * 512)
length2 EQU (BodyEnd-Boot)
times (length - length2) DB 0
Why it doesn't works?
Please, help me!!!

Posted: Wed Nov 07, 2007 3:33 pm
by frank
You cannot use BIOS interrupts in protected mode. Either load the kernel before going to protected mode or write a floppy driver/hard disk driver.

Posted: Wed Nov 07, 2007 11:29 pm
by 01000101
I would suggest loading all of the contents you need off the floppy in Real Mode (16-bit). That way you save the trouble (for now) of writing those drivers.

Remember, no bios interrupts in PMode. Get all that stuff outta the way in real mode.

Posted: Thu Nov 08, 2007 1:15 am
by AlfaOmega08
Ok, thanks, i'll try now...
If I need to use BIOS interrupts in PMode?
Have I to load the IDT?

They are so useful, I need them!!!

Posted: Thu Nov 08, 2007 1:25 am
by TomTom
If you have to use the BIOS from protected mode you'll have to switch back to (un)real mode. That's expensive and slow, though.

Posted: Thu Nov 08, 2007 1:33 am
by AlfaOmega08
:cry: OK, you have rejected this idea.

Thanks

Posted: Thu Nov 08, 2007 2:03 am
by TomTom
Well, there's actually a few cases where you actually need to do this, e.g. when your VGA driver wants to switch the video mode.

Posted: Thu Nov 08, 2007 2:18 am
by AlfaOmega08
Yes, I need interrupts for VGA and for r/w from the HD or the floppy...

I've solved the problem of the PM.
Now there is another...

At this instruction:

Code: Select all

JMP    DWORD 8h:Main32
Bochs tells me:
03877096018i[CPU0 ] >> add byte ptr cs:[eax], al : 2E0000
03877096018e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
!!!
There isn't any "ADD BYTE PTR CS:[EAX], AL" in my source
Perharps the assembler erred while assembling my code?
Or bochs has a bug and read wrong this opcode?

Posted: Thu Nov 08, 2007 2:55 am
by JamesM
99.99999999999999% certain bochs doesn't have that bug. It's almost certainly your code.

Are you on linux (or cygwin)? if so you can run

Code: Select all

objdump -d my_kernel.bin
or whatever your bootloader binary is called. This will dump out the entire dissassembled contents of your binary so you can see how that line bochs errored on matches up with your own code.

Posted: Thu Nov 08, 2007 4:00 am
by B.E
Lets look at the following code

Code: Select all

00028963558i[CPU0 ] CS.d_b = 32 bit
00028963558i[CPU0 ] SS.d_b = 16 bit
this tells me that your in protected mode, and execution is somewere between
Main32:
MOV AX, 10h ;Loads segment registers

and

MOV SS, AX

Code: Select all

00028963558i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D 
00028963558i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 000fffff 1 1
00028963558i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 000fffff 1 1
00028963558i[CPU0 ] | SS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00028963558i[CPU0 ] | ES:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00028963558i[CPU0 ] | FS:0000( 0005| 0| 0) 00000000 0000ffff 0 0
00028963558i[CPU0 ] | GS:0000( 0005| 0| 0) 00000000 0000ffff 0 0 
Notice that the 'D' (data) flag is 1 on CS, (haven't looked at the GDT structure). This means that you have a couple of problems

- first interrupts aren't disabled when going into protected mode (they must be disabled until a IDT is loaded.
- the GDT table is set up incorrectly.
- Also I noticed that the GDT isn't aligned(again I'm a bit rusty on GDT to know what it has to be aligned to)
- as already stated can not use bios interrupts once in protected mode.
- because of the above errors(also you would of read that you can't use interrupts in protected mode), this looks like a copy and paste, which is your biggest error

Posted: Thu Nov 08, 2007 5:16 am
by AlfaOmega08
Interrupts are disabled:

Code: Select all

CLI                    ;disable interrupts 
IN   AL, 70h 
OR   AL, 80h 
OUT   70h, AL   ;disable NMI 

Posted: Thu Nov 08, 2007 7:08 am
by jal
AlfaOmega08 wrote:At this instruction:

Code: Select all

JMP    DWORD 8h:Main32
Bochs tells me:
03877096018i[CPU0 ] >> add byte ptr cs:[eax], al : 2E0000
03877096018e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
!!!
There isn't any "ADD BYTE PTR CS:[EAX], AL" in my source
Perharps the assembler erred while assembling my code?
Or bochs has a bug and read wrong this opcode?
Most likely "8h:Main32" points to a different place than you think it does, and at that memory location there's that instruction. But really, seeing what you've done wrong and the knowledge you obviously lack to do create an OS, just pull the plug...


JAL

Posted: Thu Nov 08, 2007 9:15 am
by Combuster
There isn't any "ADD BYTE PTR CS:[EAX], AL" in my source
That means that you sent your code "into the weeds". That's what debugging is for. It means that you build and verify your assumptions. you'll figure soon enough that eip or cs.base is not what it should be. Next, read through the intel manuals to find the far jump, and perform every step on paper, then compare all the inputs you assumed with the inputs that are actually present.

In essence, get the bochs debugger :wink:
jal wrote:But really, seeing what you've done wrong and the knowledge you obviously lack to do create an OS, just pull the plug...
That was uncalled for. Instead of telling him to f*** off it would be more appropriate to point him to where he needs to go. You should read this to get familiar with the filosophy behind it.
TomTom wrote:If you have to use the BIOS from protected mode you'll have to switch back to (un)real mode. That's expensive and slow, though.
There's v8086 mode just for that. It is in many regards better but needs a bit more work.

Posted: Thu Nov 08, 2007 9:57 am
by jal
Combuster wrote:
jal wrote:But really, seeing what you've done wrong and the knowledge you obviously lack to do create an OS, just pull the plug...
That was uncalled for. Instead of telling him to f*** off it would be more appropriate to point him to where he needs to go. You should read this to get familiar with the filosophy behind it.
Well, I didn't use the f-word. But really, people who do not even know how to use a compiler will never create anything usuable. Yes, they may have fun with it while doing so, but mainly they will bother everyone asking what they do wrong when it fails to work. Where he needs to go? He needs to learn how to program in C and ASM. That'll take him a year or so. Then he needs to understand the internals of a computer. Let's give him six months for that. And then let him come back.


JAL

Posted: Thu Nov 08, 2007 10:52 am
by Combuster
people who do not even know how to use a compiler will never create anything usuable.
is it just me, or did the original poster just successfully assemble and run a program?! :shock: