Manipulations de la console

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

Manipulations de la console

Message par Admin le Ven 2 Déc - 17:44

C'est bien beau tout ça !! mais vous m'obligez à avoir toujours une console à l'arrière plan de mon programme et puis la police est trop petite et puis il n'a pas assez de nombre de lignes affichées et puis je veux des lettres en rouge !!
Et en plus cela serait bien si je pouvais saisir du texte et faire une pause dans l'affichage mais en assembleur ça va être très compliqué à écrire !!
Et bien cela est possible et relativement d'une manière simple.
Voyons ce code :
Code:

;************************************
;exemple manipulation console 64 bits
;manipconsole.asm
;************************************
%include "../windowsinc64.inc"
;BLACK equ 0    ; ces constantes ont été deportées dans le fichier ci dessus
;BLUE equ 1    ; mises en commentaires ici pour voir les differentes valeurs
;GREEN equ 2
;CYAN equ 3
;RED equ 4
;PURPLE equ 5
;YELLOW equ 6
;SYSTEM equ 7
;GREY equ 8
;BRIGHTBLUE equ 9
;BRIGHTGREEN equ 10
;BRIGHTCYAN equ 11
;BRIGHTRED equ 12
;BRIGHTPURPLE equ 13
;BRIGHTYELLOW equ 14
;WHITE equ 15

BUFFERSIZE equ 200   ; taille du buffer
;=============================================================================
section .data
;============================================================================
szTitre:   db "Mon message",0
szTitreConsole:  db 'Ma Console', 0
szMsgFin:   db 'Fin programme!', 0
szMsg db "Très bien l'Assembleur Win64!",0
ILGMSG  equ $ - szMsg    ; donne la longueur du message ci dessus
;structures
coorda: align 8
coord: istruc COORD
   at COORD.X,  dw  140
   at COORD.Y,  dw  1000
   iend
;instance position et taille de la console
rectconsa: align 8
rectcons:
 istruc SMALL_RECT
 at SMALL_RECT.Left, dw  0
 at SMALL_RECT.Top, dw  0
 at SMALL_RECT.Right, dw  100
 at SMALL_RECT.Bottom, dw  30
    iend
;
cFontExA: align 8          ; contient les information sur la police utilisée
CFontEx: istruc CONSOLE_FONT_INFOEX
iend
ILGCONSINFEX equ $ - CFontEx
;=============================================================================
section .bss
;=============================================================================
;ATTENTION respecter l'alignement des zones
hOut   resq 1   ; handle de la console de sortie
iByteLus        resq 1
sBuffer resb BUFFERSIZE
;=============================================================================
section .text
;=============================================================================
 global Main
 extern afferreur
