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

Autres architectures Assembleur Discussion :

[ARM][GBA] Tracer d'une ligne horizontale : hline


Sujet :

Autres architectures Assembleur

  1. #1
    Membre régulier
    Inscrit en
    Mars 2007
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 55
    Points : 73
    Points
    73
    Par défaut [ARM][GBA] Tracer d'une ligne horizontale : hline
    Bonjour les développeurs!!!

    Bon je sais pas si y'en a qui font de l'ASM ARM ici mais je sollicite votre aide tout de même, j'arrive pas à trouver ce qui cloche dans mon code ASM (vline est good, je code hline là).
    hline est une procédure qui trace un trait horizontal à l'écran.

    Bon c'est du code pour GBA mais ça reste de l'ASM ARM (ARM 7 TDMI plus précisement).

    Voilà le code :

    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
     
    @ void asm_draw_hline (int y, int x1, int x2, int color);
    @ met un pixel a une coordonnee (x, y) a une certaine valeur
    .arm
     
            @.section .iwram,"ax",%progbits
     
            .align
     
            .global  asm_draw_hline
     
            .type    asm_draw_hline, function
    @ adress = base + (y * w - (w - x)) * s
    asm_draw_hline :
        push {r4, lr}                    @ sauvegarde du contexte (r4, puis rn)
        sub r6, r2, r1                   @ r6 = x2 - x1 (longueur de la ligne tracee)
        @ mov r2, r0                     @ temp = y
        @ mov r0, r1                     @ x = x
        @ mov r1, r2                     @ y = y
        @ mov r2, #240                   @ w = 240
        @ mov r3, #2                     @ s = 2
        @ bl asm_compute_pixel_adress    @ r0 = vram + (y * w - (w - x)) * 2
        ldr r7, =0x06000000              @ vram
        mov r4, #240                     @ r4 = w = 240
        sub r1, r4, r1                   @ r0 = w - x
        mul r5, r0, r4                   @ r5 = y * w
        sub r5, r5, r1                   @ r5 = y * w - (w - x)
        mov r0, r5, lsl #1               @ r0 = (y1 * w - (w - x)) * 2
        add r0, r0, r7                   @ r0 = adresseBase + (y1 * w - (w - x)) * 2
     
        eor r5, r5, r5
        drawing_hline :
            strh r3, [r0], #2            @ on ecrit le pixel puis on incremente de 2
            add r5, #1
            cmp r6, r5                   @ si on atteint la longueur de la ligne       
        bne drawing_hline                @ alors on a trace notre ligne horizontale
        pop {r4, lr}                     @ on restaure le contexte
        bx lr                            @ on retourne a l'appelant
    Bon je ne fais aucunes vérification des bords (ni de vérification si x2 > x1 pour l'instant).

    Voilà ce que je fais dans mon code :
    0 - Sauvegarde du contexte (normal)
    1 - Calcul de la longueur du segment en pixels
    2 - Calcul de l'adresse où écrire (compute_adress était fais pour ça mais je l'ai recoder en inline dans hline)
    3 - tant qu'on a pas dessiner la longueur de pixel on boucle
    4 - On retourne à l'appelant (normal)

    Pour info, 0x06000000 correspond au début de la mémoire vidéo, si on écrit dans la mémoire vidéo bah on affiche un pixel à l'écran .

    J'ai initialiser le mode 3 de la GBA donc ça ne vient pas de ça (vline et rectfill fonctionnent parfaitement ^^).

    Voilà

    Merci de votre aide d'avance.

    Kurapix

  2. #2
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4
    Points : 5
    Points
    5
    Par défaut précisions demandées.
    Bonsoir !

    peux-tu préciser ce qui ne marche pas ? Par exemple :
    - Problème de compilation
    - Cela n'affiche rien
    - Cela affiche trop
    - Le programme plante

    Deux choses me paraissent étranges :

    - tu utilises r4 à r7 au coeur de ta fonction, mais seul r4 est sauvegardé. Cela peut corrompre les variables globales ou celles de la fonction appelante.

    - Tu te places en adresseBase + ( (y - 1) * w + x ) * 2
    Cela signifie que pour y=0, tu es avant l'adresse 0x06000000

    Pistes de debuggage :

    - Sauvegarder r4-r7
    - N'appeler que cette fonction.
    - Regarder ce que vaut r0 juste avant la boucle.

    Conseils généraux :

    - Plutôt que d'utiliser une variable (ici r5) que tu compares à r6. Tu peux décrementer r6. On gagne 2 instructions et 1 registre.

    - Bx n'est nécessaire que si tu alternes thumb/non-thumb. Dans le cas général, un POP { registres, pc } fera parfaitement l'affaire.

    Bon courage !

    Eg.

  3. #3
    Membre régulier
    Inscrit en
    Mars 2007
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 55
    Points : 73
    Points
    73
    Par défaut
    Merci egery pour ta réponse qui m'a beaucoup aidé.

    En fait, ma procédure fonctionnait bien mais j'avais remarquer comme tu l'as signaler qu'à y = 0 j'étais avant l'adresse 0x06000000, ce qui faisait qu'il y avait un problème d'affichage.
    La formule utilisée pour le calcul de l'adresse du pixel de début était erroné, la bonne formule est la suivante : base + (y * w + x) * s .

    Effectivement, je n'avais pas penser à cette petite optimisation, je l'ai fais, ma procédure est donc un peu plus rapide.

    Pour ce qui est du problème je l'ai trouvé et c'était une erreur de pile : je poppais plus de valeur que je n'en pushais dans la procédure appelée avant hline.
    (Par contre je sais pas si le programme plantait ou pas vu que je teste ça sur un émulateur GBA, pour l'instant je n'ai aucune idées pour savoir .... je m'y pencherais plus sérieusement dessus cet été .... pas avant mes examens).

    Voilà le "nouveau" code :
    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
    @ void asm_draw_hline (int y, int x1, int x2, int color);
    @ trace une ligne horizontale a la hauteur y et de longueur x2 - x1
    .arm
     
    	@.section .iwram,"ax",%progbits
     
    	.align
     
    	.global  asm_draw_hline
     
    	.type    asm_draw_hline, function
    @ adress = base + (y * w + x) * s
    @ x = coordonnee en x
    @ y = coordonnee en y
    @ w = largeur de l'ecran
    @ s = taille d'un pixel en octet(s)
    asm_draw_hline :
        push {r4, r5, lr}                 @ sauvegarde du contexte (pile r2, puis rn)
     
        sub r4, r2, r1                   @ r4 = x2 - x1 (longueur de la ligne tracee)
     
        mov r5, #240                     @ temp = 240
        mul r2, r0, r5                   @ r2 = y * 240
        add r2, r2, r1                   @ r2 = x + y * 240
        mov r1, r2, lsl #1               @ r1 = (x + y * 240) * 2 (un pixel = 2 o)
        ldr r0, =0x06000000              @ vram
        add r0, r0, r1                   @ r0 = vram + (x + 240 * y) * 2
     
        drawing_hline :
            strh r3, [r0], #2            @ on ecrit le pixel puis on incremente de 2
            subs r4, #1                  @ si on atteint la longueur de la ligne       
        bne drawing_hline                @ alors on a trace notre ligne horizontale
     
        pop {r4, r5, lr}                 @ on restaure le contexte
        bx lr                            @ on retourne a l'appelant
    Faudra ensuite que je fasse une vérification de bords et la valeur absolue pour la longueur.

    Quelle conséquence peut avoir le fait de popper plus de valeurs que de valeurs pushées?
    ou
    Quelle conséquence a un POP d'une pile vide?

    Quand on écrit ceci :
    push {r4-r6}
    cela reviendrais à faire cela? :
    push {r4}
    push {r5}
    push {r6}

    Merci pour l'aide apportée d'avance.

    Kurapix

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

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4
    Points : 5
    Points
    5
    Par défaut push pop
    Bonsoir,

    tu peux POPer tant que tu veux, mais alors le registre de pile SP (par convention r13) remonte trop haut, ce qui compromet les "restaurations de contexte" suivantes.

    En outre, en cas de nouveau PUSH (appel de fonction, éventuellement provoqué par une interruption hardware), on écrasera sûrement des données sauvegardées.

    En résumé, si SP n'est plus positionné correctement, tu corromps la pile et par suite le mécanisme d'appel/retour de fonction.

    Le PUSH {r4-r6} est un raccourci syntaxique pour PUSH {r4,r5,r6}.
    Maintenant, la pseudo instruction PUSH est implémentée par un Store Multiple (STMDB typiquement). Les registres r4-r5-r6 se voient stockés en mémoire par ordre croissant (eg r4 à l'adresse la plus basse).
    Cela correspondrait donc à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     PUSH {r6}
     PUSH {r5}
     PUSH {r4}
    sauf que cette écriture prend 3 instructions au lieu d'une...

    Si tu souhaites optimiser ta routine, la première chose à faire est de travailler par mots (32 bits), en traitant à part les pixels de début et de fin s'ils débordent.

    Yves

Discussions similaires

  1. Réponses: 4
    Dernier message: 02/06/2009, 21h28
  2. Tracer une ligne horizontale avec GEF+Draw2d
    Par demcoul dans le forum Eclipse Platform
    Réponses: 0
    Dernier message: 29/01/2009, 18h52
  3. substituer une ligne horizontale au pointeur de sourisau survol de la page affichée
    Par philou8 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 19/11/2008, 12h05
  4. Réponses: 1
    Dernier message: 19/11/2008, 09h06
  5. [ZedGraph] Avoir une ligne horizontale
    Par afrodje dans le forum VB.NET
    Réponses: 6
    Dernier message: 22/05/2008, 12h46

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