Recherche de chaines dans des sources de programmes assembleur

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

Recherche de chaines dans des sources de programmes assembleur

Message par Admin le Sam 25 Fév - 20:32

Pour vous montrer les possibilités des appels de fonctions de l'API windows, voici un programme complet en assembleur.
Comme au bout d'un moment, je n'arrivai plus à retrouver dans quel programme j'utilisais telle fonction windows, j'ai écrit un programme qui à partir de l'include qui contient toutes les fonctions windows utilisées (instruction extern), recherche dans tous les programmes assembleurs stockés dans un répertoire et ses sous repertoires, l'utilisation de ces fonctions. Le programme génère un fichier .csv qui contient le nom de la fonction et les noms complets des 5 premiers programmes qui l'utilisent.
Ce programme peut être amélioré car il ne teste pas les dépassements des tas qui stockent les chaines de caractères et en plus il ne vérifie pas qu'une fonction est utilisée plusieurs fois dans le même programme !!
Donc vous trouverez un exemple de boite de dialogue, de lecture de fichier, d'analyse de caractères, de stockage par ordre alphabétique dans une table, de balayage de répertoire et de sous répertoires, de recherche dichotomique et d'écriture dans un fichier.
Code:

;---programme 64 bits
; recherche dans les sources des fonctions appelées

%include "../windowsinc64.inc"

;=======================================
; segment des données initialisées
;=======================================
segment .data
;code page 850 é=82h  à=85h è=8Ah ê=88h 
szChForm db "%u ",0  ; format décimal pour la fonction wsprintfA

szMessFin  db 10,13,"Fin du programme.",0
szRetourLigne db 10,13,0
szExtention  db ".asm",0

;************************************************************
;identification des controles de la boite
ID_EDIT1    equ 200  ; zone de saisie
IDD_LB1      EQU   201  ; list box
ID_TXT1      EQU   202  ; texte simple
ID_TXT2    EQU 203
ID_EDIT2    equ 204  ; zone de saisie
;************************************************************
;libellés des textes à afficher dans la Boite de Dialogue
szTitreDialog db "RECHERCHE FONCTIONS",0
ILGTD  equ $ - szTitreDialog  ;et leur longueur
szTitreBouton db "OK",0
ILGTB1  equ $ - szTitreBouton
szTitreBouton2 db "FIN",0
ILGTB2  equ $ - szTitreBouton2
szTitreTexte db "Fichier des extern :",0
ILGTT1  equ $ - szTitreTexte
szInitSaisie db "../windowsinc64.inc",0
ILGTS1  equ $ - szInitSaisie
szTitreTexte2 db "Répertoire à analyser :",0
ILGTT2  equ $ - szTitreTexte2
szInitSaisie2 db "C:/Developpement/Assembleur/Projets/projet64/Tut24/*",0
ILGTS2  equ $ - szInitSaisie2
;************************************************************
;Description de la boite de dialogue
;entête des données générales
lpdta:  align 4              ; Important
lpdt: istruc DLGTEMPLATE
  at DLGTEMPLATE.style, dd  WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION    | DS_MODALFRAME |  WS_VISIBLE
  at DLGTEMPLATE.cdit, dw 6  ; nombre de controles
  at DLGTEMPLATE.x, dw 10    ; position du coin à gauche  de la boite de dialogue
  at DLGTEMPLATE.y, dw 10    ; et en haut
  at DLGTEMPLATE.cx, dw 410  ; largeur de la boite
  at DLGTEMPLATE.cy, dw 200  ; hauteur de la boite
iend 
lpdtmenu  dw 0  ; pas de menu
lpdtclass  dw 0 
szTitreD  Times (ILGTD * 2) db 0 ; titre de la fenêtre mais hélas en caractères Unicode

;description du premier controle (attention ce n'est peut être pas le premier de l'écran)
lpditC1a:  align 4            ; Important
lpditC1:  istruc DLGITEMTEMPLATE
   at DLGITEMTEMPLATE.style, dd WS_CHILD | WS_VISIBLE  | BS_DEFPUSHBUTTON | WS_TABSTOP
   at DLGITEMTEMPLATE.dwExtendedStyle, dd WS_EX_NOPARENTNOTIFY
   at DLGITEMTEMPLATE.x, dw 10  ;position à gauche du controle dans la boite
   at DLGITEMTEMPLATE.y, dw 100  ; position en haut du controle dans la boite
   at DLGITEMTEMPLATE.cx, dw 80  ; largeur du controle
   at DLGITEMTEMPLATE.cy, dw 15  ; hauteur du controle
   at DLGITEMTEMPLATE.id, dw IDOK  ; identification
iend
sysClassC1  dw 0xFFFF    ; toujours cette valeur
idClassC1  dw 0x0080    ; c'est un bouton
szTitreC1  Times (ILGTB1 * 2) db 0  ; libellé en caractères unicode
cbCreationDataC1 dw 0  ; à voir
;description du 2ième controle bouton FIN
lpditC2a:  align 4
lpditC2:  istruc DLGITEMTEMPLATE
   at DLGITEMTEMPLATE.style, dd WS_CHILD | WS_VISIBLE | WS_TABSTOP
   at DLGITEMTEMPLATE.dwExtendedStyle, dd WS_EX_NOPARENTNOTIFY
   at DLGITEMTEMPLATE.x, dw 120
   at DLGITEMTEMPLATE.y, dw 100
   at DLGITEMTEMPLATE.cx, dw 80
   at DLGITEMTEMPLATE.cy, dw 15
   at DLGITEMTEMPLATE.id, dw IDCLOSE  ; identification
iend
sysClassC2  dw 0xFFFF    ; toujours cette valeur
idClassC2  dw 0x0080    ; c'est un bouton
szTitreC2  Times (ILGTB2 * 2) db 0  ; libellé en caractères unicode
cbCreationDataC2 dw 0  ; à voir

;description du 3ième controle  libelle
lpditC3a:  align 4
lpditC3:  istruc DLGITEMTEMPLATE
   at DLGITEMTEMPLATE.style, dd  WS_VISIBLE    ; on peut ajouter  WS_BORDER  si on veut l'entourer
   at DLGITEMTEMPLATE.x, dw 10                ; d'une bordure
   at DLGITEMTEMPLATE.y, dw 10
   at DLGITEMTEMPLATE.cx, dw 100
   at DLGITEMTEMPLATE.cy, dw 15
   at DLGITEMTEMPLATE.id, dw ID_TXT1 ; identification
iend
sysClassC3  dw 0xFFFF
idClassC3  dw 0x0082  ; c'est du texte statique
szTitreC3  Times (ILGTT1 * 2) db 0
cbCreationDataC3 dw 0

;description du 4ième controle 
lpditC4a:  align 4
lpditC4:  istruc DLGITEMTEMPLATE
   at DLGITEMTEMPLATE.style, dd ES_LEFT | WS_BORDER |  WS_CHILD |WS_TABSTOP| WS_VISIBLE
   at DLGITEMTEMPLATE.x, dw 90
   at DLGITEMTEMPLATE.y, dw 10
   at DLGITEMTEMPLATE.cx, dw 150
   at DLGITEMTEMPLATE.cy, dw 10
   at DLGITEMTEMPLATE.id, dw ID_EDIT1  ; identification
iend
sysClassC4  dw 0xFFFF
idClassC4  dw 0x0081  ; c'est une zone de saisie
            db 0      ; pas de libellé
cbCreationDataC4 dw 0
szfinC4 db 0

;description du 5ième controle
lpditC5a:  align 4
lpditC5:  istruc DLGITEMTEMPLATE
   at DLGITEMTEMPLATE.style, dd  WS_VISIBLE    ; on peut ajouter  WS_BORDER  si on veut l'entourer
   at DLGITEMTEMPLATE.x, dw 10                ; d'une bordure
   at DLGITEMTEMPLATE.y, dw 30
   at DLGITEMTEMPLATE.cx, dw 100
   at DLGITEMTEMPLATE.cy, dw 20
   at DLGITEMTEMPLATE.id, dw ID_TXT2 ; identification
iend
sysClassC5  dw 0xFFFF
idClassC5  dw 0x0082  ; c'est du texte statique
szTitreC5  Times (ILGTT2 * 2) db 0
cbCreationDataC5 dw 0

;description du 6ième controle 
lpditC6a:  align 4
lpditC6:  istruc DLGITEMTEMPLATE
   at DLGITEMTEMPLATE.style, dd ES_LEFT | WS_BORDER |  WS_CHILD |WS_TABSTOP| WS_VISIBLE
   at DLGITEMTEMPLATE.x, dw 90
   at DLGITEMTEMPLATE.y, dw 30
   at DLGITEMTEMPLATE.cx, dw 300
   at DLGITEMTEMPLATE.cy, dw 10
   at DLGITEMTEMPLATE.id, dw ID_EDIT2  ; identification
iend
sysClassC6  dw 0xFFFF
idClassC6  dw 0x0081  ; c'est une zone de saisie
            db 0      ; pas de libellé
cbCreationDataC6 dw 0
szfinC6 db 0
;
szfinb db 0,0,0,0,0,0    ; zone de sécurité si pb de longueur
szFileTitle  db "Choix du fichier ",0
szFilter   db   "csv Files (*.csv)",0,"*.csv",0
          db   "All Files (*.*)",0,"*.*",0,0
szDefExt   db   "csv",0
;instance de la structure des fichiers
ofna: align 8
ofn:
   istruc OPENFILENAME
    at OPENFILENAME.nFilterIndex,  dd  1h
    at OPENFILENAME.nMaxFile,      dd MAX_PATH
    at OPENFILENAME.nMaxFileTitle, dq MAX_PATH
  iend
ILGOFN  equ $ - ofn   ;longueur de la structure ofn

infFile    istruc WIN32_FIND_DATA
   iend
ILGINFFILE equ $ - infFile

ILGNOM equ 1240
struc  RESULT1
 .cpt  resq 1
 .ptnom resq 1
 .nompgm resb ILGNOM    ;
endstruc
iresulta: align 8
iResult  istruc RESULT1
iend 
ILGRESULT1 equ $ - iResult
ptTasPgm dq sTasPgm  ; pointeur du tas des noms des programmes
ptTasExt dq sTasExt  ; pointeur du tas des noms des fonctions

;=======================================
; segment des données non initialisées
;=======================================
segment .bss
hMain  resq 1
hDlg    resq 1
hFile  resq 1
iNbByteLu resq 1
iTailleFic resq 1
iNbfoncExt resq 1
iLgBuffer  resq 1
iNbByteEcrit resq 1
iTablePt  resq 400
iTablePgm resq 400
;autre alignement
szResult  resb 100
szFile  resb 200
ILGBUF1 equ 100
szFileExt resb ILGBUF1
ILGBUF2 equ 100
szNomRep resb ILGBUF2
szNomComplet resb MAX_PATH * 2
ILGBUFFER equ 1000000
szBuffer  resb ILGBUFFER
sTasExt  resb 50000
sTasPgm  resb 500000
sBufferEcr resb 500000

;=======================================
; segment de code
;=======================================
segment .text
    global Main
   extern afferreur,affmessageP,affconsoleP,afftoutregistreP,afftoutreg8a15P,affmemoireP,affmessage,saisieClavier,vidpiles
Main:
    sub rsp, 8h    ; alignement de la pile avant tout appel de procédure
   sub rsp,20h
    ;recup handle de l'instance du programme
   mov  rcx,NULL
   call GetModuleHandleA
   mov r9,__LINE__ - 1
   cmp  eax,NULL
   je  .gestionerreurs
   mov [hMain],rax
   call creationBD  ; creation de la boite de dialogue
   mov rax,0
   jmp .main_fin
.gestionerreurs:
   call afferreur
   mov  rax,1
   jmp .fin
.main_fin:   
.fin:   
   mov  rcx,rax          ; code retour
   call ExitProcess  ; fin du programme