Main:
 sub rsp,8h
 sub rsp,20h
 ;allocation des consoles output imput et erreur
 ;call FreeConsole     ; à mettre si vous avez mis l'option /console dans le linker
    call AllocConsole
 mov r9,__LINE__ - 1
 cmp rax,NULL
 je .erreur
    mov rcx,STD_OUTPUT_HANDLE
    call GetStdHandle    ; handle de la console de sortie
    mov [hOut],rax
    ;agrandissement de la taille maxi de la console
    mov rcx,rax ; handle de la console de sortie
 mov  rdx,[coord]   ; en X la largeur de la console, en Y le nombre de lignes maxi de la console
 call SetConsoleScreenBufferSize
 mov r9,__LINE__ - 1
 cmp rax,NULL
 je .erreur
 ;agrandissement de la console
 mov   rcx,[hOut]  ; handle de la console de sortie
 mov   rdx,TRUE
    mov   r8,rectcons ; indique la position et la taille de la fenêtre de la console
 call SetConsoleWindowInfo
 mov r9,__LINE__ - 1
 cmp eax,NULL
 je .erreur

 mov rcx,szTitreConsole
 call SetConsoleTitleA     ; Titre de la console
    mov edx,050014h;Y=5  X = 20 : 14h   (passage rapide de la position du curseur)
    mov rcx,[hOut]
    call SetConsoleCursorPosition    ; position du curseur
 mov r9,__LINE__ - 1
 cmp  eax,NULL
 je   .erreur
    mov rdx,RED  ;choix de la couleur
    mov rcx,[hOut]
    call SetConsoleTextAttribute  ; changement de la couleur de la police du texte
 mov r9,__LINE__ - 1
 cmp  eax,NULL
 je   .erreur
 mov dword[CFontEx+CONSOLE_FONT_INFOEX.cbSize],ILGCONSINFEX  ; longueur de la structure
 mov rcx,[hOut]                                            ; des infos sur la police utilisée
 mov rdx,TRUE
 mov r8,CFontEx      ; passage de la structure en parametre
 call GetCurrentConsoleFontEx   ; lecture des informations sur la police
 mov r9,__LINE__ - 1
 cmp  eax,NULL
 je   .erreur
 mov word[CFontEx+CONSOLE_FONT_INFOEX.dwFontSizeY],18   ; forçage de la taille de la police
 mov word[CFontEx+CONSOLE_FONT_INFOEX.dwFontSizeX],0   ; il faut mettre à zero cette information.
 mov rcx,[hOut]
 mov rdx,TRUE
 mov r8,CFontEx
 call SetCurrentConsoleFontEx  ; changement de la taille de la police
 mov r9,__LINE__ - 1
 cmp  eax,NULL
 je   .erreur
 
 add rsp,20h   ; on rend la place des parametres précédent
 sub rsp, 8h   ; donc on enleve déjà 8 octets pour preparer la pile
 push    0     ; avant le push du parametre qui enleve 8 octets sur la pile
 sub rsp, 20h   ; puis on enleve les 32 octets pour la place des 4 parametres
       ; mov qword[rsp+20h],0
 lea r9,[sBuffer]
    mov r8,ILGMSG
 mov rdx,szMsg
 mov rcx,[hOut]
    call WriteConsoleA   ; affichage dans la console
    mov r9,__LINE__ - 1
 cmp eax,NULL
 je .erreur
 call saisieClavier
 ; et pour finir affichage de la saisie dans un message
 mov rcx, 0       ; hWnd = HWND_DESKTOP
 mov rdx,sBuffer    ; texte a afficher
 mov r8,szTitre     ; titre de la fenetre
    mov r9, MB_OK|MB_ICONINFORMATION      ; uType = MB_OK et icone info
    call MessageBoxA
 mov r9,__LINE__ - 1
 cmp eax,NULL
 je .erreur
    call FreeConsole;close the console
 mov r9,__LINE__ - 1
 cmp eax,NULL
 je .erreur
 mov rax,1   ; pgm OK
 jmp .fin
.erreur:
    call afferreur
 mov rax,0
.fin:
 mov rcx,rax
    call ExitProcess
;=========================================================
; saisie de données au clavier
;=========================================================
saisieClavier:
    sub rsp,8h
    sub rsp,20h
 mov rcx,STD_INPUT_HANDLE
    call    GetStdHandle  ; recup de handle ( STD_INPUT_HANDLE)
 mov r9,__LINE__
 cmp eax,NULL
 je .erreur
    add rsp,20h
    sub rsp,8h  ; car un seul push    
 push   0             ;  parametre de fin de saisie (ici standard)
 sub rsp,20h
 mov rcx,rax   ; handle fonction précedente
 mov rdx,sBuffer     ; buffer
 mov r8,BUFFERSIZE
 mov r9, iByteLus       ; nb octets lus
 call   ReadConsoleA
 add rsp,10h   ; le push et l'alignement
    mov r9,__LINE__ -2
 cmp eax,NULL
 je .erreur
 mov rax,[iByteLus]
 sub rax,2
 mov byte [sBuffer+rax],0  ; forçage du 00 à la place du 0D final
 jmp .fin
.erreur:
 call afferreur
.fin:
    add rsp,8h
 add rsp,20h
    mov   rax,sBuffer  ; retour adresse du buffer
 ret  


