Assembleur 64 avec le compilateur nasm
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.

Cas de l'instruction enter

Aller en bas

Cas de l'instruction enter Empty Cas de l'instruction enter

Message par Admin Mer 30 Nov - 16:04

Précédemment, nous avons vu le passage d'un paramètre par push et sa récupération par l'instruction mov rax,[rsp+8]. Mais ce n'est pas la meilleure façon de procéder car l'adresse de la pile peut évoluer et donc l'adresse du paramètre aussi. Normalement il faut utiliser l'instruction enter qui va fixer la pile de base rbp en début d'une sous procédure.
L'instruction enter contient une instruction push rsp qui va déphaser la pile de 8 octets et donc après cette instruction il faudra réaligner la pile (ne pas oublier les 8 octets du call et les 8 octets du push du parametre).
Mais attention, l'instruction enter sert dans son premier paramètre à réserver de la place pour stocker des données locales à la procédure (bien utile en cas d'appel récursif de la procédure). Si nous réservons 8 octets par exemple et bien nous déphasons de nouveau la pile de 8 octets et donc nous devrons gérer son impact.
Globalement  si nous avons un nombre de paramètres plus le nombre de réservation de 8 octets de variable locales impair , nous devons réaligner la pile . Si ce nombre est pair, il ne faut pas la réaligner.
Voyons 2 exemples :
Passage de 2 paramètres et  réservation de place par enter :
Code:

;hello3.asm programme verification alignement de la pile
; apres passage parametre par push  et instruction enter
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
 push  szTitre
 push szMsg1   ; passage de 2 parametres
    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:
    enter 8,0      ; réserve 8 octets pour utilisation locale
 sub rsp,8h  ; nous avons 2 push + une reservation  = 3  impair donc la pile doit être alignée
    sub rsp,20h     ; réservation place des 4 parametres
 mov rcx, 0       ; handle  fenêtre
    mov rdx,[rbp+16]  ; adresse du message contenu dans la pile de base
    mov r8,[rbp+24]  ; adresse du titre de la fenêtre (1er  parametre)
    mov r9, MB_OK       ;  Normal
    call MessageBoxA
 cmp rax,0
 jne .fin
 call afferreur
.fin:
 leave          ; remet la pile en place à partir de la pile de base
    ret 16       ; RE ATTENTION nous avons passé Deux parametres de 8 octets
;=================================================================
; 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

Passage de 2 paramètres et reservation de 2 fois 8 octets (non utilisés ici).
Code:

;hello4.asm programme verification alignement de la pile
; apres passage parametre par push  et instruction enter
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
 push  szTitre
 push szMsg1   ; passage de 2 parametres
    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:
    enter 16,0      ; 2 reservations pour varaibles locales
 ;sub rsp,8h  ; nous avons 2 push  + 2 reservations pair donc La pile ne doit pas être alignée
    sub rsp,20h     ; réservation place des 4 parametres
 mov rcx, 0       ; handle  fenêtre
    mov rdx,[rbp+16]  ; adresse du message contenu dans la pile de base
    mov r8,[rbp+24]  ; adresse du titre de la fenêtre (1er  parametre)
    mov r9, MB_OK       ;  Normal
    call MessageBoxA
 cmp rax,0
 jne .fin
 call afferreur
.fin:
 leave          ; remet la pile en place à partir de la pile de base
    ret 16       ; RE ATTENTION nous avons passé Deux parametres de 8 octets
;=================================================================
; 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

En fin de procédure, le leave (pendant du enter) restaure la pile à partir de bsp et donc il est inutile de libérer l'espace pris par les alignements. enfin la procédure se termine par l'instruction ret 16 pour tenir compte du push des 2 paramètres.
Voilà voilà !!!
Admin
Admin
Admin

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

https://assembleur64.kanak.fr

Revenir en haut Aller en bas

Revenir en haut


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