;===================================================
; creation de la boite de dialogue
;===================================================   
creationBD:
%define .iVar1  [rbp-8]
    enter 8,0
    sub rsp,8h    ; enter  et 1 locale
   ;add rsp,20h    ; 2 push donc pas d'alignement
   push ILGTD * 2    ; taille de la zone de reception (voir s'il ne faut pas ajouter un pour la fin)
   push szTitreD    ; zone de reception
   sub rsp, 20h 
   mov rcx,CP_ACP  ; code page ANSI par défaut
   mov rdx,0      ; flags qui indiquent les types de conversion (voir la doc )
   mov r8,szTitreDialog ; zone à convertir
   mov r9,-1  ; taille de la zone à convertir, si -1 la chaine est terminée par zero
               ; et c'est la fonction qui determinara la taille
   call MultiByteToWideChar  ;fonction de conversion ANSI ==> UNICODE
   add rsp,10h  ; pour les 2 push
   mov r9,__LINE__
   cmp eax,NULL
   je .erreurs
    add rsp,20h
   push ILGTB1 * 2
   push szTitreC1
   sub rsp, 20h 
   mov rcx,CP_ACP
   mov rdx,0
   mov r8, szTitreBouton
   mov r9,-1
   call MultiByteToWideChar
   add rsp,10h  ; pour les 2 push
   mov r9,__LINE__
   cmp eax,NULL
   je .erreurs
   
   add rsp,20h
   push ILGTB2 *2
   push szTitreC2
   sub rsp, 20h 
   mov rcx,CP_ACP
   mov rdx,0
   mov r8, szTitreBouton2
   mov r9,-1
   call MultiByteToWideChar
   add rsp,10h  ; pour les 2 push
   mov r9,__LINE__
   cmp eax,NULL
   je .erreurs
   add rsp,20h
   push ILGTT1 *2
   push szTitreC3
   sub rsp, 20h 
   mov rcx,CP_ACP
   mov rdx,0
   mov r8, szTitreTexte
   mov r9,-1
   call MultiByteToWideChar
   add rsp,10h  ; pour les 2 push
   mov r9,__LINE__
   cmp eax,NULL
   je .erreurs
   add rsp,20h
   push ILGTT2 *2
   push szTitreC5
   sub rsp, 20h 
   mov rcx,CP_ACP
   mov rdx,0
   mov r8, szTitreTexte2
   mov r9,-1
   call MultiByteToWideChar
   add rsp,10h  ; pour les 2 push
   mov r9,__LINE__
   cmp eax,NULL
   je .erreurs
      ; création boite de dialogue
   add rsp,20h
   sub rsp,8h
   push NULL  ; pas de parametre
   sub rsp,20h
   mov rcx,[hMain]  ; instance du programme à laquelle sera attachée la boite
   mov rdx,lpdt    ; adresse de début de la structure d'entête de la boite de dialogue
   mov r8,NULL   
   mov r9,Proc_Dialogue  ; procédure de gestion des évenements de la boite
   call DialogBoxIndirectParamA  ; création de la boite
   add rsp,10h
   mov r9,__LINE__
   cmp rax,NULL
   je .erreurs
   mov [hDlg],rax    ; conservation du handle de la boite attribuée par windows
   jmp .fin
.erreurs:
    call afferreur
.fin:   
   leave
   ret
;===================================================
;procedure boite de dialogue  ; même paramètre que fenetre
;===================================================
; va traiter les évenements de la boite dialogue ( clic, appui sur bouton, fermeture etc). 
; windows appelle cette fonction en lui passant 4 parametres dans les registres rcx,rdx,r8,r9
Proc_Dialogue:
%define hWnd rbp+16     ; pour simplifier l'ecriture dans les instructions suivantes
%define uMsg rbp+24
%define wParam rbp+32
%define lParam rbp+40
    mov [rsp+8],rcx  ; handle fenêtre  voir l'utilité est-ce bien necessaire
   mov [rsp+16],rdx  ; type de message
   mov [rsp+24],r8  ; wparam
   mov [rsp+32],r9  ; lparam
   enter 0,0        ; pour récuperer les valeurs definies plus haut
   sub rsp,20h      ; reservation standard
    mov rax,[uMsg] ; umsg contient le type de message lié à l'evenement de la boite 
   cmp rax,WM_INITDIALOG  ; initialisation de la boite
   je  .init
   cmp eax,WM_DESTROY    ; fermeture de la fenêtre
   je .close
   cmp rax,WM_CLOSE    ; fermeture de la fenetre
   je .close
   cmp rax,WM_COMMAND    ; appui sur les boutons
   je .bouton
   add rsp,20h
   leave
   mov rax,FALSE    ; IMPORTANT pour tous les autres messages non traités
   ret
;******************************Appui sur les boutons
.bouton:
    mov rax,[wParam] ; wparam
   cmp rax,IDOK      ; c'est lequel ?
   jne .autrebouton
   ;traitement du bouton OK
   mov rcx,[hWnd]    ; handle de la boite
   mov rdx,ID_EDIT1  ; identification de la zone de saisie
   mov r8,szFileExt  ; buffer de reception
   mov r9,ILGBUF1    ; longueur maxi du buffer
   call GetDlgItemTextA; recuperation du texte de la zone saisie   
   mov r9,__LINE__ - 1
   cmp rax,0
   je .erreur
   mov rcx,szFileExt  ;nom du fichier pour les extern
   call lectFichier    ; lecture du fichier
   call analyseExt    ; recherche des fonctions externes
   mov rcx,[hWnd]    ; handle de la boite
   mov rdx,ID_EDIT2  ; identification de la zone de saisie
   mov r8,szNomRep  ; buffer de reception
   mov r9,ILGBUF2    ; longueur maxi du buffer
   call GetDlgItemTextA; recuperation du texte de la zone saisie   
   mov r9,__LINE__ - 1
   cmp rax,0
   je .erreur
   mov rcx,szNomRep  ; nom du repertoire de départ
   call analyseReper  ; analyse des repertoires
    call creationbuffer  ; creation du buffer d'écriture
    call ecritureFic    ; ecriture du fichier des résultats
   jmp .fin
.autrebouton:   
   cmp rax,IDCLOSE  ; c'est le bouton fin donc on ferme la boutique
   je .close
   cmp rax,IDCANCEL  ;fermeture  par <ESC>
   je .close
   add rsp,20h
   leave
   mov rax,FALSE    ; IMPORTANT pour tous les autres messages non traités
   ret
;==========================
.init:  ; initialisation de la BdD
   add rsp,20h
   sub rsp,8h  ; 1 seul push donc alignement pile à faire
   push  szInitSaisie  ; initialisation zone de saisie
   sub rsp,20h
   mov rcx,[hWnd]    ; handle de la BdD
   mov rdx,ID_EDIT1    ; identifiant de la zone d'edition
   mov r8,WM_SETTEXT  ; c'est du texte
   mov r9,0
    call  SendDlgItemMessageA  ; pour maj de la zone d'edition avec le texte
   add rsp,10h    ; 1 push et 1 alignement
   add rsp,20h
   sub rsp,8h  ; 1 seul push donc alignement pile à faire
   push  szInitSaisie2  ; initialisation zone de saisie
   sub rsp,20h
   mov rcx,[hWnd]    ; handle de la BdD
   mov rdx,ID_EDIT2    ; identifiant de la zone d'edition
   mov r8,WM_SETTEXT  ; c'est du texte
   mov r9,0
    call  SendDlgItemMessageA  ; pour maj de la zone d'edition avec le texte
   add rsp,10h    ; 1 push et 1 alignement
   jmp .fin

;==================================================
.close:
    mov rcx,[hWnd]    ; handle de la boite
   mov rdx,IDCANCEL
    call EndDialog  ; fermeture de la boite de dialogue
   mov rcx,0        ; valeur de retour
    call PostQuitMessage   ; envoie du message de fin (WM_QUIT)
   jmp .fin                ; attention, il ne faut pas l'envoyer systématiquement
.erreur:
    call afferreur   
.fin:
    add rsp,20h  ; libération place
   leave        ; pendant du enter
   mov rax,TRUE  ; IMPORTANT pour le bon fonctionnement
   ret          ;
;================================================================
;lecture fichier
;================================================================
;rcx contient l'adresse du nom du fichier à lire
lectFichier:
   sub rsp,8h  ; alignement standard
;lecture fichier   
   sub rsp,8h  ; 3 push
   xor rax,rax
   push NULL
    push FILE_ATTRIBUTE_NORMAL
    push OPEN_EXISTING
   sub rsp,20h
   ;rcx contient le nom du fichier à lire
   mov rdx,GENERIC_READ
   mov r8,0
   mov r9,NULL
    call  CreateFileA
   add rsp,20h    ; 3 push et 1 alignement
   mov r9,__LINE__
   cmp eax,-1
   je .erreur
   mov [hFile],rax
   ;recherche taille du fichier pour allocation buffer
   xor rcx,rcx
   mov ecx,eax    ; handle du fichier
   mov rdx, iTailleFic  ; zone de reception de la taille
   call GetFileSizeEx
   mov r9,__LINE__
   cmp eax,NULL
   je .erreur
   mov rcx,[iTailleFic]  ; récupération de la taille
   add rsp,20h
    sub rsp,8h   
    push NULL
   sub rsp,20h
   xor rcx,rcx
   mov ecx, dword[hFile] ; handle du fichier
   mov rdx,szBuffer
   mov r8,[iTailleFic]
   mov r9,iNbByteLu
   call ReadFile
   add rsp,10h
   mov r9,__LINE__
   cmp eax,0
   je .erreur
   ;fermeture du fichier
   xor rcx,rcx
   mov ecx,[hFile]
   ;push dword[hFile]
   call CloseHandle
   mov r9,__LINE__
   cmp eax,0
   je .erreur
   jmp .fin
.erreur:
    call afferreur
.fin:   
   add rsp,28h
   ret
;==============================================================
; analyse buffer pour retrouver les extern
;==============================================================
analyseExt:
   sub rsp,8h
  ;init
  mov rbx,0
.boucle: 
  ;lire un caractere
  cmp byte[szBuffer+rbx],0
  je .fin
  ;si 0 fin
  cmp byte[szBuffer+rbx],10 ;si 10 ou 13 boucle
  je .suiteboucle
  cmp byte[szBuffer+rbx],13
  je .suiteboucle
  cmp byte[szBuffer+rbx],' ' ;si blanc boucle
  je .suiteboucle
  cmp byte[szBuffer+rbx],'e';si caractere est dif de e  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],'x';si caractere est dif de x  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],'t';si caractere est dif de x  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],'e';si caractere est dif de x  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],'r';si caractere est dif de x  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],'n';si caractere est dif de x  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],' ';si caractere est dif de x  boucle
  jne .suiteboucle