Tout d'abord les constantes windows ont été déportées dans le fichier windowsinc64.inc Nous avons laissé les constantes de couleurs pour vous faciliter la lecture.
Dans la partie .data, nous trouvons les instances des structures COORD, SMALL_RECT et CONSOLE_FONT_INFOEX (les structures elles mêmes sont décrites dans le fichier windowsinc64.inc. En 64 bits, la description de ces structures n'est pas évidente car la documentation windows ne présente que les structures en 32 bits.
Ici ces données vont permettre de gerer les tailles maxi de la console, la position et la taille de la fenêtre d'affichage de la console et les informations concernant la police de caractères.  
Comme vous le remarquez, ces instances sont alignées sur des frontières de 8 octets.
Dans la partie code, nous précisons par la directive extern que la procèdure afferreur sera exterieure à ce programme ( et placée dans le fichier routineswin.asm).
Si la console a été allouée par l'option /console, nous appelons la fonction FreeConsole pour desallouée la console crée. Puis dans tous les cas nous créons les consoles par la fonction    AllocConsole. Nous récupérerons le handle de la console de sortie par la fonction GetStdHandle et nous le stockons dans la variable hOut.
Nous passons cette donnée et la structure COORD à la fonction SetConsoleScreenBufferSize pour agrandir la console en largeur et en nombre de lignes possible.
Ensuite, nous positionnons la fenêtre de la console sur l'écran de l'ordinateur et sa taille par SetConsoleWindowInfo.
En plus, nous changeons le titre de la console par SetConsoleTitleA et même la position du curseur par SetConsoleCursorPosition. Ici les 2 coordonnées de la position  sont forcées directement dans le registre rdx. Normalement il faudrait alimenter une structure COORD et passer le contenu dans le paramètre.
Nous changeons la couleur de la police utilisée par SetConsoleTextAttribute avec le paramètre RED.
Pour changer la taille de la police, nous commençons par récuperer les informations sur la police par la fonction GetCurrentConsoleFontEx qui va alimenter la structure CONSOLE_FONT_INFOEX. Comme cela il ne nous reste plus qu'à modifier les 2 zones de cette structure pour augmenter la taille  avant de la passer à la fonction SetCurrentConsoleFontEx.
Il ne nous reste plus qu'à afficher notre message en appelant la fonction WriteConsoleA comme nous l'avons déjà vu.
Et pour terminer, nous appelons la sous procèdure saisieClavier pour faire faire une pause au programme.
Dans cette dernière, nous commençons par récuperer le handle de la console d'entrée par la fonction GetStdHandle mais avec la constante STD_INPUT_HANDLE. Nous lisons la saisie clavier par ReadConsoleA à laquelle nous devons passer 5 paramètres et donc il nous faut aligner correctement la pile. La saisie sera récupérée dans un buffer mais il nous faudra modifier la fin pour remplacer la séquence 0D0A par la fin de chaine standard 0.
La procédure retourne dans le registre rax l'adresse du buffer. Le résultat sera affiché pour controle par un bête MessageBoxA.
Avec tout cela, vous pouvez maitriser les affichages et les saisies dans la console.
Maintenant, il faut utiliser la console pour afficher les outils nécessaires à la recherche des anomalies  à savoir le vidage de registres, le vidage d'une zone mémoire puis éventuellement le vidage des piles et du registre des Flags.

REMARQUE : à l'affichage du message en rouge dans la console, vous remarquez que les caractères accentués sont mal affichés. Cela provient du fait que la console utilise la page de code 850 et pas une des pages contenant les codes accentèes ANSI (comme la 1250). J'ai essayé de changer cette page de code par la fonction SetConsoleCP mais rien à faire je n'y suis pas arrivé.
Donc il faut forcer les caractères accentués avec les codes de la page 850 comme par exemple
à   85 , é 82, è 81 ê 88  voir sur https://fr.wikipedia.org/wiki/Page_de_code_850 le reste des codes.
ce qui donne dans notre cas :
Code:

szMsg db "Tr",81,"s bien l'Assembleur Win64!",0
avatar
Admin
Admin

Messages : 38
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