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

x86 16-bits Assembleur Discussion :

EMU8086, multi segmentation et buffering


Sujet :

x86 16-bits Assembleur

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 8
    Points : 1
    Points
    1
    Par défaut EMU8086, multi segmentation et buffering
    Bonjour à tous,

    Dans le cadre d'un devoir, je dois réaliser un jeu à l'aide d'EMU8086.
    J'en ai réalisé une bonne partie sans trop de soucis mais je bloque ici sur un problème qui à mon avis est très courant mais qui pourtant me fait m'arracher les cheveux.

    Pour l'affichage de mon jeu, j'ai réalisé une boucle qui affiche 25FPS.
    Cela fonctionne très bien mais le phénomène bien connu de "flickering" se produit.
    Pour le résoudre j'ai donc décidé de mettre en place un Back Buffering.
    Je voulais donc stocker cela dans un tableau de 64000 cases étant donné que je travaille en 320x200 (mode 13h).
    Mais voilà, emu8086 en a décidé autrement...

    Je me doutais bien que je ne pouvais pas stocker ce tableau dans mon segment unique de .COM
    J'ai donc décidé de créer un nouveau segment de données dédié à ce tableau.
    Mais même en faisant cela, le tableau dépasse sur le segment de code et au "blit" je me retrouve avec un joli fouilli:



    La solution aurait pu être de passer vers un .EXE mais cela a donné exactement le même résultat...

    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
    #make_COM#
     
     
    CSEG SEGMENT
    start:
     
    ASSUME CS:CSEG, DS:CSEG, ES:CSEG  
     
    org  100h    
     
     
    mov ah, 0   ; On passe en mode graphique.
    mov al, 13h ; mode 13h = 320x200 pixels, 256 colors.
    int 10h     ; set it!          
     
     
     
    BlitScreen:  
        pusha
     
        ;On place es dans la memoire video
        mov ax, 0A000h
        mov es, ax   
     
        ;On place ds dans le buffer video
        mov ax, DoubleBuffer
        mov ds, ax
     
        ;Addresse de depart de ds:si
        mov si, offset backBuffer  
        ;Addresse de destination de es:di
        mov di, 0 
     
        ;Nombre de tours
        mov cx,64000/2
        rep movsw 
        popa
    ret
     
    ENDS
     
    DoubleBuffer SEGMENT
     
        backBuffer db 64000 dup(0)   
     
    ENDS
    Si vous avez des retours d'expérience ou des idées pour m'aider je vous serais extrêmement reconnaissant.
    Par avance merci !

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Je vais dire un truc bête mais as-tu pensé à mettre ton buffer à zéro avant de commencer à l'exploiter ?

  3. #3
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Je vais dire un truc bête mais as-tu pensé à mettre ton buffer à zéro avant de commencer à l'exploiter ?
    Non ce n'est pas bête du tout, j'y ai pensé...
    Malheureusement une fonction aussi bete que celle-ci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        mov ax, offset backBuffer
        mov es, ax
        xor di, di
        mov ax, 0
        mov cx, 64000/2
        rep stosw
    Ne fonctionne pas et tourne au crash à cause du dépassement de mémoire...

  4. #4
    Membre éclairé
    Avatar de edfed
    Profil pro
    être humain
    Inscrit en
    Décembre 2007
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : Décembre 2007
    Messages : 476
    Points : 701
    Points
    701
    Billets dans le blog
    1
    Par défaut
    le segment doublebuffer au lieu de l'etiquette backbuffer dans es et ça fonctionnera.

  5. #5
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par edfed Voir le message
    le segment doublebuffer au lieu de l'etiquette backbuffer dans es et ça fonctionnera.
    J'obtiens exactement le même résultat malheureusement.
    Dans les faits cela fonctionne déjà, ce qui doit être tracé l'est correctement, il y a juste la zone d'écriture qui se situe en plein milieu du segment de code au lieu du segment DoubleBuffer que j'ai créé pour justement servir de "poubelle".
    Ce qui fait le foulli de couleurs au fond....

    Merci pour vos réponses déjà en tous cas.

  6. #6
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Effectivement Obsidian, je n'avais plus vu cette erreur a force de "tentatives" hasardeuses depuis hier.
    C'est mieux comme ceci, mais cela crash toujours...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        mov ax, DoubleBuffer
        mov es, ax
        mov di, offset backBuffer
        mov ax, 0
        mov cx, 64000/2
        rep stosw

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par Chdidi Voir le message
    J'obtiens exactement le même résultat malheureusement.
    Attention, il faut initialiser le registre de segment à doubleBuffer et DI à backBuffer. Cela dit, c'est déjà l'approche que tu suis dans ton tout premier exemple…

    Dans les faits cela fonctionne déjà, ce qui doit être tracé l'est correctement, il y a juste la zone d'écriture qui se situe en plein milieu du segment de code au lieu du segment DoubleBuffer que j'ai créé pour justement servir de "poubelle".
    Es-tu sûr que c'est vraiment le code que tu vois se blitter à l'écran ? Parce que :

    1. Ça représente VRAIMENT beaucoup de code, et je ne crois pas que tu en aies écrit autant jusqu'ici ;
    2. Il n'y a pas de raison que ça se produise puisque tu as alloué suffisamment de mémoire pour le buffer de backup (64000 octets exactement) ;
    3. Tes sprites sont affichés par dessus les parasites. Tu devrais écraser ton code de cette façon.

  8. #8
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Es-tu sûr que c'est vraiment le code que tu vois se blitter à l'écran ? Parce que :
    1. Ça représente VRAIMENT beaucoup de code, et je ne crois pas que tu en aies écrit autant jusqu'ici ;
    2. Il n'y a pas de raison que ça se produise puisque tu as alloué suffisamment de mémoire pour le buffer de backup (64000 octets exactement) ;
    3. Tes sprites sont affichés par dessus les parasites. Tu devrais écraser ton code de cette façon.
    Il y a actuellement 1050 lignes de code, penses tu que cela puisse être autre chose ?
    Ce qui est dérangeant c'est que je n'arrive pas à "débugguer" mon code en voyant par exemple l'adresse où j'écris, car je pense que le problème c'est que le compilateur "ignore" mon segment DoubleBuffer et cale ça où il peut...

    J'ai essayé de tourner ça dans tous les sens et je n'arrive pas à effacer le contenu de backBuffer.
    Une simple loop avec un mov provoque un crash (sans erreur du dos)...
    C'est cela qui me pousse à croire à un problème de placement en mémoire

  9. #9
    Membre éclairé
    Avatar de edfed
    Profil pro
    être humain
    Inscrit en
    Décembre 2007
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : Décembre 2007
    Messages : 476
    Points : 701
    Points
    701
    Billets dans le blog
    1
    Par défaut
    utilise un autre segment vraiment externe.
    peut etre qu'il faudrait passer en format MZ pour avoir plusieurs segments au lieu d'un seul.

    ou donner l'adresse explicite du segment doublebuffer, je te conseille le segment 8000h pour ça. le segment 0A000h etant le framebuffer.

  10. #10
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par edfed Voir le message
    utilise un autre segment vraiment externe.
    peut etre qu'il faudrait passer en format MZ pour avoir plusieurs segments au lieu d'un seul.

    ou donner l'adresse explicite du segment doublebuffer, je te conseille le segment 8000h pour ça. le segment 0A000h etant le framebuffer.
    VICTOIRE !
    J'ai écris explicitement dans le segment 07000h mon buffer et tout fonctionne parfaitement !
    Je peux écrire, effacer, copier et lire sans soucis.
    Le 08000h provoquait encore quelques artéfacts.
    Cela fait un peu "bidouille", je regarderai donc pour la première solution que tu m'as donné histoire de rendre cela plus propre.
    Il a aussi fallu que je passe à un format .EXE pour pouvoir changer ds en cours d'execution, en .COM il y avait crash...

    Encore merci à vous deux, bonne soirée !

  11. #11
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Euh ! Il y a deux choses quand même qui me sautent aux yeux ce matin :

    1. Tu n'initialises pas ton segment de pile ! En *.com, elle devrait être au même endroit que ton segment de code, mais il faudrait voir si ce n'est pas elle que tu écrases ;
    2. Tu ne fixes pas le sens de déplacement de STOSW avec CLD ou STD !


    Si ton blit est parti dans le mauvais sens, c'est pas étonnant que tu aies écrasé ton code. :-)

  12. #12
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Euh ! Il y a deux choses quand même qui me sautent aux yeux ce matin :

    1. Tu n'initialises pas ton segment de pile ! En *.com, elle devrait être au même endroit que ton segment de code, mais il faudrait voir si ce n'est pas elle que tu écrases ;
    2. Tu ne fixes pas le sens de déplacement de STOSW avec CLD ou STD !


    Si ton blit est parti dans le mauvais sens, c'est pas étonnant que tu aies écrasé ton code. :-)
    J'ai fait un nouvel essai, le blit part bien dans le bon sens...
    Pour la pile, c'est possible, mais je ne sais pas comment vérifier cela.
    J'espère juste qu'en mémoire il n'y a rien à l'adresse 07000h qui soit critique, si ce n'est pas le cas je pense rester sur ce stockage...

  13. #13
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par Chdidi Voir le message
    J'ai fait un nouvel essai, le blit part bien dans le bon sens...
    Oui, mais c'est purement aléatoire. Ça dépend de l'état du bit juste avant que ton programme soit appelé. Est-ce que ça plante toujours même si ça part dans le bon sens ?

    Pour la pile, c'est possible, mais je ne sais pas comment vérifier cela.
    J'espère juste qu'en mémoire il n'y a rien à l'adresse 07000h qui soit critique, si ce n'est pas le cas je pense rester sur ce stockage...
    Je n'ai plus le plan mémoire exact des PC 8086 en mode réel, mais si tu travailles sous D.O.S., le mieux serait quand même de lui réclamer officiellement un segment libre avec une fonction d'allocation.

  14. #14
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 8
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Oui, mais c'est purement aléatoire. Ça dépend de l'état du bit juste avant que ton programme soit appelé. Est-ce que ça plante toujours même si ça part dans le bon sens ?

    Je n'ai plus le plan mémoire exact des PC 8086 en mode réel, mais si tu travailles sous D.O.S., le mieux serait quand même de lui réclamer officiellement un segment libre avec une fonction d'allocation.
    Oui j'ai testé avec CLD, cela plante toujours...
    Est-ce que tu aurais des liens sur les fonctions d'allocation ?
    Je n'ai aucune idée de comment faire ça...

    Merci

  15. #15
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par Chdidi Voir le message
    Oui j'ai testé avec CLD, cela plante toujours...
    Ce qui est curieux, c'est que ça plante avec un *.exe. C'est probablement dû à plusieurs problèmes cumulés. Par contre, avec un *.com, c'est normal : c'est un programme fait pour tenir un seul segment, donc maximum 65280 octets, code, données et pile compris. Mais c'est surtout un fichier-image sans aucune structure et chargé tel quel en mémoire à partir de l'offset 100h.

    Donc, il n'y aucune raison pour que le fichier exécutable ait en lui-même une idée de l'endroit où placer « doubleBuffer », étant donné que le segment de code est alloué par le système au chargement et qu'il n'y a pas de table associée à ton fichier pour boucher les trous comme il y en a avec l'exe.

    Il y a donc de fortes chances pour « doubleBuffer », à la compilation, vaille soit zéro, soit tombe sur le premier multiple de 16 octets libre après la taille de ton code. Dans les deux cas, tu écrases les vecteurs de tes interruptions en début de plan mémoire.

    Est-ce que tu aurais des liens sur les fonctions d'allocation ?
    Je n'ai aucune idée de comment faire ça...
    Regarde les fonctions 48h (allouer) et 49h (libérer) de l'interruption 21h :

    http://www.gladir.com/LEXIQUE/INTR/int21f48.htm

    Tu alloues ta mémoire par « paragraphes », c'est-à-dire par blocs multiples de 16 octets (ce qui correspond en réalité exactement à « l'unité » d'un registre de segment).

  16. #16
    Membre chevronné
    Avatar de Forthman
    Homme Profil pro
    conception mécanique
    Inscrit en
    Janvier 2005
    Messages
    702
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : conception mécanique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2005
    Messages : 702
    Points : 1 905
    Points
    1 905
    Par défaut
    on peut aussi utiliser plus d'un segment avec un fichier .COM

    Je pencherai plutôt pour la fonction 4Ah de l'int 21h
    pour "modifier" l'allocation mémoire (je l'utilisais souvent sur avec mes programmes DOS)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    En entrée :
    ES = segment de base ( =CS pour un .COM)
    BX = nombre de paragraphes à réserver
    AH= 4Ah
    En sortie :
    si FC=1 alors erreur et AX = code d'erreur

    Par exemple, pour réserver 64Ko de plus aux 64Ko du programme .COM

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    mov ax,cs
    mov es,ax
    mov bx,2000h (8192*16=131072octets = 128Ko)
    mov ah,4Ah
    int 21h
    Tu peux après initialiser es pour pointer sur ton segment "graphique" par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    mov ax,cs
    add ax,1000h
    mov es,ax
    a+ François

  17. #17
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par Forthman Voir le message
    on peut aussi utiliser plus d'un segment avec un fichier .COM
    Oui, mais à condition de l'allouer explicitement à l'exécution. C'est ce que l'on dit ici.

    Je pencherai plutôt pour la fonction 4Ah de l'int 21h
    pour "modifier" l'allocation mémoire (je l'utilisais souvent sur avec mes programmes DOS)
    Bof, je ne la trouve pas si « intéressante » que ça dans le contexte actuel car le primo-postant a besoin de 64000 octets pour son double buffer, soit presque exactement la taille adressable d'un segment. En plus mélanger le code et tenir compte l'emplacement actuelle de la pile, c'est se donner du mal pas grand chose. En plus, la fonction en question ne peut pas déplacer le segment au besoin. Donc, s'il a la malchance d'être immédiatement suivi d'un objet en mémoire, la réallocation ne pourra pas se faire.

  18. #18
    Membre éclairé
    Avatar de edfed
    Profil pro
    être humain
    Inscrit en
    Décembre 2007
    Messages
    476
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : être humain

    Informations forums :
    Inscription : Décembre 2007
    Messages : 476
    Points : 701
    Points
    701
    Billets dans le blog
    1
    Par défaut
    pour faire tourner un programme en stand alone, on peut utiliser le segment 9000h sans se preoccuper de ce qu'il peut bien y avoir dedans. en mode purement reel, la zone entre 10000h et 9FFFFh est largement disponible. sur un systeme où seul sera chargé ce programme, il n'y aura pas le moindre probleme à allouer de force certaines zones de mémoire. vu qu'emu8086 est un emulateur, il n'y a aucun probleme à tester. puis le probleme est assez simple en verité. il va pas tarder à être resolu je pense.

  19. #19
    Membre chevronné
    Avatar de Forthman
    Homme Profil pro
    conception mécanique
    Inscrit en
    Janvier 2005
    Messages
    702
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : conception mécanique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2005
    Messages : 702
    Points : 1 905
    Points
    1 905
    Par défaut
    bourrin va !

Discussions similaires

  1. Render Buffer multi couche
    Par LastSpear dans le forum OpenGL
    Réponses: 4
    Dernier message: 23/08/2011, 18h12
  2. la segmentation multi-echelle
    Par mkachekh dans le forum Traitement d'images
    Réponses: 4
    Dernier message: 27/08/2010, 12h23
  3. Réponses: 6
    Dernier message: 27/07/2007, 16h42
  4. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 10h00

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