.bouclebl: 
   ;chercher blanc puis boucler jusqu'a un caractere  (2)
  inc rbx
  cmp byte[szBuffer+rbx],' '
  je .bouclebl
  mov rdi,[ptTasExt]  ; pointeur du debut de la fonction
.bouclefonct:
   mov  al,[szBuffer+rbx] ;recopie du nom de la fonction
   mov  r12,[ptTasExt]    ; sur le tas
   mov  byte[r12],al
   inc qword[ptTasExt]
   inc rbx
    ;si  0 fin
  cmp byte[szBuffer+rbx],0
  je .finfonct
  cmp byte[szBuffer+rbx],10 ;si 10 ou 13
  je .finfonct
  cmp byte[szBuffer+rbx],13
  je .finfonct
  cmp byte[szBuffer+rbx],' ' ;si blanc
  je .finfonct
  cmp byte[szBuffer+rbx],',' ;si virgule
  jne .bouclefonct  ; boucle autrement
.finfonct: 
  mov  r12,[ptTasExt]
  mov  byte[r12],0  ; 0 pour la fin de chaine
  inc qword[ptTasExt]
  ; envoyer le nom de la fonction à la procedure de stockage
  call stockFonction
  mov rdi,[ptTasExt]  ; pointeur du debut de la fonction suivante
.bouclesuite: 
  cmp byte[szBuffer+rbx],0
  je .fin
  cmp byte[szBuffer+rbx],10 ;si 10 ou 13 boucle
  je .suiteboucle
  cmp byte[szBuffer+rbx],13
  je .suiteboucle
  cmp byte[szBuffer+rbx],',' ;si virgule
  je .suitefonct
  ;donc je dois être sur un blanc
  inc rbx
  jmp .bouclesuite
.suitefonct:  ; une virgule donc autre donnee
  inc rbx
  jmp .bouclefonct 
.suiteboucle:
    inc rbx
   jmp .boucle
.fin:   
   add rsp,8h
   ret
