Advertisement
Guest User

Untitled

a guest
Jan 25th, 2018
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ;  Fichier : EntreeSortie.asm
  2.  
  3. ; Le texte après un point-virgule est un commentaire. L'assembleur n'en tient pas compte.
  4.  
  5. ;       Code C++ et son équivalent en NASM/C.
  6.  
  7. ;       int main( )
  8. ;       {
  9. ;           int N ;
  10. ;           cout << "Entrez la valeur de N : " ;        // Incitation
  11. ;           cin >> N ;                  // Lecture
  12. ;           cout << "N =  " << N << endl ;          // Écho
  13. ;           return 0 ;
  14. ;       }
  15.  
  16.  
  17.  
  18. ;  On utilisera l'assembleur NASM.
  19.  
  20. ; "global _main" est une expression qui dit où est la première instruction à être exécutée. Regarder dans la section .text pour retrouver l»'étiquette _main.
  21. global _main
  22. ; Les deux déclarations suivantes (extern) indiquent à l'assembleur qu'il existe deux fonctions appelées _printf et _scanf qui ne sont pas dans ce fichier-ci.
  23. ; L'assembleur va mettre une note dans le fichier objet (.o) que ces deux fonctions seront attendues lors de l'édition des liens (la commande gcc dans l'étape 2).
  24. extern _printf
  25. extern _scanf
  26.  
  27. ; Les fonctions _printf et _scanf sont des fonctions du langage C que gcc ira récupérer lors de l'étape 2 - édition des liens.
  28.  
  29. ; La section .data est la zone où l'on réserve nos variables et "littéraux" (equate) que l'on veut bien définir. (Il n'y a pas d'exemple de equate dans ce fichier-ci.)
  30.  
  31. section .data
  32.  
  33. ; Ici, les chaînes de caractères sont terminées par le caractère NULL ( 0 ). C'est une convention.
  34.  
  35. ; Dans les déclarations ci-dessous, db tient pour data byte. C'est un type de 1 byte de long. L'assembleur va regarder le contexte pour décider combien de bytes en tout sont nécessaire.
  36.  
  37. ; La présence de "" indique une chaîne de caractères. Les nombres tels 0 et 10 sont des entiers. Dans cet exemple, vu qu'ils suivent un db, ils seront codés dans un byte chacun.
  38.  
  39. ; Le mot qui précède un : est une étiquette. Nous la voyons comme le nom d'une variable, l'assembleur la voit comme l'adresse d'un espace mémoire.
  40.  
  41. incitation: db "Entrez la valeur de N : ", 0
  42.  
  43. format_input:   db "%d", 0  ; Cette chaîne est utilisée par _scanf, le %d indique que l'on veut un entier décimal.
  44.                         ; _scanf s'attend à un paramètre adresse sur la pile. Cette adresse doit être l'adresse d'une chaîne de caractères.
  45.                         ; À partir de cette chaîne, _scanf détermine quoi lire du clavier :
  46.                         ;  -  %d  = entier Décimal
  47.                         ;  -  %u = Unsigned entier décimal
  48.                         ;  -  %s  = String
  49.                         ; _scanf s'attend à ce qu'il y ait déjà une autre adresse (décalage) sur la pile pour identifier la variable qui va recevoir la réponse.
  50.  
  51. format_output: db "N =  %d", 10, 0 ; newline (10 = 0Ah), null terminator ( 0 )
  52.                         ; Cette chaîne est utilisée par _printf.
  53.                         ; _printf s'attend à un paramètre adresse sur la pile. Cette adresse doit être l'adresse d'une chaîne de caractères.
  54.                         ; À partir de cette chaîne, _printf détermine quoi afficher à l'écran : %d = entier décimal, %u = unsigned, %s = string
  55.                         ; _printf s'attend à ce qu'il y ait d'autres adresses ou valeurs sur la pile pour identifier ce qui va être affiché.
  56.                         ; Il peut y avoir plusieurs %d, %u et %s dans la première chaine. Pour chacun de ces symboles, il devra y avoir un
  57.                         ; paramètre de mis sur la pile AVANT que de mettre l'adresse de la première chaîne.
  58.  
  59. ; NASM a ses propres façons de faire pour déclarer des variables. Il y a des différences avec MASM, TASM, YASM et autres assembleurs.
  60.                        
  61. N:          times 4 db 0 ; 32-bits integer = 4 bytes
  62.  
  63. ; On ne se sert pas de la section .bss mais je la laisse au cas où ... dans le futur ...
  64. section .bss
  65.  
  66. ; La section .text contient le code.
  67. section .text
  68.  
  69. _main:
  70.  
  71.     push ebp            ; --> 1 - sauvegarder l'état de la pile et du record d'activation présent (le contenu du ebp est mis sur la pile)
  72.     mov ebp, esp            ; Mettre la valeur du "stack pointer" dans le "base pointer".
  73.     push ebx            ; --> 2- Sauvegarder ebx et ecx vu qu'on va les utiliser pour nos calculs (le contenu du ecx est mis sur la pile)
  74.     push ecx            ; --> 3- (le contenu du ecx est mis sur la pile)
  75.                     ; Ceci se veut un exemple de sauvegarde de l'état des registres généraux.
  76.    
  77.     ; Demander N
  78.     ; D'abord afficher le message d'incitation
  79.     push incitation         ; --> 4- adresse du message d'incitation (4 bytes) est mise sur la pile
  80.     call _printf            ; _printf  utilise de l'information sur le fait de la pile  (ne modifie pas la pile)
  81.                     ; Ceci va faire l'affichage du message d'incitation.
  82.     add esp,4           ; <-- 4- enlever le paramètre de la pile
  83.                     ; Dans ce modèle-ci, vu que _printf est une procédure qui peut avoir un paramètre et plus, c'est à nous
  84.                     ; de faire le "ménage" des paramètres passés sur la pile. On sait que le paramètre passé était de 4 bytes,
  85.                     ; donc on ajoute 4 à la valeur du "stack pointer" ce qui est équivalent à "enlever" le 4 bytes du fait.
  86.  
  87.     ; Ensuite, on fait la lecture proprement dite
  88.     push N              ; --> 5- adresse de la variable N mise sur la pile
  89.     push format_input       ; --> 6- adresse du format de lecture mise sur la pile
  90.     call _scanf
  91.     add esp,8           ; <- 6- et <-- 5- enlever les paramètres de la pile
  92.    
  93.    
  94.     ; Faire un écho
  95.  
  96.     mov ebx, dword[N]       ; Mettre la valeur de N dans EBX. En NASM, [N] fait référence au contenu alors que N est seulement le déplacement.
  97.                     ; 'dword' est un cast. Il est équivalent au 'dword ptr' de MASM. Il veut dire 4 bytes de taille.
  98.     push ebx            ; --> 7-  Mettre la valeur à afficher sur le fait de la pile
  99.     push format_output      ; --> 8-  Mettre l'adresse de la chaîne sur la pile
  100.     call _printf            ; Afficher
  101.     add esp, 12         ; <-- 8 et   <-- 7 - enlever les 2 paramètres de la pile.
  102.    
  103.  
  104.    
  105.    
  106.     pop ecx             ; <-- 3- restauration des registres ecx et ebx.
  107.     pop ebx             ; <-- 2- Notez que les pop sont en ordre inverse des push de la sauvegarde.
  108.    
  109.     mov esp, ebp
  110.     pop ebp             ; <-- 1- restauration du ebp original
  111.    
  112.     mov eax, 0          ; "return 0 ;" comme dans le main() de C++
  113.                         ; À ce point-ci, vous devriez voir que le "return expression ;" du C++ veut juste dire
  114.                         ; - évaluer l'expression
  115.                         ; - mettre la valeur finale de l'expression dans le EAX
  116.                         ; - faire un ret
  117.     ret
  118.  
  119. ; Note vue sur internet dans un blogue :
  120.  
  121. ; "Also, note that, at least on Windows (using MinGW), printf stomps on EAX (return value), ECX, and EDX, and modifies EFLAGS.
  122. ;  As do all of the standard C functions, that I've used thus far, for that matter."
  123.  
  124. ; Donc, faire attention de sauvegarder et restaurer les registres que vous utilisez.
  125. ; Ne pas oublier d'enlever les paramètres que vous passez. (== Faire le ménage.)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement