Jump to content

Some Weird Processor Error Happens, When I Enter Protected Mode

- - - - -

  • Please log in to reply
26 replies to this topic

#1
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
I have been working on an operating system, but I get this error that says:

Quote

An unrecoverable processor error has been encountered.


(I was testing this in a virtual machine.)

ORG 0x00 


USE16 


db "S3" 


MEM_SZ_1                         equ  0x1000 

MEM_SZ_2                         equ  0x1002 


start: 


xor ax, ax 

mov es, ax 


call GetMemorySize 

mov word [MEM_SZ_1], ax 

mov ax, bx 

mov word [MEM_SZ_2], ax 


;; Set up the Global Descriptor Table. 

xor ax, ax 

mov bx, 0x2000  ;; Put it at 0x2000 

mov word [bx+00], ax   ;; This is the NULL entry. 

mov word [bx+02], ax   ;; And this is still the same entry. 


mov word [bx+04], 0xFFFF   ;; Limit -1. 

mov word [bx+06], 0x8000   ;; Low word of base address is this. 


mov byte [bx+08], 0x01      ;; Higher byte of base address is this. 

mov byte [bx+09], 10011010b     ;; Some other stuff... 

mov byte [bx+10], 11001111b     ;; .....  

mov byte [bx+11], 0x00      ;; The rest of the base address. 


mov word [bx+12], 0xFFFF  ;; The limit. 

mov word [bx+14], 0x00     ;; The base address should be 0. 


mov byte [bx+16], 0x00     ;; So should be the rest of the base address. 

mov byte [bx+17], 10010010b     ;; And some other stuff...  

mov byte [bx+18], 11001111b     ;; .....  

mov byte [bx+19], 0x00     ;; And the last byte of the base address. 


lgdt [GDT_desc]               ;; Load the global descriptor table. 


;; Enable protected mode. 

mov eax, cr0 

or eax, 1 

mov cr0, eax 


;; Use protected mode and jump to start of p.m. part of program. 

jmp 00001000b:start_pm 


;; Table size is 12 bytes and start is at 0x2000. 

GDT_desc: 

dw 12 

dd 0x2000 


;; The start of the protected mode part of the program. 

USE32 

start_pm: 


;; Set up DS and ES. 

mov ax, 10000b 

mov ds, ax 

mov es, ax 


;; Get ready to write to screen. 

mov ebx, 0xB8000 


;; "PM" stands for "Protected Mode" 

mov byte [ebx+00], "P" 

mov byte [ebx+02], "M" 


;; "OK" stands for "OKay" 

mov byte [ebx+04], "O" 

mov byte [ebx+06], "K" 


;; Now, we just sit there and do nothing. 

.lp1: 

hlt 

jmp .lp1 


;; This function is supposed to use the BIOS service 

;; to get the memory size. 

GetMemorySize: 

	xor cx, cx 

	xor dx, dx 

	mov ax, 0xE801 

	int 0x15 

	cmp dx, 0 

	jz .over1 

		mov ax, cx 

		mov bx, dx 

	.over1: 

ret 

I tried commenting everything out and uncommenting (?) and testing things step by step, and I figured out that the problem occurs after the LGDT instruction. Can anyone tell me what's wrong?

(This program is loaded to address 0x1800:0x0000, if that helps any.)

Maybe there's something wrong with the entries in the GDT?



Edit: I tried inserting this:
hlt 


jmp start_pm 
right after the line with the label "start_pm:" , and it still gets that error, so I think the error happens somewhere after the LGDT instruction and before the stuff after the "start_pm:" label.

Edited by RhetoricalRuvim, 17 July 2011 - 09:03 PM.


#2
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
I'm pretty sure you screwed up your GDT. Try hard-coding it and see what happens.
sudo rm -rf /

#3
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
I tried this, and it still gives me that error:
ORG 0x00 


USE16 


db "S3" 


MEM_SZ_1                         equ  0x1000 

MEM_SZ_2                         equ  0x1002 


jmp start 


;; 8-byte align the GDT. 

TIMES 16 - ($ - $$)  DB 0x00 


GDT: 

.myNULL: 