;=============================================================
;stockage pointeur fonction dans table
;=============================================================
;rdi contient le pointeur de debut de la chaine
stockFonction:
    sub rsp,28h
   cmp qword[iNbfoncExt],0
   jne .suiteins
   mov [iTablePt],rdi  ; première fonction à stocker
   inc qword[iNbfoncExt]
   jmp .fin
.suiteins:    ; autres fonctions à stocker
    mov r13,0
.bouclerech:
    mov rcx,[iTablePt+8*r13]
   mov rdx,rdi
   call lstrcmp      ; fonction windows
   cmp eax,0
   jg .plusgrand
   jl .pluspetit
   jmp .fin  ; egalité donc deja stockée
.pluspetit:
    inc r13    ; on incremente le compteur
    cmp r13,[iNbfoncExt]  ; mais on atteint le dernier poste
    jge .insertion     ; donc il faut inserer en fin de table
   jmp .bouclerech  ; sinon on continue la recherche
.plusgrand:
    mov rcx,[iNbfoncExt]  ; il faut donc deplacer
    mov rdx,rcx      ; toutes les fonctions déjà stockées
    dec rcx          ; pour faire un trou
.boucledepl:   
    mov rax,[iTablePt+8*rcx]   ; donc on deplace chaque poste
   mov [iTablePt+8*rdx],rax
   dec rcx
   dec rdx
   cmp rcx,r13
   jge .boucledepl
.insertion:            ; et on insere le nouveau nom dans le trou
    mov [iTablePt+8*r13],rdi ; à la bonne place dans l'ordre alpha
   inc qword[iNbfoncExt]
.fin:   
   add rsp,28h
   ret
;==========================================================
;analyse repertoire
;==========================================================
; rcx nom du repertoire à analyser
; procedure recursive donc les données internes necessaires
;doivent être stockées dans la pile
analyseReper:
%define .hFile  [rbp-8]    ; pointeur handle fichier
%define .repert [rbp-232]  ; zone contenant le nom complet du repertoire
%define .infFile [rbp-632] ; zone necessaire aux fonctions de recherche
   enter 640,0
   sub rsp,20h
   mov rdx,rcx  ; copie du nom du repertoire dans la zone de la pile
   lea rcx,.repert
   call lstrcpy
   lea rcx,.repert  ; on garde le repertoire
   lea rdx,.infFile    ; structure pour le balayage des fichiers
   call FindFirstFileA  ; recherche du premier fichier
   mov r9,__LINE__
   cmp eax,NULL
   je .erreur
   mov .hFile,rax 
.boucle:   ; traitement de tous les fichiers du repertoire
   xor rax,rax
   lea r14,.infFile
   mov eax,[r14+WIN32_FIND_DATA.dwFileAttributes]
   and eax,FILE_ATTRIBUTE_DIRECTORY      ; est-ce un repertoire ?
   cmp eax,0
   jne .repertoire
   lea rcx,[r14+WIN32_FIND_DATA.cFileName]
   ; il ne faut prendre que les fichiers extention .asm
    lea rcx,[r14+WIN32_FIND_DATA.cFileName]
   call lstrlen    ; calcul de la longueur
   sub rax,4
   lea rcx,[r14+WIN32_FIND_DATA.cFileName]
   add rcx,rax
   mov rdx,szExtention  ; l'extention est-elle .asm ?
   call lstrcmp
   cmp rax,0
   jne .suitefichier  ; si non on passe au suivant
   ;il faut concatener le repertoire et le nom du fichier
   mov rcx,szNomComplet
   lea rdx,.repert
   call lstrcpy  ; copie du repertoire
   mov rcx,szNomComplet
   call lstrlen    ; calcul de la longueur
   dec rax        ; pour enlever le * final
   mov byte[szNomComplet+rax],0
   lea rdx,[r14+WIN32_FIND_DATA.cFileName]
   mov rcx,szNomComplet
   call lstrcat  ; concatene le nom du fichier
   mov rcx,szNomComplet  ; lecture du fichier
   call lectFichier
    ; recherche des fonctions appelées dans le fichier lu
   call rechercheFonctFichier
   jmp .suitefichier
.repertoire:   
    lea rcx,[r14+WIN32_FIND_DATA.cFileName]
   ; il faut eliminer les repertoires qui commencent par .
   cmp byte [rcx],'.'
   je  .suitefichier
      ;il faut concatener le repertoire et le nom du fichier
   mov rcx,szNomComplet
   lea rdx,.repert
   call lstrcpy  ; copie du repertoie
   mov rcx,szNomComplet
   call lstrlen    ; calcul de la longueur
   dec rax    ; pour enlever le * final
   mov byte[szNomComplet+rax],0
   mov rcx,szNomComplet
   lea rdx,[r14+WIN32_FIND_DATA.cFileName]
   call lstrcat  ; concatene le nom du fichier
   mov rcx,szNomComplet
   call lstrlen    ; calcul de la longueur
   mov byte[szNomComplet+rax],'/'
   inc rax
   mov byte[szNomComplet+rax],'*'
   inc rax        ; pour ajouter le 0 final
   mov byte[szNomComplet+rax],0
   mov  rcx,szNomComplet  ; analyse du sous répertoire
   call analyseReper
   jmp .suitefichier
.suitefichier:
   mov rcx, .hFile  ; contient la valeur retourné par le Findfirst
   lea rdx, .infFile
   call FindNextFileA
   mov r9,__LINE__
   cmp eax,0
   jne .boucle  ; boucle sur autre fichier
    call GetLastError  ; recherche numero erreur
    cmp eax,ERROR_NO_MORE_FILES
    jne .erreur   ; autres erreurs
   ;fin de la recherche
   mov rcx, .hFile  ; fermeture
   call FindClose
   mov r9,__LINE__
   cmp eax,0
   je .erreur
   jmp .fin
.erreur:
    call afferreur
.fin:      
   leave
   ret
;================================================
;init fichier
;================================================
initFichier:
    mov dword[ofn+OPENFILENAME.lStructSize],ILGOFN    ; longueur de la structure
   mov qword[ofn+OPENFILENAME.lpstrFilter],szFilter 
    mov qword[ofn+OPENFILENAME.lpstrFile],szFile
   mov qword[ofn+OPENFILENAME.lpstrDefEx],szDefExt
   mov qword [ofn+OPENFILENAME.lpstrFileTitle],szFileTitle   
    ret   
;================================================
;recherche fonction dans  fichier
;================================================
rechercheFonctFichier:
   sub rsp,8h
  ;init
  mov rbx,0
.boucle: 
  ;lire un caractere
  cmp byte[szBuffer+rbx],0
  je .fin
  ;si 0 fin
  cmp byte[szBuffer+rbx],10 ;si 10 ou 13 boucle
  je .suiteboucle
  cmp byte[szBuffer+rbx],13
  je .suiteboucle
  cmp byte[szBuffer+rbx],09  ; tabulation
  je .suiteboucle
  cmp byte[szBuffer+rbx],' ' ;si blanc boucle
  je .suiteboucle
  cmp byte[szBuffer+rbx],'c';si caractere est dif de e  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],'a';si caractere est dif de x  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],'l';si caractere est dif de x  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],'l';si caractere est dif de x  boucle
  jne .suiteboucle
  inc rbx
  cmp byte[szBuffer+rbx],' ';si caractere est dif de blanc  boucle
  jne .suiteboucle
.bouclebl: 
  inc rbx
  cmp byte[szBuffer+rbx],' ';si caractere est egal à blanc  boucle
  je .bouclebl 
  ;ici on est au début de la fonction
  lea r11,[szBuffer+rbx]  ; on garde un pointeur vers le debut
.boucle2:
  cmp byte[szBuffer+rbx],0;si caractere est 0 fin
  je .finboucle2A
  cmp byte[szBuffer+rbx],10;si fin de ligne
  je .finboucle2
  cmp byte[szBuffer+rbx],13;si fin de ligne
  je .finboucle2
  cmp byte[szBuffer+rbx],09;tabulation
  je .finboucle2
  cmp byte[szBuffer+rbx],' ';si caractere est dif de blanc  boucle
  je .finboucle2
  inc rbx
  jmp .boucle2
.finboucle2:
  mov byte [szBuffer+rbx],0  ; on met un zero final
  inc rbx ; pour la suite de la recherche
.finboucle2A:  ;fin de fichier  on touche pas a rbx
  ; maintenant il faut chercher la fonction dans la table
   mov rcx,r11
    call rech_dicho
   cmp rax,-1
   jne .trouve
    jmp .suiteboucle  ; pas dans la table donc autre call
.trouve:
    ;il faut mettre a jour la table des noms de programmes
    cmp qword[iTablePgm+8*rax],0    ; la zone est elle cree ?
   jne .suite
   mov r12,[ptTasPgm]
   mov qword [iTablePgm+8*rax],r12; on met le pointeur du tas
   mov rdx,r12
   add rdx,10h    ; car un compteur et un pointeur
   mov [r12+RESULT1.ptnom],rdx  ; et on stocke dans cette zone
   add qword[ptTasPgm],ILGRESULT1  ; et on l'augmente de la longueur de la structure
   jmp .suitestk
.suite:
    mov r12,[iTablePgm+8*rax]
.suitestk:   
    cmp qword [r12+RESULT1.cpt],5
    jge .suiteboucle    ; pas plus de 5 programmes pour une fonction   
   inc qword [r12+RESULT1.cpt]  ; plus un dans le compteur
   mov rdx,szNomComplet
   mov rcx,[r12+RESULT1.ptnom]  ; copie du nom complet du programme
   call lstrcpy
   mov rcx,szNomComplet
   call lstrlen          ; calcul de la longueur
   mov rcx,[r12+RESULT1.ptnom]
   add rax,rcx
   mov byte [rax],';'    ; et on met un ; comme séparateur
   inc rax
   mov byte [rax],0
   mov [r12+RESULT1.ptnom],rax
.suiteboucle:
    inc rbx
   jmp .boucle   
.fin: 
    add rsp,8h
   ret
