Appel d'un sous programme

Voir le sujet précédent Voir le sujet suivant Aller en bas

Appel d'un sous programme

Message par Admin le Mar 29 Nov - 21:16

Nous allons compliquer le premier programme en effectuant un appel à un sous programme, et en testant le code retour d'une fonction pour afficher un message d'erreur. Le code de l'erreur est retourné par la fonction GetLastError dans le registre rax et nous allons appeler la fonction wsprintA pour formater le message d'erreur.
Nous remplaçons le type du message à afficher par les constantes normalisées (0 devient donc MB_OK).
Nous remplaçons aussi les instructions lea par des mov pour alimenter les adresses des chaines (remarquez, quand même la différence de codification : utilisation ou non des [ ] , source d'erreurs fréquentes).
Voici le code :
Code:

;programme fenetre windows en 64 bits
global Main
extern ExitProcess,MessageBoxA,GetLastError,wsprintfA     ; fonction API windows
MB_OK equ 000h
MB_OKCANCEL equ 001h
MB_ICONERROR equ 010h
MB_ICONINFORMATION  equ 040h
;==============================================
;données initialisées
;==============================================
section .data
szTitre:  db 'Win64', 0
szTitreErreur:  db 'Win64', 0
szMsg:    db 'Hello world!', 0
szMsg1    db "Appel ok",0
szMsgErreur db "Erreur  N° %d",0
;==============================================
; données non initialisées
;==============================================
section .bss
szZoneRep   resb 80

section .text
Main:
    sub rsp, 28h  
    mov rcx, 0       ; handle  fenêtre
    lea rdx,[szMsg]    ; adresse du message
    lea r8,[szTitre]   ; adresse du titre de la fenêtre
    mov r9, MB_OK|MB_ICONINFORMATION       ;  type du message : OK
    call MessageBoxA
    call appel
    mov  rcx,rax     ; code retour avec le code retour de MessageBoxA
    call ExitProcess  ; fonction de fin du programme
;=================================================================
; verification lors de l'appel
;=================================================================
appel:
 sub rsp,8h
    sub rsp,20h
 mov rcx, 0       ; handle  fenêtre
    mov rdx,szMsg1   ; adresse du message
    mov r8,szTitre   ; adresse du titre de la fenêtre
    mov r9, -1       ;  forçage d'une erreur
    call MessageBoxA
 cmp rax,0
 jne .fin
 call afferreur
.fin:
    add rsp,28h
    ret
;=================================================================
; affichage du message d'erreur
;=================================================================
afferreur:
    sub rsp,8h
    sub rsp,20h
 call GetLastError   ;récupèration du code erreur dans le registre rax
 mov rcx,szZoneRep   ; zone de retour du formatage
 mov rdx,szMsgErreur ; libellé du message
 mov r8,rax       ; code erreur
 call wsprintfA   ; on devrait tester aussi le code retour
 mov rcx, 0       ; handle  fenêtre
    mov rdx,szZoneRep   ; adresse du message
    mov r8,szTitreErreur   ; adresse du titre de la fenêtre
    mov r9, MB_OKCANCEL|MB_ICONERROR       ;  type du message : Erreur
    call MessageBoxA
.fin:
   add rsp,28h
   ret

La procédure maître Main est identique à celle du programme précédent, et nous avons ajouté un call à la sous procédure appel.
Ce call va stocker l'adresse de retour sur la pile, ce qui entraine un déphasage de la pile de 8 octets et donc nous allons la réaligner par l'instruction sub rsp,8h. Nous réservons aussi la place des 4 paramètres standards pour l'appel des fonctions par sub rsp,20h.
Pour l'appel de la fonction MessageBoxA, nous forçons la valeur -1 dans le type du message pour générer volontairement une erreur. Nous testons le code retour de la fonction et s'il est égal à zéro nous appelons une sous procédure d'affichage du code erreur.
Nous avons à nouveau désaligné la pile et donc nous devons à nouveau mettre l'instruction sub rsp,8h puis l'instruction sub rsp,20H avant d'appeler la fonction GetLasterror
La fonction wsprintfA nécessite le passage de l'adresse d'une zone réceptrice  dans rcx, d'une instruction de formatage dans rdx et de la valeur à formater dans rcx. La zone réceptrice est passé à la fonction MessageBoxA pour être affichée.
IMPORTANT : la fin des sous procédures se termine par un ret et non pas comme dans la fonction principale par un appel à ExitProcess. C'est donc à nous à rétablir correctement la pile par l'instruction add rsp,28h avant le retour. Si vous l'oubliez ou si vous mettez une mauvaise valeur, le ret ne retrouvera pas la bonne adresse de retour à la fonction appelante et vous aurez un crash du programme (mais pas systématique !!).
Vous remarquerez aussi qu'il n'est pas utile de mettre une instruction de réservation sub rsp,20h entre les appels de chaque fonction (mais vous la trouverez à tort dans des exemples de programme sur internet).
Vous pouvez modifier les types de message pour regarder l'impact sur l'affichage ou essayer de générer différents codes erreurs.
Si vous aimez les crash de programmes Laughing vous pouvez supprimer les instructions d'alignement et voir leur impact.
avatar
Admin
Admin

Messages : 37
Date d'inscription : 28/11/2016

Voir le profil de l'utilisateur http://assembleur64.forumactif.com

Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum