IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation d'OS Assembleur Discussion :

Probleme d'interruptions ( mauvaise IDT ou GDT ou 8259A-2 )


Sujet :

Programmation d'OS Assembleur

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut Probleme d'interruptions ( mauvaise IDT ou GDT ou 8259A-2 )
    Bonjour,
    Je suis en train de programmer un embryon de kernel pour apprendre un peu mieux comment tout cela fonctionne.
    J'utilise pour ca les tutoriels suivants :
    http://a.michelizza.free.fr/pmwiki.php?n=TutoOS.TutoOS
    http://www.osdever.net/bkerndev/Docs/idt.htm
    http://www.jamesmolloy.co.uk/tutorial_html/index.html

    Mais je bloque sur la gestion des interruptions.
    Je reussis a charger la GDT et a l'utiliser sans problème, mais quand je charge l'IDT et reprogramme les 8259A, bochs me dit que j'ai des erreurs de segments.
    Je pense que je comprends le problème, c'est a dire que quand il y a une interruption et que le processeur va chercher le descripteur systeme dans l'IDT grace au vecteur que lui transmet le 8259A, il le trouve bien. Apres, quand il va chercher l'ISR dans le segment de code que lui indique le descripteur systeme de l'IDT avec l'offset qui est aussi présent dans ce même descripteur système, il le trouve aussi ( la preuve mon ISR par defaut est bien apellee, et elle a pour effet d'ecrire 'Default' a l'ecran ).

    Le problème est que je lance le programme, je charge l'IDT et reprogramme les 8259A, ca m'ecrit Default beaucoup de fois a l'ecran et bochs lance un >>panic<< et s'arrete en me disant qu'il y a un depassement de limite de segment.

    Je ne sais pas trop d'ou ca vient donc je demande de l'aide !


    Voila le code :

    idt.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    #ifndef IDT_HEADER
    #define IDT_HEADER
     
    #define IDT_BASE 0x0800
    #define IDT_SIZE 0xFF /* note : la limit est la taille et NON l'adresse de fin */
     
    /* le type des descripteurs systeme que l'on va mettre dans l'IDT */
    struct idt_descriptor_t
    {
    	unsigned short offset0_15;
    	unsigned short segment_selector16_31;
    	unsigned char always0;
    	unsigned char flags; /* P sur 1 bit, DPL ( contient le ring sur 2 bit ), et toujours 01110 */
    	unsigned short offset48_63;
     
    }__attribute__ ((packed));
     
     
    /* the structure that will be loaded into the IDTR register */
    struct idt_ptr_t
    {	
    	unsigned short limit;
    	unsigned int base;
    }__attribute__ ((packed));
     
     
    void init_idt_desc(struct idt_descriptor_t* idt_desc,
    	unsigned int offset, unsigned short ss, unsigned char flags);
     
    void init_idt();
     
    extern void idt_load();
    extern void isr_default();
    extern void isr_clock();
    extern void isr_kbd();
     
    #endif

    idt.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    #include <idt.h>
    #include <lib.h>
    #include <screen.h>
     
    /*
    	l'IDT elle meme.
    	c'est un tableau de 256 descripteurs systeme
    */
    struct idt_descriptor_t idt[IDT_SIZE];
     
    /*
    	l'offset designe ou se trouve l'ISR a partir du debut du segment de code.
    	Comme il est separe en deux parties dans un descripteur systeme ( pour la retro compatibilite 80286 ),
    	la partie basse et la partie haute, il faut faire des operations bitwise pour le diviser.
    */
    void init_idt_desc(struct idt_descriptor_t* idt_desc,
    	unsigned int offset, unsigned short ss, unsigned char flags)
    {
    	idt_desc->offset0_15 = ( offset & 0xFFFF ); /* on recupere les 16 bits de poids faible de l'offset */
    	idt_desc->segment_selector16_31 = ss;
    	idt_desc->always0 = 0x00;
    	idt_desc->flags = flags;
    	idt_desc->offset48_63 = ( offset & 0xFFFF0000 ) >> 16; /* on recupere les 16 bits de poids fort */
    }
     
    /* 
    	Fonction qui initialise TOUTES les entrees de L'IDT
    	grace a la fonction init_idt_desc()
    */
    void init_idt()
    {
    	short i=0;
     
    	/* on initialise tous les descripteurs de l'IDT pour qu'ils pointent vers l'ISR par defaut */
    	for(i=0; i<IDT_SIZE; i++)
    	{
    		/* 0x8E signifie : descripteur systeme de type interrupt gate */
    		init_idt_desc(&idt[i], (unsigned int)isr_default, 0x0008, 0x8E); 
    	}
    	screen_write(TEXT_FORMAT_GREEN, "2\n");
     
    	/* les interruptions 32 et 33 apelleront les isr horloge et clavier */
    	init_idt_desc(&idt[32], (unsigned int)isr_clock, 0x0008, 0x8E); /* clock */
    	init_idt_desc(&idt[33], (unsigned int)isr_kbd, 0x0008, 0x8E); /* clavier */
     
    	screen_write(TEXT_FORMAT_GREEN, "3\n");
     
    	struct idt_ptr_t idt_ptr;
    	idt_ptr.base = IDT_BASE;
    	idt_ptr.limit = IDT_SIZE*8; /* car un descripteur fait 8 Bytes */
     
    	screen_write(TEXT_FORMAT_GREEN, "4\n");
     
    	/* et on recopie effectivement l'IDT a l'adresse prevue */
    	memcpy(
    			(char*) idt_ptr.base,
    			(char*) &idt,
    			idt_ptr.limit 
    		);
     
    	screen_write(TEXT_FORMAT_GREEN, "5\n");
     
    	/*	fonction assembleur qui va charger notre IDT */
    	idt_load(&idt_ptr);
     
    }
    asm_idt.asm
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    [GLOBAL idt_load]
     
    idt_load:
    	mov eax, [esp+4]	; on recupere l'adresse de la structure idt_ptr_t, passee sur la pile
    	lidt [eax]			; et on charge la structure idt_ptr_t dans le registre IDTR
    	ret
    asm_isrs.asm :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    [GLOBAL isr_default]
    [GLOBAL isr_clock]
    [GLOBAL isr_kbd]
     
    [extern isr_default_c]
    [extern isr_clock_c]
    [extern isr_kbd_c]
     
    isr_default:
    	call isr_default_c	; on apelle la fonction C qui contient le code de l'ISR
    	mov al, 0x20		; on met dans al la valeur qui correspond a EOI pour le PIC
    	out 0x20, al		; on envoie le signal au PIC que l'interruption a ete traitee
    	iret				; retour d'interruption
     
    isr_clock:
    	call isr_clock_c
    	mov al, 0x20
    	out 0x20, al
    	iret
     
    isr_kbd:
    	call isr_kbd_c
    	mov al, 0x20
    	out 0x20, al
    	iret
    isrs.c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    #include <screen.h>
     
    void isr_default_c()
    {
    	screen_write(TEXT_FORMAT_RED, "default.\n"); 
    }
     
    void isr_clock_c()
    {
    	screen_write(TEXT_FORMAT_RED, "clock.\n");
    }
     
    void isr_kbd_c()
    {
    	screen_write(TEXT_FORMAT_RED, "keyboard.\n");
    }

    le code pour reprogrammer les 8259A :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
     
    [GLOBAL init_pics]    ; pour que le code C puisse apeller init_pics().
     
    ; note : les jmp servent a faire une temporisation pour etre sur 
    ; que le PIC a le temps de lire les registres avant de reecrire.
     
    init_pics:
     
    	; on envoie la valeur de al sur les ports des PICS,
    	; pour initialiser leur ICW1
    	mov al, 0x11	; sequence d'initialisation
    	out 0x20, al	; maitre
    	jmp .1
    	.1:
    	out 0xA0, al	; esclave
    	jmp .init_icw2	 
     
    .init_icw2:
    	; initialisation de ICW2
    	; c'est la qu'on va dire en gros au pic :
    	; "quand tu recois l'IRQ x, tu vas envoyer au processeur le vecteur de valeur y"
    	; ce vecteur correspondra a un index dans l'IDT bien sur
    	; on va faire comme ca :
    	; les IRQ0-7 (PIC 1) sont programmees pour renvoyer les vecteurs correspondant aux interruptions 0x20-0x27 ( 32 a 39 )
    	; les IRQ8-15 (PIC 2) sont programmees pour renvoyer les vecteurs correspondant aux interruptions 0x28-0x2f ( 40 a 47 )
    	mov al, 0x20
    	out 0x21, al	; maitre, vecteur de depart = 32
    	jmp .2
    	.2:
    	mov al, 0x28
    	out 0xA1, al	; esclave, vecteur de depart = 40
    	jmp .init_icw3
     
    .init_icw3:
    	; initialisation du registre ICW3
    	; celui ci informe les PICS sur la maniere donc ils sont cascades.
    	; le controleur esclave est rattache a la broche 2 du maitre par sa broche 4
    	mov al, 0x04
    	out 0x21, al	; le maitre est relie sur la broche 4 de l'esclave ( 8259-1 is master )
    	jmp .3
    	.3:
    	mov al, 0x02
    	out 0xA1, al	; l'esclave est relie sur la broche 2 du maitre ( 8259-2 is slave )
    	jmp .init_icw4
     
    .init_icw4:
    	; initialisation du registre ICW4
    	; celui ci specifie aux 8259A dans quel mode ils doivent fonctionner
    	; ici on utilise le mode par defaut, AEOI: automatic end of interrupt
    	; aussi connu sous le nom de mode 8086
    	mov al, 0x01
    	out 0x21, al
    	jmp .4
    	.4:
    	out 0xA1, al
    	jmp .set_ocw1
     
    .set_ocw1:
    	; le mot d'operation de controle OCW1 permet masquer/demasquer les interruptions
    	; en ecrivant dans le registre IMR du 8259A
     
    	mov	al,0xff		; on masque tout pour l'instant ( 1=masked, 0=unmasked )
    	out 0x21,al
    	jmp .5
    	.5:
        out 0xA1,al
    et les erreurs que me renvoie bochs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    05163214e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163241e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163268e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163295e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163322e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163349e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163376e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163403e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163430e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163457e[CPU0 ] fetch_raw_descriptor: GDT: index (151f) 2a3 > limit (7f8)
    00005163485e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163486e[CPU0 ] branch_near32: offset outside of CS limits
    00005163487e[CPU0 ] branch_near32: offset outside of CS limits
    00005163678e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163679e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163680e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163681e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163682e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163683e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163684e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163685e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163686e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163687e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163688e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163689e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163690e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163691e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163691e[CPU0 ] interrupt(): gate.type(1) != {5,6,7,14,15}
    00005163692e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163692e[CPU0 ] interrupt(): gate.type(1) != {5,6,7,14,15}
    00005163693e[CPU0 ] read_RMW_virtual_byte_32(): segment limit violation
    00005163693e[CPU0 ] interrupt(): gate.type(1) != {5,6,7,14,15}
    00005163693e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
    00005163693i[CPU0 ] CPU is in protected mode (active)
    00005163693i[CPU0 ] CS.d_b = 32 bit
    00005163693i[CPU0 ] SS.d_b = 32 bit
    00005163693i[CPU0 ] | EAX=14ba0000  EBX=4000007c  ECX=88fff69f  EDX=000b5131
    00005163693i[CPU0 ] | ESP=0000083f  EBP=000015e6  ESI=00000004  EDI=000010a6
    00005163693i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
    00005163693i[CPU0 ] | SEG selector     base    limit G D
    00005163693i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
    00005163693i[CPU0 ] |  CS:0008( 0001| 0|  0) 00000000 0fffffff 1 1
    00005163693i[CPU0 ] |  DS:0010( 0002| 0|  0) 00000000 0fffffff 1 1
    00005163693i[CPU0 ] |  SS:0018( 0003| 0|  0) 00000000 0fffffff 1 1
    00005163693i[CPU0 ] |  ES:0010( 0002| 0|  0) 00000000 0fffffff 1 1
    00005163693i[CPU0 ] |  FS:0010( 0002| 0|  0) 00000000 0fffffff 1 1
    00005163693i[CPU0 ] |  GS:0010( 0002| 0|  0) 00000000 0fffffff 1 1
    00005163693i[CPU0 ] | EIP=00001510 (00001510)
    00005163693i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
    00005163693i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
    00005163693i[CPU0 ] 0x00001510>> add byte ptr ds:[eax], al : 0000
    00005163693e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
    00005163693i[SYS  ] bx_pc_system_c::Reset(HARDWARE) called
    00005163693i[CPU0 ] cpu hardware reset


    Voila donc si une ame charitable pouvait m'aider un peu, parce que la je coince un peu...
    Merci


    EDIT ! : Je viens de regler mon probleme d'IDT et de GDT en recompilant Bochs en mode debug et en verifiant chaque octet en memoire, elles sont tout a fait valides maintenant. Il me reste juste un souci lors de la reprogrammation des 8259-A, c'est a dire que quand je les reprogramme ils foutent totalement en l'air la GDT et l'IDT.... c'est assez bizarre...
    Enfin bon voila je vais continuer a debugger le programme lentement mais surement

  2. #2
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Décembre 2013
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2013
    Messages : 19
    Points : 2
    Points
    2
    Par défaut Programmation d'un kernel (noyau) en asm..
    Bonjour

    Les différents exemples que tu regardes et que tu essayes de programmer sont "bugués" ou parfois très mal programmés....

    Recupères les sources en asm sur le net...

    Ensuite commences par un simple bootsecteur...en asm...tu le testes et ensuite tu passes au kernel...

    Ensuite attaque le 8259 en asm et non en c...pour la programmation de ton noyau....ton objectif étant d'activer en premier ton clavier évidement sinon tu respire de l'air:tu vas te retrouver sur qemu à admirer ton operating system sans pouvoir inter agir avec lui...donc du vent...

    Tu vas écrire des centaine de lignes mais que tu comprendras bien...sinon tu as un écran noir...

    Tu ecrits un fichier pour la GDT...un autre pour le 8259 (initialisation,masques....)et un autre pour les interruptions...tu sépares bien ton bootsect de ton kernel...et apres un petit : cat bootsect kernel /dev/zero | dd of=floppy bs=512 count=2880 et ensuite qemu ....programmes sous Debian...sinon les autres ,c'est de la daube...de belles images et encore..

    Pour le c...c'est un langage de haut niveau donc une couche de plus donc possibilités accrues d'erreurs...

    Je ne connais pas le c mais uniquement l'asm sur 68000 et 8086...je ne peux uniquement t'aider que dans ce langage...

    Cordialement.

    NB,n'oublies pas de passer en mode protégé...et j'ai du oublier d'autres recommandations...

  3. #3
    Expert éminent

    Profil pro
    Fabricant et casseur d'avions
    Inscrit en
    Avril 2004
    Messages
    3 813
    Détails du profil
    Informations personnelles :
    Localisation : France, Tarn (Midi Pyrénées)

    Informations professionnelles :
    Activité : Fabricant et casseur d'avions
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Avril 2004
    Messages : 3 813
    Points : 7 638
    Points
    7 638
    Par défaut
    J'ose espérer que depuis 2011, il a résolu son souci... sinon, je salue la persévérance! (ou l'obstination... mais ça va souvent de paire)
    "Errare humanum est, sed perseverare diabolicum"

    Ma page sur DVP.com

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problemes d'interruptions Boutons Poussoirs
    Par sheva94 dans le forum Embarqué
    Réponses: 1
    Dernier message: 09/03/2012, 06h40
  2. Probleme d'interruption de callback
    Par ptit-nico dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 26/06/2008, 15h54
  3. probleme d'interruption de l'execution
    Par DIDIDIDA dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 28/01/2008, 10h45
  4. probleme d'interruption de l'execution
    Par DIDIDIDA dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 28/01/2008, 10h33
  5. {VBA Excel}Probleme sur macro mauvaise lecture de feuille excel
    Par Thomas69 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 09/08/2007, 15h38

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo