GDT: mov ss, ax in ASM code causing a triple fault, Advice?

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
User avatar
Tezzanator
Posts: 11
Joined: Sun Aug 17, 2008 2:04 pm
Location: Darlington, UK
Contact:

GDT: mov ss, ax in ASM code causing a triple fault, Advice?

Post by Tezzanator »

Hi, I seem to be getting a triple fault which I can't find any obvious cause for, I've narrowed it down to a single instruction but it still eludes solvation (Nice wording D:)

anyhow This is the ASM code I am using for the GDTFlush Commonly seen in many tutorials:

Code: Select all

[GLOBAL GDTFlush]    ; Allows the C code to call gdt_flush().

GDTFlush:
	mov eax, [esp+4]  ; Get the pointer to the GDT, passed as a parameter.
	lgdt [eax]        ; Load the new GDT pointer

	mov ax, 0x10      ; 0x10 is the offset in the GDT to our data segment
	mov ds, ax        ; Load all data segment selectors
	mov es, ax
	mov fs, ax
	mov gs, ax
	;hlt
	mov ss, ax ; FAULT HAPPENS ON THIS
        ;hlt
	jmp 0x08:.flush   ; 0x08 is the offset to our code segment: Far jump!
.flush:
	ret
And the C++ Code I am using to call it is in the form of this class:
Header:

Code: Select all

#ifndef GDT_H
#define GDT_H

#include "system.h"

struct GDTEntry
{
    u16int limit_low;
    u16int base_low;
    u8int base_middle;
    u8int access;
    u8int granularity;
    u8int base_high;
} __attribute__((packed));

struct GDTptr
{
    u16int limit;
    u8int base;
} __attribute__((packed));


extern "C" { void GDTFlush(u32int pointer); };


class GDT
{
    private:
        struct GDTEntry GDT_Entries[5];
        struct GDTptr GDT_Ptr;
	void set_gate(s32int num, u32int base, u32int limit, u8int access, u8int gran);

    public:
        GDT();
        ~GDT();
};

#endif
Code:

Code: Select all

#include "GDT.h"

GDT::GDT()
{
	
	GDT_Ptr.limit = (sizeof(GDTEntry) * 5) - 1;
        GDT_Ptr.base  = (u32int)&GDT_Entries;


        set_gate(0, 0, 0, 0, 0);                                // Null segment
        set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); // Code segment
        set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
        set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); // User mode code segment
        set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); // User mode data segment

        GDTFlush((u32int)&GDT_Ptr);

}

GDT::~GDT()
{

}

void GDT::set_gate(s32int num, u32int base, u32int limit, u8int access, u8int gran)
{       
        GDT_Entries[num].base_low    = (base & 0xFFFF);
        GDT_Entries[num].base_middle = (base >> 16) & 0xFF;
        GDT_Entries[num].base_high   = (base >> 24) & 0xFF;

        GDT_Entries[num].limit_low   = (limit & 0xFFFF);
        
        GDT_Entries[num].granularity |= gran & 0xF0;
        GDT_Entries[num].access      = access;
}
The bochs log shows me that ss did indeed get set to 0x10 (Value of AX).

Code: Select all

...
00013371786i[CPU0 ] | RAX=0000000000060010  RBX=0000000000102000
...
00013371786i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00013371786i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00013371786i[CPU0 ] |  DS:0010( 0002| 0|  0) ffffffff 000fffff 1 1
00013371786i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00013371786i[CPU0 ] |  ES:0010( 0002| 0|  0) ffffffff 000fffff 1 1
00013371786i[CPU0 ] |  FS:0010( 0002| 0|  0) ffffffff 000fffff 1 1
00013371786i[CPU0 ] |  GS:0010( 0002| 0|  0) ffffffff 000fffff 1 1
The one thing that sticks out to me is "base" is ffffffff while it should be 00000000?

Sorry If this is a really dumb thing but it's had me stumped for a few hours now and I've looked all over the net and within my code to unreavel it's secrets!
Last edited by Tezzanator on Tue Jul 28, 2009 2:54 pm, edited 1 time in total.
Cjreek
Member
Member
Posts: 70
Joined: Thu May 28, 2009 2:41 pm
Location: Germany

Re: GDT: mov ss, ax in ASM code causing a triple fault, Advice?

Post by Cjreek »

Hi,

Code: Select all

00013371786i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00013371786i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 000fffff 1 1
00013371786i[CPU0 ] |  DS:0010( 0002| 0|  0) ffffffff 000fffff 1 1
00013371786i[CPU0 ] |  SS:0010( 0002| 0|  0) 00000000 000fffff 1 1
00013371786i[CPU0 ] |  ES:0010( 0002| 0|  0) ffffffff 000fffff 1 1
00013371786i[CPU0 ] |  FS:0010( 0002| 0|  0) ffffffff 000fffff 1 1
00013371786i[CPU0 ] |  GS:0010( 0002| 0|  0) ffffffff 000fffff 1 1
Are you sure you want to start your data segment at FFFFFFFF ? I think this may be the cause of the fault.

Cjreek
ru2aqare
Member
Member
Posts: 342
Joined: Fri Jul 11, 2008 5:15 am
Location: Hungary

Re: GDT: mov ss, ax in ASM code causing a triple fault, Advice?

Post by ru2aqare »

Code: Select all

#ifndef GDT_H
struct GDTptr
{
    u16int limit;
    u8int base; <<< are you sure it's not missing a * operator? It should be a pointer, not a byte.
Also this line seems suspicious. Why the | operator? This field is not initialized beforehand, so it shouldn't be necessary.

Code: Select all

        GDT_Entries[num].granularity |= gran & 0xF0;
User avatar
Tezzanator
Posts: 11
Joined: Sun Aug 17, 2008 2:04 pm
Location: Darlington, UK
Contact:

Re: GDT: mov ss, ax in ASM code causing a triple fault, Advice?

Post by Tezzanator »

Wow, I feel Like an idiot o_o

No excuse for oversightes like that [-X , Got it working now, thanks for your help - I suppose when you stare at the code long enough, stupidity hides withtin!!
I think It's time I get my friend onboard this experimentation project and finally have another set of eyes to iron out idiotic mistakes such as this.
Post Reply