Appel d'un sous programme
Page 1 sur 1
Appel d'un sous programme
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 :
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 vous pouvez supprimer les instructions d'alignement et voir leur impact.
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 vous pouvez supprimer les instructions d'alignement et voir leur impact.
Sujets similaires
» Appel d'une fonction de l'API avec plus de 4 paramètres
» Programme de lancement de la compilation et du linker
» Premier programme : affichage d'un message
» Programme de lancement de la compilation et du linker
» Premier programme : affichage d'un message
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
|
|