dd 0x00 

dd 0x00 

.myCode: 

dw 0xFFFF 

dw 0x8000 

db 0x01 

db 10011010b 

db 11001111b 

db 0x00 

.myData: 

dw 0xFFFF 

dw 0x0000 

db 0x00 

db 10010010b 

db 11001111b 

db 0x00 


start: 


xor ax, ax 

mov es, ax 


call GetMemorySize 

mov word [MEM_SZ_1], ax 

mov ax, bx 

mov word [MEM_SZ_2], ax 


;; Set up the Global Descriptor Table. 

xor ax, ax 

mov bx, 0x2000  ;; Put it at 0x2000 

mov word [bx+00], ax   ;; This is the NULL entry. 

mov word [bx+02], ax   ;; And this is still the same entry. 

mov word [bx+04], ax   ;; And so is this... 

mov word [bx+06], ax   ;; And this... 


mov word [bx+08], 0xFFFF   ;; Limit -1. 

mov word [bx+10], 0x8000   ;; Low word of base address is this. 


mov byte [bx+12], 0x01      ;; Higher byte of base address is this. 

mov byte [bx+13], 10011010b     ;; Some other stuff... 

mov byte [bx+14], 11001111b     ;; .....  

mov byte [bx+15], 0x00      ;; The rest of the base address. 


mov word [bx+16], 0xFFFF  ;; The limit. 

mov word [bx+18], 0x00     ;; The base address should be 0. 


mov byte [bx+20], 0x00     ;; So should be the rest of the base address. 

mov byte [bx+21], 10010010b     ;; And some other stuff...  

mov byte [bx+22], 11001111b     ;; .....  

mov byte [bx+23], 0x00     ;; And the last byte of the base address. 


lgdt [GDT_desc]               ;; Load the global descriptor table. 


;; Enable protected mode. 

mov eax, cr0 

or eax, 1 

mov cr0, eax 


;; Use protected mode and jump to start of p.m. part of program. 

jmp 00001000b:start_pm 


;; Table size is 12 bytes and start is at 0x2000. 

GDT_desc: 

; dw 12 

; dd 0x2000 

dw 12 

dd GDT + 0x18000 


;; The start of the protected mode part of the program. 

USE32 

start_pm: 


;; Set up DS and ES. 

mov ax, 10000b 

mov ds, ax 

mov es, ax 


;; Get ready to write to screen. 

mov ebx, 0xB8000 


;; "PM" stands for "Protected Mode" 

mov byte [ebx+00], "P" 

mov byte [ebx+02], "M" 


;; "OK" stands for "OKay" 

mov byte [ebx+04], "O" 

mov byte [ebx+06], "K" 


;; Now, we just sit there and do nothing. 

.lp1: 

hlt 

jmp .lp1 


#4
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript

GDT_desc: 

dw 12 

dd GDT + [B][U]0x18000 [/U][/B]

Why are you adding 0x18000?
sudo rm -rf /

#5
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
Because it's "ORG 0x00" at the beginning of the page, and that program is loaded to 0x1800:0x0000, so to get the actual address I think I need to add the offset of GDT to 0x1800<<4.

#6
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
So you're doing org 0x00 because...
sudo rm -rf /

#7
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
It's ORG 0x00 because the stage 2 code sets the code segment to 0x1800:
jmp STAGE3_SEGMENT:STAGE3_OFFSET + 2 


#8
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Er...not sure that's the best way to do things. Normally I load a dummy GDT in stage 1, jump into flat mode, do a few fun things, then reload the GDT from there to get into full protected mode.

The thing is, you don't really want to mess with segments and stuff before you load your GDT because that can mess things up pretty well, as you can see.
sudo rm -rf /

#9
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
Since the code is at 0x18000, and the registers are only 16-bit, I think it would make more sense to use ORG 0x00 and segment 0x1800, because ORG 0x18000 wouldn't exactly fit to the 16-bit limit, would it?

Edit: So should I load stage 3 to lower memory, from stage 2, instead of higher memory?