;=================================================
;  recherche dicho dans la liste
;=================================================
;rcx contient le pointeur vers la chaine a rechercher
;rax contient -1 ou valeur de l'index trouvé
rech_dicho:   
    push r14  ; sauvegarde du registre utilisé dans fct précedente
    sub rsp,20h  ; car il faut tenir compte du push précedent
   mov rdi,rcx
   ;on utilise r13 et r15 comme valeur inter et r14 comme median
   mov r13,0  ; valeur mini
   mov r15,[iNbfoncExt]  ; valeur maxi
   dec r15
.boucle:
    cmp r13,r15
   jg .nontrouve      ; non trouvé
   mov r14,r13        ;calcul de l'indice median (min+max)/2
   add r14,r15
   shr r14,1          ; divise par 2
   mov rcx,rdi
   mov rdx,[iTablePt+8*r14]
   call lstrcmp      ; fonction windows
   cmp eax,0
   jg .haut
   je .trouve
   dec r14
   mov r15,r14
   jmp .boucle
.haut:
    inc r14
    mov r13,r14
    jmp .boucle   
.trouve:   
    mov rax,r14
   jmp .fin
.nontrouve:
    mov rax,-1
.fin:
    add rsp,20h
   pop r14
    ret    
;=================================================
;  creation du buffer d'ecriture
;=================================================
creationbuffer:   
   sub rsp,28h
   mov r12,sBufferEcr  ; on garde l'adresse de debut pour calcul longueur
   mov rdi,sBufferEcr  ; pointeur vers la destination
   mov rbx,0
.boucle:               ; boucle de balayage de la table des fonctions
   mov rcx,rdi
   mov rdx,[iTablePt+rbx*8] ; copie du nom de la fonction
   call lstrcpy            ; dans le buffer d'ecriture
    mov rcx,[iTablePt+rbx*8]
   call lstrlen          ; on cherche sa longueur
   add rdi,rax
   mov byte[rdi],';'      ; pour mettre le séparateur ;
   inc rdi
   mov rdx,[iTablePgm+rbx*8]  ; la fonction  a t'elle été utilisée ?
   cmp rdx,0
   je .suite      ; non donc on termine la ligne
   mov rcx,rdi 
   add rdx,16  ; pour prendre le nom des programmes
   call lstrcpy    ; on copie la liste des programmes qui l'utilisent
    mov rcx,[iTablePgm+rbx*8]
   add rcx,16    ; pour calculer la longueur de la chaine
   call lstrlen   
   add rdi,rax
.suite:   
   mov byte[rdi],10  ; caractères de fin de ligne
   inc rdi
   mov byte[rdi],13
   inc rdi   
   inc rbx
   cmp rbx,[iNbfoncExt]
   jl .boucle          ; boucle si reste encore des donctions
   mov byte[rdi],0  ; 0 final
   inc rdi   
   sub rdi,r12
   mov [iLgBuffer],rdi  ; longueur du buffer d'écriture
.fin:
   add rsp,28h
   ret
;=================================================
;  ecriture fichier resultat
;=================================================
ecritureFic:      
    sub rsp,28h
    call initFichier ; initialisation de la structure
   mov  rax,NULL  ; handle de la fenêtre
   mov [ofn+OPENFILENAME.hwndOwner],rax
   mov dword[ofn+OPENFILENAME.Flags],OFN_HIDEREADONLY + OFN_OVERWRITEPROMPT
   mov rcx,ofn
   call GetSaveFileNameA  ; choix du nom du fichier à sauvegarder
   cmp eax,0
   jnz .suite
   add rsp,28h ; pas de selection donc retour sans rien faire
   ret
.suite:
   add rsp,20h
   sub rsp,8h
   push NULL
    push FILE_ATTRIBUTE_NORMAL
    push CREATE_ALWAYS
   sub rsp,20h
   mov rcx,[ofn+OPENFILENAME.lpstrFile]
   mov rdx,GENERIC_WRITE
   mov r8,0
   mov r9,NULL
   xor rax,rax
    call  CreateFileA  ; création de la structure du fichier à écrire
   add rsp,32
   mov r9,__LINE__
   cmp eax,0
   je .erreur
   mov r14,rax  ;sauvegarde du handle du fichier
    ;ecriture du buffer
    add rsp,20h
    sub rsp,8h   
    push NULL
   sub rsp,20h
   ;xor rcx,rcx
   mov rcx, r14 ; handle du fichier
   mov rdx,sBufferEcr
   mov r8,[iLgBuffer]
   mov r9,iNbByteEcrit
   call WriteFile
   add rsp,10h
   mov r9,__LINE__
   cmp eax,0
   je .erreur
   ;fermeture du fichier
   mov rcx,r14 ; handle du fichier
   call CloseHandle
   mov r9,__LINE__
   cmp eax,0
   je .erreur
   mov   rax, TRUE   ; OK
   jmp .fin
   ; erreur rencontrée
.erreur:   
   call afferreur
   mov rax,FALSE   
.fin:   
   add rsp,28h
   ret      
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