En fait, il est demandé de dire ce qu'affiche le programme ci dessous écrit en assembleur x86 ? de plus,que fait ce programme sur une variable "tab" quelconque ?
N.B: j'étudie l'assembleur pour des raisons personnelles et je suis débutant. J'aimerai que vous commenter le code que je vais donner; surtout au niveau du passage des paramètres
Par pile.
Svp illustrer si possible la pile des données ou des paramètres par un schéma
Voici le code:
.Intel_syntaxe noprefix
.data ; segment de données
Tab: .int 12,7,9,17,3,10,-1 ; déclaration d'un tableau d'entier
Mess_res1: .asciz"résultat 1:" ; déclaration de 3 variables type chaine de caractère
Mess_res2: .asciz"résultat 2:"
Mess_res3: .asciz"résultat 3:"
Rest1:.int 0 ; ici on déclaré 3 entiers
Rest1:.int 0
Rest1:.int 0
Descripteur_ont:.asciz "%d"
.global main
.main: ; début du programme principal
Push offset mess_res1 on charge l'adresse du premier message dans la pile
Call print_string on fait appel a cette fonction pour afficher une chaine de caractère mais je veux savoir si c'est mess_res1 qui sera affiché ?
Add esp,4 on ajoute 4 a esp
Push offset res1
Push offset tab
Call sp_res1
Add esp, 8 je ne comprends pas
Push offset res1
Call print_int
Call print_endl
Push offset mess_res2 on charge l'adresse du premier message dans la pile
Call print_string on fait appel a cette fonction pour afficher une chaine de caractère mais je veux savoir si c'est mess_res1 qui sera affiché ?
Add esp,4 on ajoute a a esp
Push offset res2
Push res1
Push offset tab
Call sp_res2
Add esp, 12 je ne comprends pas
Push res2
Call print_int
Call print_endl
Push offset mess_res3 on charge l'adresse du premier message dans la pile
Call print_string on fait appel a cette fonction pour afficher une chaine de caractère mais je veux savoir si c'est mess_res1 qui sera affiché ?
Add esp,4 on ajoute a a esp
Push offset res3
Push res1
Push offset tab
Call sp_res3
Add esp, 12 je ne comprends pas
Push res3
Call print_int ici on affiche quoi ?
Call print_endl
Push 0
Call exit
Procédure sp_res1
Sp_res1:
Push ebp
Mov ebp,esp
Mov eax,[ebp+8 ] je ne comprend pas
Mov ebx,0
Boucle3:
Cmp dword ptr [ eax+ebx*4],-1 je ne comprends pas
Je fin_boucle3
Inc ebx
Jmp boucle3
Fin_boucle3:
Mov eax, [ebp+12 ] je ne comprends pas
Mov [ eax],ebx je ne comprends pas
Pop ebp
Ret
Procédure sp_res2
Sp_res2
Push ebp
Mov ebp,esp
Mov eax,[ebp+8 ] je ne comprends pas
Mov ebx,0
Mov ecx,[ebp+12] je ne comprends pas
Mov edx,0
Boucle6:
Cmp ebx,ecx
Je fin_boucle6
Add edx,[ eax+ebx*4] je ne comprends pas
Inc ebx
Jmp boucle6
Fin_boucle6:
Mov eax, edx
Mov edx,0
Div ecx
Mov ebx, [ebp+16 ] je ne comprends pas
Mov [ebx],eax je ne comprends pas
Pop ebp
Ret
Procédure sp_res3
Sp_res3
Push ebp
Mov ebp,esp
Mov eax,[ebp+8 ]je ne comprends pas
Mov ebx,1
Mov ecx,[ebp+12]je ne comprends pas
Mov edx,[eax]
Boucle4:
Cmp ebx,ecx
Je fin_boucle4
Cmp [eax+ebx*4],edx je ne comprends pas
Jet fin_test2
Mov edx,[eax+ebx*4] je ne comprends pas
Fin_test2:
Inc ebx
Jmp boucle4
Fin_boucle4:
Mov eax, [ebp+16 ] je comprends pas
Mov [ eax],edx
Pop ebp
Ret
Svp illustrer si possible la pile des données ou des paramètres
Bonjour !
Pour "illustrer" la pile tu es assez grand pour le faire tout seul : un peu de patience et de concentration. Il suffit de suivre les "push,pop" et "call" en n'oubliant pas que les "ret" restaurent le pointeur de pile.
Tous tes "je ne comprends pas" semblent être des chargements (ou comparaison) de registre avec un contenu de mémoire donnée de manière indirecte (par un pointeur).
Exemples :
mov eax,[ebp+16] : mettre dans le registre "eax" ce qui est dans la mémoire dont l'adresse est dans la mémoire pointée par le contenu de "ebp+16" (le seizième octet à partir de "ebp")
Cmp [eax+ebx*4],edx : il s'agit d'une comparaison entre le contenu de "edx" et ce qui est dans la mémoire pointée par la valeur de "eax+ebx*4".
Il y a un "Jet fin_test2" qui me semble être une erreur. Ne serait-ce pas "JE" (Jump si égal)
Merci bbomaths pour ce lien très édifiant.
Bonsoir.
Première analyse (sauf erreur de ma part)
.Intel_syntaxe noprefix
; segment de données ----------------------------------------------------------
.data
; déclaration d'un tableau de 7 entiers int32
; - 1 = fin de tableau
Tab : .int 12, 7, 9, 17, 3, 10, -1
; déclaration de 3 variables type chaine de caractère finissant par 0x00 (fin de chaine de caracteres en C)
msg_result_1 : .asciz "résultat 1:"
msg_result_2 : .asciz "résultat 2:"
msg_result_3 : .asciz "résultat 3:"
; déclaration de 3 entiers nuls
result_1 : .int 0 ; nombre d'int32 dans le tableau
result_2 : .int 0
result_3 : .int 0
; descripteur d'affichage d'entier en C
Descripteur_ont : .asciz "%d "
; début du programme principal ------------------------------------------------
.global main
.main:
; impression de msg_result_1 "résultat 1: "
push offset msg_result_1
call print_string
; compense 1 push
add esp, 4
; recherche du nombre d'int32 dans le tableau
push offset result_1
push offset tab
call sp_res1
; compense 2 push
add esp, 8
; impression entier
push offset result_1
call print_int
; impression fin de ligne
call print_endl
; impression de msg_result_2 "résultat 2: "
push offset msg_result_2
call print_string
; compense 1 push
add esp, 4
; appel sp_res2
push offset result_2
push result_1
push offset tab
call sp_res2
; compense 3 push
add esp, 12
; impression entier
push result_2
call print_int
; fin de ligne
call print_endl
; impression de msg_result_3 "résultat 3: "
push offset msg_result_3
call print_string
; compense 1 push
add esp, 4
; appel sp_res3
push offset result_3
push result_1
push offset tab
call sp_res3
; compense 3 push
add esp, 12
; impression entier
push result_3
call print_int
; fin de ligne
call print_endl
; fin du main
push 0
call exit
; Procédure sp_res1 : recherche du nombre d'int32 dans le tableau -------------
;
; arg_0 : adresse result_1
; arg_1 : adresse tab <- esp
sp_res1:
# sauvegarde pointeur stack frame precedente
push ebp
# nouveau pointeur stack frame
mov ebp, esp
; eax : adresse result_1
mov eax, [ebp + 8]
; ebx : nombre d'int32
mov ebx, 0
; balayage du tableau d'int32
boucle3:
; int32 = -1 ?
cmp dword ptr [eax + ebx * 4], -1
; oui : fin de tableau trouve
je fin_boucle3
; non : int32 suivant
inc ebx
jmp boucle3
fin_boucle3:
; result_1 = nombre d'int32 dans le tableau
mov eax, [ebp + 12]
mov [eax], ebx
# restitution pointeur stack frame precedente
pop ebp
ret
Bonjour.
Suite à une relecture matinale, remplacez dans sp_res1 :
; eax : adresse result_1
mov eax, [ebp + 8]
Par :
; eax : adresse tableau
mov eax, [ebp + 8]
Essayez de décortiquer le reste...
Quel outil de compilation utilisez-vous ?
Bonjour et Grand merci pour tous les éclaircissements que vous m' apportés bbomaths
Je vous reviendrai si je bloque quelque part !!!!
Pour l'outil de compilation ,je n'en connais pas . vous pouvez me proposer les meilleurs qui sont gratuits.
si vous avez un outil de compilation a me proposer, laisser moi le lien pour facilement télécharger .
En ce qui concerne
Bonjour.
Si on regarde l'exécution des lignes :
push int32
call sous_prog
add esp, 4
Avant le push, ESP est à une adresse adr_0.
Pendant l'exécution du push, ESP est décrémenté de 4 puis int32 est stocké à cette adresse adr_1 (= adr_0 - 4).
Pendant l'exécution du call, ESP va varier jusqu'à retrouver la valeur adr_1 après le dernier ret de sous_prog.
Comme il faut retrouver la valeur adr_0 pour ESP, on incrémente ESP de 4 octets.
Il y aurait eu 2 push, on devrait compenser ces 2 push en additionnant 8 à ESP.
Etc.
Bonsoir
Ça devient de plus en plus clair !!!
Je bute a la deuxième procédure.
Procédure sp_res2
Sp_res2:
; ici je comprends
Push ebp
Mov ebp,esp
; eax: adresse du tableau
; cela veux dire que eax pointe vers le premier élément
; du tableau ? Qui est 12 !!!
Mov eax,[ebp+8 ]
; on affecte a ebx la valeur 0
Mov ebx,0
; ecx: adresse de res2
Mov ecx,[ebp+12]
; on affecte au registre edx la valeur 0
Mov edx,0
Boucle6:
; c'est ici que je m'embrouille
; on sait que ebx contient la valeur 0 et ecx contient ;l'adresse de
; res2 or cette adresse pointe vers la valeur 0
; ma question est de savoir,est ce que c'est l'adresse de ; ecx ou la valeur pointé par cette adresse (0) qui des deux
; sera utilisée pour faire la comparaison avec ebx???
;quelle est la valeur d'adresse de ecx ???
Cmp ebx,ecx
Je fin_boucle6
; c'est ebx qui donne les indice du tableau ??? Si oui je ; ; comprends et si non expliquer moi comment parcourir le ; ; ; tableau
Add edx,[ eax+ebx*4]
Inc ebx
Jmp boucle6
Fin_boucle6:
; on sauvegarde le résultat de edx dans eax en écrasant ;l'ancienne valeur de eax
Mov eax, edx
; on ecrase le résultat qui était dans edx en l'affectant 0
Mov edx,0
; c'est edx qui sera divisé par ecx ou l'inverse ??
Div ecx
; ici, on défini l'adresse a laquelle le résultat sera stocké dans ; la pile
Mov ebx, [ebp+16 ]
Mov [ebx],eax
Pop ebp
Ret
Bonjour.
; Procédure sp_res2 : calcul de la moyenne des éléments du tableau ------------
;
; arg_0 : adresse result_2
; arg_1 : nombre d'int32 dans le tableau
; arg_2 : adresse tab <- esp
sp_res2 :
; sauvegarde pointeur stack frame précédente
push ebp
; nouveau pointeur stack frame
mov ebp, esp
; eax : adresse du tableau
mov eax, [ebp + 8]
; ebx : index sur tableau
mov ebx, 0
; ecx : nombre d'int32 dans le tableau
mov ecx, [ebp + 12]
; edx : somme des éléments du tableau
mov edx, 0
boucle6:
; fin de tableau ?
cmp ebx, ecx
; oui : fin de tableau trouvée
je fin_boucle6
; non : ajout de l'élément a la somme
add edx, [eax + ebx * 4]
; élément suivant
inc ebx
jmp boucle6
fin_boucle6:
; calcul moyenne
; DIV r/m32 : Unsigned divide EDX:EAX by r/m32,
; with result stored in EAX ← Quotient, EDX ← Remainder.
; edx:eax ~ numérateur
mov eax, edx
mov edx, 0
; ecx ~ dénominateur
div ecx
; sauvegarde quotient (~ eax) dans result_2
mov ebx, [ebp + 16]
mov [ebx], eax
; restitution pointeur stack frame précédente
pop ebp
ret
Bonjour
Merci beaucoup , j'ai déjà presque une très bonne compréhension de tout l'exercice et de nombreux éléments de cours dans lesquels j'avais des zones d'ombre.
Mais j'ai une dernière préoccupation pour l'exo en question :
1. Que signifie int32 ?? ( entiers relatifs utilisés avec des registres de 32 bits ) ?
2. Quand doit on utiliser " dword ptr " ??
3. Notre tableau a 7 nombres entiers relatifs
Étant donné que la première procédure est chargée de renvoyer le nombre d'int32 contenu dans ce tableau, quand je l'exécute a la main , je trouve qu'elle renverra a la fin 6 (six) comme nombre d'int32 contenu dans ce tableau.
Je me trompe ??
Illustration :
Ebx=0 ; au départ
Cmp1 dword ptr [ eax + 0*4] =12 # -1 ebx=0+1=1
Cmp2 dword ptr [ eax + 1*4] =7 # -1 ebx=2
Cmp3 dword ptr [ eax + 2*4] =9 # -1 ebx=3
Cmp4 dword ptr [ eax + 3*4] =17# -1 ebx=4
Cmp5 dword ptr [ eax + 4*4] =3 # -1 ebx=5
Cmp6 dword ptr [ eax + 5*4] =10 # -1 ebx=6
Cmp7 dword ptr [ eax + 6*4] = -1 = -1 on ressort de
la boucle puisque la condition est vérifiée ebx ne s'est plus incrémenté et garde la valeur 6 !!!!!!!
1 /
int8 = mot de 8 bits signé
int16= mot de 16 bits signé
int32 = mot de 32 bits signé
uint8 = mot de 8 bits non signé
uint16= mot de 16 bits non signé
uint32 = mot de 32 bits non signé
Raccourcis pour différents langages.
2 /
voir
3 /
Comme déjà précisé, la donnée finale vaut -1 (0xFFFF...FFFF) pour indiquer uniquement une fin de tableau. Sinon, il faudrait mémoriser le nombre d'élements.
; déclaration d'un tableau de 7 entiers int32
; - 1 = fin de tableau
Tab : .int 12, 7, 9, 17, 3, 10, -1
Il y a donc que 6 données utiles.
malou edit > lien modifié
Bonjour bbomath, en fait ,je viens de faire une analyse sur sp_res3 . hier je me suis préoccupé a autres.
Une analyse rapide me permet de dire que sp_res3 renvoie
Le " minimum " du tableau d'int32
Attention !!! Je pense qu'il y'a erreur !!!
Voir lignes rouge et vert que j'ai ajouté
Si je me trompe corrigez
Procédure sp_res3
Sp_res3
Push ebp
Mov ebp,esp
Mov eax,[ebp+8 ]
Mov ebx,1
Mov ecx,[ebp+12]
Mov edx,[eax]
Boucle4:
Cmp ebx,ecx
Je fin_boucle4
Cmp [eax+ebx*4]
Jet fin_test2
Mov edx,[eax+ebx*4]
;on doit incrémenté et faire un saut inconditionnel
inc ecx
jmp boucle4
Fin_test2:
Inc ebx
Jmp boucle4
Fin_boucle4:
Mov eax, [ebp+16]
Mov [ eax],edx
Pop ebp
Ret
Bonjour.
Bonne analyse car effectivement sp_res3 permet la recherche de min(tab).
Par contre, votre suggestion de modification n'est pas bonne car
- EBX contient l'index sur le tableau et il est incrémenté de +1 à chaque tour ;
- ECX contient le nombre d'int32 dans le tableau.
Incrémenter ECX fait que le je du bloc d'instructions ne sera jamais réalisé :
cmp ebx, ecx
je fin_boucle4
; Procédure sp_res3 : recherche de min(tab) -----------------------------------
;
; arg_0 : adresse result_3
; arg_1 : nombre d'int32 dans le tableau
; arg_2 : adresse tab <- esp
sp_res3 :
; sauvegarde pointeur stack frame precedente
push ebp
; nouveau pointeur stack frame
mov ebp, esp
; eax : adresse du tableau
mov eax, [ebp + 8]
; ebx : index sur tableau initialisé à 1
mov ebx, 1
; ecx : nombre d'int32 dans le tableau
mov ecx, [ebp + 12]
; edx : min(tab) = 1er element du tableau par defaut
mov edx, [eax]
; balayage du tableau...
boucle4:
; fin de tableau ?
cmp ebx, ecx
je fin_boucle4
; non : element du tableau >= min(tab)
cmp [eax + ebx * 4], edx
jge fin_test2
; non : min(tab) = element du tableau
mov edx,[eax + ebx * 4]
fin_test2:
; élément suivant
inc ebx
jmp boucle4
fin_boucle4:
; sauvegarde min(tab) dans result_3
mov eax, [ebp + 16]
mov [eax], edx
; restitution pointeur stack frame precedente
pop ebp
ret
Bonjour
J'ai une préoccupation entre la deuxième comparaison [eax + ebx * 4], edx et fin_test2
Procédure sp_res4
Sp_res4
Push ebp
Mov ebp,esp
Mov eax,[ebp+8 ]
Mov ebx,1
Mov ecx,[ebp+12]
Mov edx,[eax]
Boucle4:
Cmp ebx,ecx
Je fin_boucle4
Cmp [eax+ebx*4], edx
Jle fin_test2
Mov edx,[eax+ebx*4]
;Tab:.int 12, 7, 9, 17, 3, 10, -1
;Au départ , edx = 12
;[eax +ebx*4]<= max(tab). ???
;Cmp1 12>7 on fait un saut a fin_test2 edx=12
;Cmp2 12>9 on fait un saut a fin_test2 edx=12
;Cmp3 12<17 on affecte a edx le nouveau max (17) edx=17
;edx contiendra a cet instant 17 et rien n'indique au ;programme de recommencer a la boucle4
;Inc ebx; cette instruction ne doit pas t-il exister a cet endroit ???
; jmp boucle4 ; de même que celle ci ???
Fin_test2:
Inc ebx
Jmp boucle4
Fin_boucle4:
Mov eax, [ebp+16]
Mov [ eax],edx
Pop ebp
Ret
Bonjour, j'ai commencé a travailler sur la lecture et l'ecriture dans les fichiers. Je veux savoir si je doit créer un nouveau sujet ou non pour vous exposez les problèmes que je rencontrerai dans cette partie ?
Merci pour votre bonne compréhension
Pour passer de la recherche de min(tab) à la recherche de max(tab), il suffit de remplacer le jge par jle
; Procédure sp_res4 : recherche de max(tab) -----------------------------------
;
; arg_0 : adresse result_4
; arg_1 : nombre d'int32 dans le tableau
; arg_2 : adresse tab <- esp
sp_res4 :
; sauvegarde pointeur stack frame precedente
push ebp
; nouveau pointeur stack frame
mov ebp, esp
; eax : adresse du tableau
mov eax, [ebp + 8]
; ebx : index sur tableau initialisé à 1
mov ebx, 1
; ecx : nombre d'int32 dans le tableau
mov ecx, [ebp + 12]
; edx : min(tab) = 1er element du tableau par defaut
mov edx, [eax]
; balayage du tableau...
boucle8:
; fin de tableau ?
cmp ebx, ecx
je fin_boucle8
; non : element du tableau >= max(tab) ?
cmp [eax + ebx * 4], edx
jle fin_test8
; non : max(tab) = element du tableau
mov edx,[eax + ebx * 4]
fin_test8:
; élément suivant
inc ebx
jmp boucle8
fin_boucle8:
; sauvegarde max(tab) dans result_4
mov eax, [ebp + 16]
mov [eax], edx
; restitution pointeur stack frame precedente
pop ebp
ret
Vous devez être membre accéder à ce service...
Pas encore inscrit ?
1 compte par personne, multi-compte interdit !
Ou identifiez-vous :