Bonjour, pour commencer je vous prie d'être indulgents car c'est ma première source asm sur le site. J'ai voulu faire un petit programme utilisant les boites de dialogue pour reconnaitre un texte saisi (une adresse memoire entre 00400000 et 00405F00), d'afficher 256 octets à partir de l'adresse et les caractères ascii correspondant.
Source / Exemple :
;programme à compiler avec Nasm et alink
;
;nasmw -fobj memoire.asm compile le programme (donne memoire.obj)
;alink -oPE memoire.obj memoire.res link avec memoire.res (fichier ressource)
extern GetModuleHandleA
import GetModuleHandleA Kernel32.dll
extern ExitProcess
import ExitProcess Kernel32.dll
extern MessageBoxA
import MessageBoxA user32.dll
extern DialogBoxParamA
import DialogBoxParamA user32.dll
extern LoadIconA
import LoadIconA user32.dll
extern SetClassLongA
import SetClassLongA user32.dll
extern GetDlgItem
import GetDlgItem user32.dll
extern GetWindowTextA
import GetWindowTextA user32.dll
extern EndDialog
import EndDialog user32.dll
extern SendMessageA
import SendMessageA user32.dll
extern SetDlgItemTextA
import SetDlgItemTextA user32.dll
segment code public use32 class=CODE
..start:
push dword 0
call [GetModuleHandleA]
push dword 0 ;valeur d'initialisation pour WM_INITDIALOG
push dword AppDlgProc ;adresse de la procédure de traitement
push dword 0 ;hWndParent
push dword 101 ;identifiant DialogBox
push eax ;hInstance, // handle of application instance
call [DialogBoxParamA]
push dword 0
call [ExitProcess]
AppDlgProc:
mov eax,[esp+8] ; EAX = message
mov edx,[esp+12] ; EDX = wParam
mov ecx,[esp+4] ; ECX = hdlg
mov [hdlg],ecx
cmp eax,0x111 ;WM_COMMAND
je short onCOMMAND
cmp eax, 0x110 ;WM_INITDIALOG
je short onINITDIALOG
xor eax,eax
ret 16
onINITDIALOG:
lea eax,[esp-44]
xor edx,edx
mov dword [eax+4],32512 ;IDI_APPLICATION
mov dword [eax+12],-14 ;GCL_HICON
mov [eax+8],ecx
mov [eax],edx
mov [eax+20],ecx
mov dword [eax+24],1000 ;ID_TXT
mov [eax+40],edx
mov esp,eax
mov dword [eax+36],8 ;nb maxi de caractères (sans zéro terminal)
mov dword [eax+32],0xC5 ;EM_SETLIMITTEXT
call [LoadIconA]
mov [esp+8],eax
call [SetClassLongA]
call [GetDlgItem]
mov [esp],eax
mov [htxt],eax
call [SendMessageA]
ret 16
onCOMMAND: ; EDX = wParam
cmp edx,1 ;IDOK
je short onOK
cmp edx,2 ;IDCANCEL
je short onCANCEL
ret 16
onCANCEL:
push dword 0
push ecx
call [EndDialog]
ret 16
onOK:
sub esp, 32 ; szbuff[20]+GetWindowText(12)
mov ecx,[htxt]
lea eax, [esp+12] ; adr szbuff(ma chaine)
mov dword [esp+8],20 ; nb maxi de caractères
mov [esp],ecx ; handle du contrôle
mov [esp+4],eax ; adresse chaine
call [GetWindowTextA] ; copie la chaine dans le buffer, la valeur de retour est le nb de caractères
; esp pointe sur la chaine
;xxxxxx Procédure de traitement xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
; convertit la chaine de caractère en une adresse placée dans depart
push ebx ;sauvegarde les registres utilisés par W32
push edi ; " " " " "
xor edi,edi
mov ecx,4 ;4x2 octets à traduire
boucle mov ah,[esp+2*edi+8] ;esp+8 pointe sur la chaine de caractères
call asciihexa ;convertit un caractère en sa valeur numérique
mov al,ah
shl al,4
mov ah,[esp+2*edi+9]
call asciihexa ;est effectué 2 fois par octet
add al,ah ;digit de poids fort et digit de poids faible
mov [depart+ecx-1],al
inc edi
loop boucle
mov eax,[depart]
mov [memcour],eax
mov edx,Adresse ;adresse de la chaine qui devra être affichée
; convertit l'adresse en une chaine ascii (fait l'opération inverse de précédemment) caractères 0123456789ABCDEF
cchaine mov ebx,memcour ;pointe sur memcour (emplacement de l'adresse de la ligne courante)
xor edi,edi
mov ecx,4 ;met 0 dans edi et 4 dans ecx
boucle1 mov al,[ebx+edi] ;lit les octets, du plus faible au plus élevé
call hexascii ;et le convertit en 2 caractères ascii
mov [edx+2*ecx-2],ax ;met l'octet de poids le plus faible à droite et celui le plus fort à gauche
inc edi ;passe à l'octet suivant
loop boucle1 ;terminé ?
; lit 16 octets à partir de la ligne courante, affiche les valeurs et le caractère ascii correspondant (si imprimable)
mov ebx,[memcour]
xor edi,edi ;met pointeur à zéro
mov ecx,16 ;par tranche de 16 octets
boucle2 mov al,[ebx+edi] ;lit la valeur pointée à adresse+pointeur
; vérifie si imprimable
cmp al,31
jna nimp ;caractère non imprimable
mov [edx+edi+80],al
jmp suite
nimp mov [edx+edi+80],byte 46 ;remplacé par .
suite ;convertit la valeur en chaine ascii
call hexascii ;convertit en caractères ascii
mov [edx+4*edi+12],ax ;affiche deux digits par octet
mov [edx+4*edi+14],word " " ;2 espaces
mov al,[ebx+edi] ;caractère ascii correspondant
inc edi
loop boucle2 ;les 16 octets sont ils terminés ?
mov [edx+8],dword " | " ;séparateur adresse - valeurs
mov [edx+76],dword " | " ;séparateur valeur - ascii
mov [edx+96],dword 0x0A0D2020 ;espace,espace,13,10 fin de la ligne
add [memcour],dword 16 ;16 caractères suivants
add edx,100 ;100 caractères par ligne
lea eax,[Adresse+1600] ;16 lignes x 100 caractères par ligne
cmp eax,edx
jbe affiche ;a-t-on tout affiché ?
jmp cchaine
affiche mov [edx],byte 0 ;fin de la chaine
push dword Adresse ;chaine à afficher
push dword 1001 ;id contrôle
mov eax,[hdlg] ;handle dialogbox
push eax
call [SetDlgItemTextA] ;envoie dans le contrôle
; restaure les registres et retourne à la DialogBox
pop edi
pop ebx
add esp,20
ret 16
asciihexa: ;convertit le caractère mis dans ah en une valeur hexa clc
sub ah,0x30
and ah,ah
jb erreur ;<30h (avant 0)
cmp ah,0x9
jbe fin ;numérique
sub ah,0x7
cmp ah,0xA
jb erreur ;39h<<41h (entre 9 et A)
cmp ah,0xF
jbe fin ;alpha (A-F)
sub ah,0x20
cmp ah,0xA
jb erreur ;<61h (entre G et <a)
cmp ah,0xF
ja erreur ;>f
fin ret ;retourne à la procédure de traitement
erreur push dword 0
push dword error
push dword messerr
push dword 0
call [MessageBoxA]
mov edi,[esp+4] ;restaure les registres et retourne à la DialogBox
mov ebx,[esp+8]
add esp,32
ret 16
hexascii: ;convertit la valeur mise dans al en 2 octets al et ah (al=poids fort, ah=poids faible)
mov ah,al
shr al,4 ;lit les 4 bits de poids fort
cmp al,0x9 ;vérifie si numérique
jna num1 ;si <=9
add al,"A"-"0"-10 ;sinon ajoute 7
num1 and ah,0xf ;lit les 4 bits de poids faible
cmp ah,0x9
jna num2
add ah,"A"-"0"-10
num2 add ax,"00" ;rajoute "0"-0 à chacun des octets
ret
segment data public use32 class=DATA
htxt dd 0
hdlg resd 1
error db "Erreur",0
messerr db "Adresse Hexa de 8 caractères requise",0
Titre db "Examen de la mémoire",0
depart resd 1 ;adresse de base
memcour resd 1 ;adresse de la ligne courante (bloc de 16 caractères)
Adresse resb 1601
Conclusion :
Plusieurs routines pourront être récupérées:
conversion ascii/hexa et vice versa
lecture des données saisies
envoi d'un texte dans une EditBox
nb si vous reconnaissez des morceaux de code, je les ai peut-être récupérés ailleurs (il faut parfois procéder ainsi pour voir comment celà marche). J'ai également effectué des transcriptions MASM/NASM
Le code est commenté pour permettre d'aider (peut-être) de plus Newbie que moi
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.