flat assembler
Message board for the users of flat assembler.

Index > OS Construction > Is this code correct?

Author
Thread Post new topic Reply to topic
sid123



Joined: 30 Jul 2013
Posts: 339
Location: Asia, Singapore
sid123 22 Nov 2013, 14:44
Code:
org 32768
call SWITCH_PMODE 
GLO_VARS: 
        PMODE_ENTER db 'Entering Protected Mode......',13,10,0 
        loadGDT db 'Loaded the GDT!',13,10,0 
PRINTF16: 
        mov ah,0x0E 
        jmp .loop 
.loop: 
        lodsb 
        cmp al,0 
        je .ok 
        int 0x10 
        jmp .loop 
.ok: 
        ret 
LOAD_GDT: 
        cli     ; Clear all interrupts 
        pusha ; Don't destroy the registers 
        lgdt    [GDT_CONTENT] ; LDGT : Load GDT  
        sti     ; At this point our GDT is loaded so  
        ; restore interrupts 
        popa ; Restore Them 
        ret     ; All done! 
; Our GDT  
gdt_data:  
        dd 0                            ; null descriptor 
        dd 0  
  
; gdt code:                             ; code descriptor 
        dw 0FFFFh                       ; limit low 
        dw 0                            ; base low 
        db 0                            ; base middle 
        db 10011010b                    ; access 
        db 11001111b                    ; granularity 
        db 0                            ; base high 
  
; gdt data:                             ; data descriptor 
        dw 0FFFFh                       ; limit low (Same as code) 
        dw 0                            ; base low 
        db 0                            ; base middle 
        db 10010010b                    ; access 
        db 11001111b                    ; granularity 
        db 0                            ; base high 
  
THIS_IS_THE_END: 
GDT_CONTENT:  
        dw THIS_IS_THE_END - gdt_data - 1       ; limit (Size of GDT) 
        dd gdt_data                     ; base of GDT 
SWITCH_PMODE: 
        mov si,loadGDT 
        call PRINTF16 
        call LOAD_GDT ; Load the Global Descriptor Tables 
        mov si,PMODE_ENTER 
        call PRINTF16 
        cli ; Disable Interrupts, 
        ; the BIOS IVT is inaccessible in Protected Mode. 
        mov             eax, cr0                         
        or              eax, 1 
        mov             cr0, eax ; At this point we are in Protected Mode! 
        jmp 08h:PMODE ; HERE'S THE PROBLEM! 
        ; DO NOT RENABLE INTERRUPTS! 
        ; DOING SO WILL CAUSE A TPF (Triple Fault) 
        ; after we goto the 32 bit world  
        ; we would restore them. 

; ************************************************************** 
;                                               WELCOME TO THE 32 BIT WORLD! 
;                                               NTMODE IS ENABLED! 
;                                                    WARNING: 
;                                       DO NOT RESTORE INTERRUPTS UNTIL 
;                                       WE ARE SETTLED IN PROTECTED MODE 
; ************************************************************** 
; Congratulations you've come a long journey 
; from 16 bit Real World to 32 bit Protected World! 
; Enjoy life! 
; ************************************************************** 
use32 ; We are pmode set 32 bit Code 
PMODE: 
        cli  
        hlt 
    

The problem occurs when I jump like jmp 0x8:PMODE
I have no idea why. My CPU resets(?)
Also this code is loaded at 0x2000:0x8000
And the good bochs tells me this
Image
As you can clearly see the switch is a success, but after jumping
there is a problem......
It's a GPF (General Protection Fault, Exception 13, 3rd)

_________________
"Those who can make you believe in absurdities can make you commit atrocities" -- Voltaire https://github.com/Benderx2/R3X
XD
Post 22 Nov 2013, 14:44
View user's profile Send private message Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 23 Nov 2013, 16:32
Quote:

org 32768

first of all, I highly recommend you express numbers such as these in hex. 32768 = 0x8000.

second of all: where is the loader that places the code at the ORG address? there is only 1 instruction that jumps to an absolute address so it's possible an errant loader places the code elsewhere. the relative instructions (the calls and relative jumps) would still work. the int should also work.

Quote:
cli ; Clear all interrupts
pusha ; Don't destroy the registers
lgdt [GDT_CONTENT] ; LDGT : Load GDT
sti ; At this point our GDT is loaded so

you don't need to block interrupts for a single instruction (lgdt) since the processor can't pause such instructions in the middle of executing them.

also; you're not modifying any of the registers so you don't need to push them to the stack.

- Stefan

_________________
byte me.
Post 23 Nov 2013, 16:32
View user's profile Send private message Visit poster's website Reply with quote
cod3b453



Joined: 25 Aug 2004
Posts: 618
cod3b453 23 Nov 2013, 23:57
I'm not able to test this but if your code is at 0x2000:0x8000 (0x28000 linear) then you'll need to rebase the GDTR address to also account for the segment since you've set org to 0x8000. My real mode is a little rusty but I think this:
Code:
lgdt [cs:GDT_CONTENT] ; or any other segment register of the same value
    
should fix it. Next you will need to make the same correction to the jmp that causes the mode switch:
Code:
jmp pword 08h:PMODE+(0x2000 shl 4) ; must have pword here for more than 16bit linear address    
Hopefully that will do it.
Post 23 Nov 2013, 23:57
View user's profile Send private message Reply with quote
sid123



Joined: 30 Jul 2013
Posts: 339
Location: Asia, Singapore
sid123 25 Nov 2013, 11:32
Quote:
where is the loader that places the code at the ORG address

