Partage
  • Partager sur Facebook
  • Partager sur Twitter

Assembleur sapin

Sujet résolu
    30 juin 2021 à 1:46:32

    Bonjour.

    Je cherche a faire les classique pour débutant que j'ai appris en java/c++ en assembleur.

    C'est un peu chaud et c'est plus dure des trouver des tuto :) si vous en avez donnez les moi ! je suis sous ubuntu linux.

    Du coup je cherche a faire :

    *****
    ****
    ***
    **
    *

    Mon code :

    ; ------------------------------------------------------------------------------
    ;     nasm -felf64 sapin.asm && ld sapin.o && ./a.out
    ; ------------------------------------------------------------------------------
    
            global  _start
    
            section .text
    _start: mov     rax, 1      ; system call for write
            mov     rdi, 1      ; file handle 1 is stdout
            mov     rdx, 1      ; number of bytes
            mov     rcx, 6      ; size sapin
            push    rcx         ; save size
    loopA:  mov     rsi, char   ; address of string to output
            pop     rcx         ; get number of row
            dec     rcx         ; decrement number of row
            jz      end         ; no more row end
            push    rcx         ; save number of row if not 0 after decrement
    loopB:  syscall             ; print
            dec     rcx         ; decrement rcx
            jnz     loopB       ; while not 0 print
            mov     rsi, last
            syscall
            jmp     loopA
    
    end:    mov     rax, 60     ; system call for exit
            xor     rdi, rdi    ; exit code 0
            syscall             ; invoke operating system to exit
    
            section .data
    char:   db      "*"         ; note the newline at the end
    last:   db      10          ; note the newline at the end

    Et ca m'enchaine les étoiles a toute vitesse sans jamais s'arreter :s

    Qu'est-ce que j'ai loupé ?

    -
    Edité par -Crixus- 30 juin 2021 à 1:47:13

    • Partager sur Facebook
    • Partager sur Twitter

    "Etre vrai, peu le peuvent."
    Friedrich Nietzsche

      30 juin 2021 à 16:10:21

      le mieux serait d'utiliser un debugger (gdb ou celui intégrer à SASM, un IDE pour nasm par exemple) pour suivre pas à pas l'exécution. 

      il faut ajouter le paramètre -gdwarf à la ligne de compilation de nasm ( https://www.reddit.com/r/asm/comments/ba4qi9/debugging_nasm/ )

      • Partager sur Facebook
      • Partager sur Twitter
        30 juin 2021 à 18:16:40

        Bonjour.

        une instruction pop rcx dans une boucle, ce n'est pas terrible !!

        Vous faites un seul push rcx dans l'initialisation mais le pop rcx va être fait de multiples fois.

        Comme vous êtes en assembleur Intel 64 bits, vous pouvez utiliser d"autres registres (de r8 à r15) pour sauver rcx ou pour le remplacer !!

        Bon courage

        • Partager sur Facebook
        • Partager sur Twitter
          30 juin 2021 à 23:43:36

          Merci pour vos conseils a tout les 2.

          En effet un débugger devrait beaucoup m'aider. J'avais testé GDB pour débugger du c mais j'avais trouvé ca "compliqué" comparé au débugger d'IDE comme éclipse pour java. Il faut que je me mette vraiment dedans car il me semble que c'est un outils puissant et en bonne synergie avec l'assembleur et ghidra (cracking/retro ingé).

           

          Edit :

          Vous m'avez débloqué de fou xD

          J'ai installé SASM, le logiciel est trop minimaliste mais avec l'integration GDB j'ai l'impression d'avoir une machine de guerre. Merci @umfred

          J'ai changé mon registre rcx par r15 et tout fonctionne. Merci @PaulDurelin
          Après analyse avec le debugger, après l'instruction :

          loopB:  syscall             ; print

          le registre était incrementé. Je ne sais pas pour quoi :s. J'imagine qu'il me reste bien des chose a apprendre avec l'asm.

          Le code ci-dessous est donc fonctionnel même si "une instruction pop rcx dans une boucle, ce n'est pas terrible !!" :)

          ; ------------------------------------------------------------------------------
          ;     nasm -felf64 sapin.asm && ld sapin.o && ./a.out
          ; ------------------------------------------------------------------------------
          
                  global  main
          
                  section .text
          main:
                  mov     rbp, rsp    ; for correct debugging
                  mov     rax, 1      ; system call for write
                  mov     rdi, 1      ; file handle 1 is stdout
                  mov     rdx, 1      ; number of bytes
                  mov     r15, 6      ; size sapin
                  push    r15         ; save size
          loopA:  mov     rsi, char   ; address of string to output
                  pop     r15         ; get number of row
                  dec     r15         ; decrement number of row
                  jz      end         ; no more row end
                  push    r15         ; save number of row if not 0 after decrement
          loopB:  syscall             ; print
                  dec     r15         ; decrement r15
                  jnz     loopB       ; while not 0 print
                  mov     rsi, last
                  syscall
                  jmp     loopA
          
          end:    mov     rax, 60     ; system call for exit
                  xor     rdi, rdi    ; exit code 0
                  syscall             ; invoke operating system to exit
          
                  section .data
          char:   db      '*'         ; note the newline at the end
          last:   db      0xa          ; note the newline at the end

          output :
          *****
          ****
          ***
          **
          *


          -
          Edité par -Crixus- 1 juillet 2021 à 0:49:16

          • Partager sur Facebook
          • Partager sur Twitter

          "Etre vrai, peu le peuvent."
          Friedrich Nietzsche

            1 juillet 2021 à 14:43:24

            Ah ah ah : votre programme fonctionne car vous avez ajouté un push dans la boucle (je ne dirais rien).

            Changer le registre rcx par r15 ne change rien à votre problème car en effet vous avez 2 boucles imbriquées et vous utilisez le même indice dans les 2 boucles ce qui vous oblige à effectuer ces pop et push du registre.

            Donc il faut gérer la première boucle avec r15 et la deuxième avec rcx.

            Bon courage.

            • Partager sur Facebook
            • Partager sur Twitter
              1 juillet 2021 à 19:09:32

              son astuce consiste à sauvegarder la valeur du registre à l'aide du push (nombre de ligne), puis à décompter son registre pour afficher les n étoiles d'une ligne, puis de récupérer la valeur initiale à l'aide du pop pour compter le nombre de lignes. Tout ce passe comme prévu. (le push et le pop étaient déjà dans le premier code).

              le syscall devait modifier le rcx, ce qui faisait qu'il était perdu au niveau de la valeur et posait problème.

              • Partager sur Facebook
              • Partager sur Twitter
                1 juillet 2021 à 21:41:32

                Ah oui tu as raison. J'avais pas vu le push dans la boucle du premier programme.

                • Partager sur Facebook
                • Partager sur Twitter
                  1 juillet 2021 à 23:01:38

                  Oui le code fonctionne. L'analyse de la compilation de code en c avec ghidra utilise plutot la logique de Paul.

                  int main(void) {
                  	printf("Hello\n");
                  	for(int i = 0; i < 5; i++){
                  		for(int j = i; j >= 0; j--){
                  			printf("*");
                  		}
                  		printf("\n");
                  	}
                  
                  	return EXIT_SUCCESS;
                  }
                  



                  -
                  Edité par -Crixus- 1 juillet 2021 à 23:03:09

                  • Partager sur Facebook
                  • Partager sur Twitter

                  "Etre vrai, peu le peuvent."
                  Friedrich Nietzsche

                    2 juillet 2021 à 15:59:53

                    Et donc  il n'y a pas besoin de push et de pop dans les boucles !!
                    • Partager sur Facebook
                    • Partager sur Twitter
                      2 juillet 2021 à 22:52:02

                      Oui.

                      Par contre le compilateur C il utilise EBP pour stocker des valeurs alors que de ce que j'ai lu EBP est un registre réservé aux adresse, aux pointeur...

                      Pour quoi le compilateur c utilise EBP pour stocker des entier ?

                      -
                      Edité par -Crixus- 3 juillet 2021 à 2:36:01

                      • Partager sur Facebook
                      • Partager sur Twitter

                      "Etre vrai, peu le peuvent."
                      Friedrich Nietzsche

                        3 juillet 2021 à 16:18:39

                        "Pour quoi le compilateur c utilise EBP pour stocker des entier ?"
                        Parce que rien ne l’empêche !
                        De toute façon de nos jours , ce sont tous des registres généraux donc bon.
                        Même si historiquement certaine instruction reste attaché à un registre particulier.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          3 juillet 2021 à 19:57:17

                          Super.

                          Merci pour toutes vos réponses.

                          • Partager sur Facebook
                          • Partager sur Twitter

                          "Etre vrai, peu le peuvent."
                          Friedrich Nietzsche

                          Assembleur sapin

                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                          • Editeur
                          • Markdown