#10
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
Yes, I know. You don't have to have the code and data in the same segment. I've done my bootloaders a bit differently so I'm not entirely sure what your needs are, but try doing ORG 0x18000 and getting rid of the add.
sudo rm -rf /

#11
RhetoricalRuvim

RhetoricalRuvim

    JavaScript Programmer

  • Members
  • PipPipPipPipPipPipPipPip
  • 1,252 posts
  • Location:C:\Countries\US
Okay, it's this, now:
ORG 0x1000 


USE16 


db "S3" 


MEM_SZ_1                         equ  0x1000 

MEM_SZ_2                         equ  0x1002 


jmp 0x00:start 


;; 8-byte align the GDT. 

TIMES 16 - ($ - $$)  DB 0x00 


GDT: 

.myNULL: 

dd 0x00 

dd 0x00 

.myCode: 

dw 0xFFFF 

dw 0x8000 

db 0x01 

db 10011010b 

db 11001111b 

db 0x00 

.myData: 

dw 0xFFFF 

dw 0x0000 

db 0x00 

db 10010010b 

db 11001111b 

db 0x00 


start: 


xor ax, ax 

mov es, ax 

mov ds, ax 


call GetMemorySize 

mov word [MEM_SZ_1], ax 

mov ax, bx 

mov word [MEM_SZ_2], ax 


;; Set up the Global Descriptor Table. 

xor ax, ax 

mov bx, 0x2000  ;; Put it at 0x2000 

mov word [bx+00], ax   ;; This is the NULL entry. 

mov word [bx+02], ax   ;; And this is still the same entry. 

mov word [bx+04], ax   ;; And so is this... 

mov word [bx+06], ax   ;; And this... 


mov word [bx+08], 0xFFFF   ;; Limit -1. 

mov word [bx+10], 0x8000   ;; Low word of base address is this. 


mov byte [bx+12], 0x01      ;; Higher byte of base address is this. 

mov byte [bx+13], 10011010b     ;; Some other stuff... 

mov byte [bx+14], 11001111b     ;; .....  

mov byte [bx+15], 0x00      ;; The rest of the base address. 


mov word [bx+16], 0xFFFF  ;; The limit. 

mov word [bx+18], 0x00     ;; The base address should be 0. 


mov byte [bx+20], 0x00     ;; So should be the rest of the base address. 

mov byte [bx+21], 10010010b     ;; And some other stuff...  

mov byte [bx+22], 11001111b     ;; .....  

mov byte [bx+23], 0x00     ;; And the last byte of the base address. 


lgdt [GDT_desc]               ;; Load the global descriptor table. 


;; Enable protected mode. 

mov eax, cr0 

or eax, 1 

mov cr0, eax 


;; Use protected mode and jump to start of p.m. part of program. 

jmp 00001000b:start_pm 


;; Table size is 12 bytes and start is at 0x2000. 

GDT_desc: 

; dw 12 

; dd 0x2000 

dw 12 

dd GDT 


;; The start of the protected mode part of the program. 

USE32 

start_pm: 


;; Set up DS and ES. 

mov ax, 10000b 

mov ds, ax 

mov es, ax 


;; Get ready to write to screen. 

mov ebx, 0xB8000 


;; "PM" stands for "Protected Mode" 

mov byte [ebx+00], "P" 

mov byte [ebx+02], "M" 


;; "OK" stands for "OKay" 

mov byte [ebx+04], "O" 

mov byte [ebx+06], "K" 


;; Now, we just sit there and do nothing. 

.lp1: 

hlt 

jmp .lp1 
And the 32-bit code is loaded to 0x0000:0x1000, now.

But it still gets that same error, when it gets to that same place.

#12
dargueta

dargueta

    Writes binary right handed and hex left handed

  • Moderators
  • 4,705 posts
  • Programming Language:C, Java, C++, PHP, Python, Perl, Assembly, Bash, Others
  • Learning:JavaScript
One thing I noticed that's probably unrelated: always execute CLI before loading the GDT or anything.

cli

lgdt    [GDT_desc]

mov     eax, cr0

or      eax, 1

mov     cr0, eax

jmp     0x08:start_pm


start_pm:

sti

; ... etc...


sudo rm -rf /




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users