The loader is the Kernel itself btw. (0x2000:0x0000)

_________________
"Those who can make you believe in absurdities can make you commit atrocities" -- Voltaire https://github.com/Benderx2/R3X
XD
Post 25 Nov 2013, 11:32
View user's profile Send private message Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 25 Nov 2013, 12:08
I was referring to the loader code. you didn't post it.
Post 25 Nov 2013, 12:08
View user's profile Send private message Visit poster's website Reply with quote
sid123



Joined: 30 Jul 2013
Posts: 339
Location: Asia, Singapore
sid123 25 Nov 2013, 14:58
Oh, You mean the code here it is :
Code:
; Uses a simple binary loader
mov ax,filename ; File Name to load
mov bx,0
mov cx,0x8000 ; Point to load the Program (0x2000:0x8000)
call INT13_LOADFILE ; Load the Program using INT 13H
call 0x8000 ; Jump to the Loaded Point.    

I would post the INT13_LOADFILE, but that's pretty huge, Do you want me to post it?

_________________
"Those who can make you believe in absurdities can make you commit atrocities" -- Voltaire https://github.com/Benderx2/R3X
XD
Post 25 Nov 2013, 14:58
View user's profile Send private message Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 25 Nov 2013, 19:36
what is the value of the segment registers (most importantly DS but also CS)? loading memory is sensitive to the value in DS. if any code modifies DS without restoring it then you'll get memory corruption.

_________________
byte me.
Post 25 Nov 2013, 19:36
View user's profile Send private message Visit poster's website Reply with quote
sid123



Joined: 30 Jul 2013
Posts: 339
Location: Asia, Singapore
sid123 29 Nov 2013, 10:09
DS = 0x2000 (When the Kernel is loaded all the segment registers are equal to 0x2000)
CS = 0x2000
Post 29 Nov 2013, 10:09
View user's profile Send private message Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 01 Dec 2013, 12:08
if you still can't find the issue then post the loader code. we'll go from there.
Post 01 Dec 2013, 12:08
View user's profile Send private message Visit poster's website Reply with quote
sid123



Joined: 30 Jul 2013
Posts: 339
Location: Asia, Singapore
sid123 01 Dec 2013, 12:35
Thanks BAic for helping and responding to my irritating replies,
Well, let me ask the question in the simplest way,
usually all 32-bit Loaders are loaded at 0x9000 segment in memory,
My Kernel is loaded at 0x2000 segment, so is it possible to switch to protected mode in this segment. Also, I can consider chainloading, load a file a 0000:07C0 and jump to that location. Which do you think is the better way?
Also I had a question, is it ok to change the stack after you have previously changed it?

_________________
"Those who can make you believe in absurdities can make you commit atrocities" -- Voltaire https://github.com/Benderx2/R3X
XD
Post 01 Dec 2013, 12:35
View user's profile Send private message Reply with quote
ManOfSteel



Joined: 02 Feb 2005
Posts: 1154
ManOfSteel 01 Dec 2013, 15:35
sid123 wrote:
My Kernel is loaded at 0x2000 segment, so is it possible to switch to protected mode in this segment. Also, I can consider chainloading, load a file a 0000:07C0 and jump to that location. Which do you think is the better way?

There are some limits to the memory ranges you can access directly from real mode.
But I've used both methods and there surely is no "better way".

sid123 wrote:
is it ok to change the stack after you have previously changed it?

You should be able to do so as long as everything (e.g. segment registers) is kept up-to-date.
Post 01 Dec 2013, 15:35
View user's profile Send private message Reply with quote
BAiC



Joined: 22 Mar 2011
Posts: 272
Location: California
BAiC 01 Dec 2013, 21:49
as long as memory exists in the physical address range (use BIOS E820 for general memory detection) then it's fine to switch to protected mode in that region. segments are purely a CPU-side concept from Intel. the hardware (outside the CPU) deals with physical addresses exclusively.

no one can help you without the full code.
Post 01 Dec 2013, 21:49
View user's profile Send private message Visit poster's website Reply with quote
sid123



Joined: 30 Jul 2013
Posts: 339
Location: Asia, Singapore
sid123 02 Dec 2013, 08:16
Got the Problem!
Thanks BAiC!
In the INT13H_LOADFILE
I wrote some extra code and did something like this :
Code:
mov ds,ax 
    

And I forgot to restore the original DS.
So I did :
Code:
INT13H_LOADFILE:
push ds
; ......... All the junk here
.END:
pop ds
ret    

And you know what?
I got a MineCraft Engine (MineAssemble Working on my OS!)
http://www.youtube.com/watch?v=0uGuVHbtms4

_________________
"Those who can make you believe in absurdities can make you commit atrocities" -- Voltaire https://github.com/Benderx2/R3X
XD
Post 02 Dec 2013, 08:16
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20363
Location: In your JS exploiting you and your system
revolution 02 Dec 2013, 08:31
sid123 wrote:
Got the Problem!
...
And I forgot to restore the original DS.
Yup. Segment registers; still causing problems and bugs 35 years later. They were always a stupid idea from day one.
Post 02 Dec 2013, 08:31
View user's profile Send private message Visit poster's website Reply with quote
nerdguy



Joined: 24 Nov 2013
Posts: 7
nerdguy 06 Dec 2013, 09:30
@revolution
And I thought I was the only one to think like that............
Well good news is that soon Intel is trying to get rid of segmentation,
In the x64 Architecture segmentation is thrown off (Although Not completely)
Post 06 Dec 2013, 09:30
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.