Pages : 1
#1 Le 20/04/2008, à 09:39
- dzouille
erreur en assembleur
Bonjour à tous,
d'abord je précise que je suis nouvelle sur le forum et je suis aussi nouvelle à utiliser ubuntu (moins d'un an)...
J'ai taper un petit code en assembleur.
ce programme permet de lire 10 nombres entiers non signés au clavier et écrire dans un fichier resultat les mêmes nombres multipliés par 2. Le fichier résultat doit être crée par le programme et pas par redirection.
global main
section .data
max db 10
cpt db 0
deux db 2
nom db "resultat.dat"
section .bss
clav resb 1
fd resd 1
section .code
main:
mov eax,5
mov ebx,nom
mov ecx,64
mov edx,111111111b
mov [fd],eax
lecture:
mov eax,3
mov ebx,0
mov ecx,clav
mov edx,1
int 80h
sub byte[clav],'0'
mov eax,[clav]
mul BYTE[deux]
mov [clav],eax
mov eax,4
mov ebx,[fd]
mov ecx,[clav]
mov edx,1
int 80h
mov eax,19 ;appel système lseek
mov ebx,[nom] ;descripteur de fichier
mov ecx,2 ;offset
mov edx,2 ;SEEK_CUR
int 0x80
inc word[cpt]
cmp word[cpt],max
jg lecture
;==== FIN ====
mov ebx,0 ; argument 0
mov eax,1 ; appel système N°1 = exit
int 80h ; appel système
À la compilation tout va bien,
mais à l'édition des liens ça coince
$ ld ex3.o -o ex3 -e main
ex3.o: In function `lecture':
ex3.asm:(.code+0x89): relocation truncated to fit: R_386_16 against `.data'
Merci d'avance pour votre aide
Hors ligne
#2 Le 20/04/2008, à 17:33
- Le Farfadet Spatial
Re : erreur en assembleur
Salut à tous !
Hé bien ! Ça fait à peu près dix ans que je n'ai pas fait d'assembleur pur... Que de souvenirs...
Dzouille, lorsque je compile ton programme, j'ai la même erreur chez moi. Est-ce que par hasard ton processeur ne serait pas un 64 bits, de même que ta version d'Ubuntu ? J'ai l'impression que Nasm a du mal avec ce genre d'architecture. Cela dit, je ne suis pas certain que ce soit le fond du problème, mais comme personne ne semble vouloir se préoccuper de toi et que je suis toujours ému par les femmes en détresse, je transmets le court de mes réflexions.
À bientôt.
Le Farfadet Spatial
Hors ligne
#3 Le 20/04/2008, à 17:47
- dzouille
Re : erreur en assembleur
Bonjour,
J'ai voulu essayer avec un seule nombre. donc on entre un chiffre au clavier, il se multiplie pas 2 et va dans le fichier resultat.dat.
la tout va bien, sauf qu'en ouvrant le fichier resultat.dat j'ai ^@ qui s'affiche, jamais mon chiffre que j'ai entré au clavier... je comprend pas.
Merci à toi Farfadet de te préoccupé de moi... je désespérais d'avoir une réponse
Dernière modification par dzouille (Le 20/04/2008, à 17:48)
Hors ligne
#4 Le 20/04/2008, à 18:55
- Le Farfadet Spatial
Re : erreur en assembleur
Salut à tous !
J'ai voulu essayer avec un seule nombre. donc on entre un chiffre au clavier, il se multiplie pas 2 et va dans le fichier resultat.dat.
la tout va bien, sauf qu'en ouvrant le fichier resultat.dat j'ai ^@ qui s'affiche, jamais mon chiffre que j'ai entré au clavier... je comprend pas.
C'est tout à fait normal, puisque tu inscrits la valeur saisie et non pas son code ascii/utf8. A minima, si la valeur ne fait qu'un seul caractère, il faut lui ajouter la valeur du caractère '0'. S'il y a plus d'un caractère, il faut prendre le reste de la division par dix, ajouter '0' et l'écrire dans le fichier, puis diviser la valeur par dix et recommencer, jusqu'à n'avoir plus que zéro.
À bientôt.
Le Farfadet Spatial
Hors ligne
#5 Le 20/04/2008, à 19:07
- dzouille
Re : erreur en assembleur
Je le fais.
Je commence par lire au clavier, je met le contenu de ce que j'ai lu dans eax, je lui ajoute '0'. je multiplie le contenu de eax par 2, je retransfère la valeur dans ma variable. Et je l'envoie dans mon fichier. (en considérant qu'a chaque je n'entre qu'un chiffre au clavier)
Ça me semble correct comme logique.. enfin sans doute que non, puisque je n'ai que ce caractère qui va dans mon fichier.
Merci
Hors ligne
#6 Le 20/04/2008, à 19:45
- Le Farfadet Spatial
Re : erreur en assembleur
Salut à tous !
Heu... Je n'ai pas vu ça dans ton code source, mais il me semble que tu l'as quelque peu modifié. Donc, plutôt que de demander de l'aide dans le vide, pourquoi ne donnes-tu pas la version actuelle ?
Sinon, je me demande pourquoi tu multiplies par 2, il doit y avoir un truc qui m'échappe...
À bientôt.
Le Farfadet Spatial
Hors ligne
#7 Le 20/04/2008, à 19:54
- dzouille
Re : erreur en assembleur
Je multiplie par deux car: ... et écrire dans un fichier resultat les mêmes nombres multipliés par 2.... Donc dans mon fichier resultat je renvoie le nombre entré au clavier multiplier par 2.
ok, je renvoie mon code
global main
;==============
section .data
;==============
max db 10
cpt db 0
deux db 2
nom db "resultat.dat"
;==============
section .bss
;==============
clav resb 1
fd resd 1
;=============
section .text
;=============
main:mov eax,5
mov ebx,nom
mov ecx,64
OR ecx,1
mov edx, 111111111b
int 80hmov [fd],eax
; lecture au clavier
lecture:
mov eax,3
mov ebx,0
mov ecx,clav
mov edx,1
int 80hmov eax,[clav]
add eax,'0'mul BYTE[deux]
mov [clav],eax;add BYTE[clav],'0'
mov eax,19
mov ebx,[nom] ;descripteur de fichier
mov ecx,2 ;offset
mov edx,1 ;SEEK_CUR
int 0x80mov eax,4
mov ebx,[fd]
mov ecx,[clav]
mov edx,1
int 80h;inc word[cpt]
;cmp word[cpt],max
;jg lecturefin:
mov eax, 1
mov ebx, 0
int 80h
Voici mon nouveau code,il n'y a pas énormément de modification...
Hors ligne
#8 Le 23/04/2008, à 15:30
- Ultandir
Re : erreur en assembleur
Bonjour,
Avec ce nouveau script, toujours la même erreur? ( je ne peut pas compiler actuellement mais c'est pour savoir si l'erreur de compilation est toujours une piste ou si c'en est devnu une autre.. )
Fedora Cambridge i386
Zenwalk 5.2
-------------
Il y a 10 types de personnes : celles qui connaissent le binaire, et celles qui ne le connaissent pas.
Hors ligne
#9 Le 23/04/2008, à 15:40
- Le Farfadet Spatial
Re : erreur en assembleur
Salut à tous !
Avec ce nouveau script, toujours la même erreur?
En assembleur, on ne parle pas trop de script, plutôt de programme et pas vraiment de compilation non plus, plutôt d'assemblage --- oui, je suis tatillon.
Cela dit, non, il me semble que le problème de dzouille, maintenant, c'est que ce qui est écrit dans le fichier ne correspond pas à ce qu'elle tape au clavier. Je dois admettre que je n'ai pas pris le temps de regarder ça chez moi.
À bientôt.
Le Farfadet Spatial
Hors ligne
#10 Le 23/04/2008, à 17:44
- Ultandir
Re : erreur en assembleur
Autant pour moi pour les noms, je n'ai plus l'habitude d'écrire en assembleur.
Sinon, ce qui me gène dans son script, c'est que ces "mov" n'indiquent pas du tout combien elle déplace.
Je m'explique.
On ne sait pas si elle déplace un long, un short, un byte....
Rajouter la lettre correspondante ( movl....) pourrait fixer la chose.
Ca me parait fort que le problème vienne de la mais bon, si le programme prend un byte au lieu d'un long et qu'il tronque le code binaire, ca peut donner de droles de choses
@Dzouille : A tu fait exprès de choisir ces registres précis; (%eax, %ebx, %ecx....) ou les a tu pris par défaut?
Si tu manipule de petites valeurs, ne serait il pas plus sage de prendre des "sous-registres" (%al, %ah si ma mémoire est bonne...)
Sinon ca fait du bien de voir que certaines personnes s'interessent à l'assembleur, je commencait à desesperer et à croire que je suis vraiment cinglé comme le disent les personnes a qui je dit que j'aime l'assembleur
Fedora Cambridge i386
Zenwalk 5.2
-------------
Il y a 10 types de personnes : celles qui connaissent le binaire, et celles qui ne le connaissent pas.
Hors ligne
#11 Le 23/04/2008, à 19:11
- dzouille
Re : erreur en assembleur
Ultandir, je choisi eax, ebx,... car je dois pouvoir allé jusqu'à la valeur 1000000000.
et avec ces registre la j'ai la possibilité d'allé jusqu'à 4000000000 et un peu plus...
Sinon, je vous remercie, j'y ai passer toute la soirée et j'ai changer pas mal de chose, quasiment tout enfait, et j'obtient enfin ce que je voulais au départ. je passe par un tableau qui reçois les 10nb entré au clavier, il les multiplie et les envoie dans un fichier resultat.dat...
ca tourne à merveille, je vous envoie le code si ca vous interesse.
Il ya egalement pas mal de commentaires. Voila, encore merci à vous
global main
;========================================================
section .data
nombre dd 0
nom db "resultat.dat",0
espace db ' '
deux db 2;========================================================
section .bss
hFichier resd 1
clav resb 10
bufferInv resb 10
tabNombres resd 10
;========================================================
section .code
main:
call boucle ; rempli le tableau avec les chiffre multiplier par deux.
call ouverture ; ouvre le fichier resultat.dat
call ecritureFichier ; tranforme chaque nb du tableau en caractere pour les afficher, si == 0(null) ecris un espace pour le ; nombre suivant.
call fermeture ; referme le fichier
call fin ; fin du programme;--- remplir le tableau ---
mov ECX, 0 ;Indice de deplacement dans le tableau et compteur
boucle:
push ECX
call lectureClavierpop ECX
call caracToBin ;conversion vers Binaire
mov EAX, [nombre]
shl EAX,1 ; nombre contient le nombre lu
;mul BYTE[deux] ; multiplie ce nombre par deuxmov [tabNombres + ECX * 4], EAX ; case ECX du tableau reçois le nombre
inc ECX ; incrémente le compteur
cmp ECX, 10 ; si il a lu les 10 nombres
jne boucle ; si non recommence avec le nombre suivant
ret
;--- ouverture du fichier ---
ouverture:mov EAX, 5
mov EBX, nom
mov ECX, 001000000b ; O_CREATE
or ECX, 01b ; O_WRONLY
mov EDX, 110110110b ; droits
int 80h ; création du fichier
mov [hFichier], EAX
ret
;--- Ecriture du Fichier ---
ecritureFichier:mov EBX, 0 ;EBX sert d'indice de deplacement dans le tableau
boucleTab:
mov EAX, [tabNombres + EBX * 4] ; EAX reçois le 1e nombre du tableau
mov [nombre], EAX ; le met dans nombre
call BinToCarac ; le transforme en caractère pour pouvoir l'afficher
mov ECX,clav
.boucleEcrire: ; ecris le nombre
call ecrire
inc ECX
cmp BYTE [ECX], 0
jne .boucleEcrire
mov ECX, espace ; fin d'un nb, met un espace
call ecrire
inc EBX ; pour passer à l'élément suivant du tableau
cmp EBX, 10 ; 10 élément = fin
jne boucleTab
ret
;--- Fermeture du fichier ---
fermeture:mov EAX,6
mov EBX,[hFichier]
int 80h
ret
;--- lecture au clavier ---
lectureClavier:
pusha
mov EAX, 3
mov EBX, 0
mov ECX, clav
mov EDX, 10
int 80h
popa
ret
;--- ecriture ---
ecrire:
push EAX
push EBX
push EDX
mov EAX, 4
mov EBX, [hFichier]
mov EDX, 1
int 80h
pop EDX
pop EBX
pop EAX
ret
;--- le caractère en binaire ---
caracToBin:
;Calcul la longueur du nombre
pusha
mov EAX, 0
.longueur:
cmp BYTE [clav + EAX], 10 ; Line Feed = 10 (enter)
je .finLongueur
inc EAX ; incrémente EAX à chaque caractère(EAX contiendra le nombre de caractères entrés)
jmp .longueur
.finLongueur:
mov EDX, 0
mov DWORD [nombre], 0
mov ECX,EAX
mov EBX, 1
.bouclecaracToBin:
dec ECX
mov EAX, 0
mov AL,[clav + ECX]
sub AL, '0'
mul EBX
add DWORD [nombre], EAX
mov EAX, EBX
mov EBX, 10
mul EBX
mov EBX, EAX
cmp ECX, 0
jne .bouclecaracToBin
popa
ret
;--- le binaire en caractère ---
BinToCarac:
pusha
mov ECX, 0
mov EAX, [nombre]
.boucleBinToStr:
xor EDX, EDX
mov EBX, 10
div EBX
add DL, '0'
mov [bufferInv + ECX], DL
inc ECX
cmp EAX, 0
jne .boucleBinToStr
dec ECX
xor EDX, EDX
.retournement:
mov al, [bufferInv + ECX]
mov [clav+EDX], al
inc EDX
dec ECX
jns .retournement
mov byte [clav+EDX],0
popa
ret
;--- épilogue ---
fin:mov EAX,1
mov EBX,0
int 80h
Hors ligne
#12 Le 24/04/2008, à 07:01
- Ultandir
Re : erreur en assembleur
Merci beaucoup à toi de partager ton travail en assembleur ^^.
Dit moi, comment as tu appris l'assembleur??
Fedora Cambridge i386
Zenwalk 5.2
-------------
Il y a 10 types de personnes : celles qui connaissent le binaire, et celles qui ne le connaissent pas.
Hors ligne
#13 Le 24/04/2008, à 08:03
- dzouille
Re : erreur en assembleur
Je suis étudiante en informatique. J'ai commencer à l'apprendre l'an passée...
Hors ligne
#14 Le 24/04/2008, à 08:23
- Ultandir
Re : erreur en assembleur
Je suis étudiant en informatique aussi!
Tu est étudiante en quel année et ou?
Fedora Cambridge i386
Zenwalk 5.2
-------------
Il y a 10 types de personnes : celles qui connaissent le binaire, et celles qui ne le connaissent pas.
Hors ligne
#15 Le 24/04/2008, à 08:56
- Nasman
Re : erreur en assembleur
Je débute l'assembleur sous Linux mais j'ai une bonne expérience sous Windows. Il y a une chose qui m'horripile c'est l'instruction mul byte[deux] qui peut être avantageusement remplacé par des shl eax,1.
De même pour multiplier par dix on peut utiliser l'instruction
lea edx,[eax+4*eax] qui "multiplie par 5" suivi d'un shl edx,1
Pour diviser par dix on multiplie par 1/10 à une puissance de deux près.
Plus quelques petites optimisations de code:
pour mettre à zéro remplacer mov eax,0 par xor eax,eax
pour tester si zéro remplacer cmp eax,0 par and eax,eax
Par compte je profite de ce post pour apprendre comment gérer le clavier et la création de fichiers sous Linux.
J'attend la sortie de Hardy 64 pour tester l'assembleur en 64 bits.
PC fixe sous Bionic 64 bits et portable avec Focal 64 bits
Hors ligne
#16 Le 24/04/2008, à 09:45
- tafari
Re : erreur en assembleur
mon dieu je pensais pas que des gens pouvais faire de l'assembleur durant leur temps libre... c'était ma hantise en cours d'info...:(
Hors ligne
#17 Le 24/04/2008, à 09:59
- dzouille
Re : erreur en assembleur
Ultandir, je suis étudiante en 1er, j'ai recommencer... j'étudie à bruxelles (la heb - esi)
tafari, si je fais autant d'assembleur c'est parce que je n'aimais pas du tout l'an passée, mais je compte bien reussir cette année, et pas me contenter de reussir tout juste moi aussi c'est le cours que j'aime le moins, mais je dois y passer...
Nasman, oui j'ai changer le mul byte[deux] par un shl eax,1... c'est beaucoup mieux
Hors ligne
#18 Le 24/04/2008, à 10:07
- Ultandir
Re : erreur en assembleur
Assembleur, SHELL, C et C++ sont mes langages de prédilection ^^ ( oui je sais je suis fou )
EDIT : Dzouille peut tu me faire parvenir tes cours? Ca m'interesserait d'en avoir plus ( parce que nous nous avons fait très peu d'assembleur et seulement en première année)
Dernière modification par Ultandir (Le 24/04/2008, à 10:09)
Fedora Cambridge i386
Zenwalk 5.2
-------------
Il y a 10 types de personnes : celles qui connaissent le binaire, et celles qui ne le connaissent pas.
Hors ligne
#19 Le 24/04/2008, à 10:50
- dzouille
Re : erreur en assembleur
Je ferais ça ce soir sans faut, la je suis à l'ecole, et j'ai pas mes cours sous la main.
Hors ligne
#20 Le 24/04/2008, à 10:54
- Ultandir
Re : erreur en assembleur
OK, Merci beaucoup d'avance!!
Tu pourra me les envoyer par mail? ( normalement, tu devrait pouvoir m'envoyer un mail si tu va dans la description de mon profil puis envoyer un mail )
Fedora Cambridge i386
Zenwalk 5.2
-------------
Il y a 10 types de personnes : celles qui connaissent le binaire, et celles qui ne le connaissent pas.
Hors ligne
#21 Le 24/04/2008, à 20:19
- Le Farfadet Spatial
Re : erreur en assembleur
Salut à tous !
Il y a une chose qui m'horripile c'est l'instruction mul byte[deux] qui peut être avantageusement remplacé par des shl eax,1.
De même pour multiplier par dix on peut utiliser l'instruction
lea edx,[eax+4*eax] qui "multiplie par 5" suivi d'un shl edx,1
Pour diviser par dix on multiplie par 1/10 à une puissance de deux près.Plus quelques petites optimisations de code:
pour mettre à zéro remplacer mov eax,0 par xor eax,eax
pour tester si zéro remplacer cmp eax,0 par and eax,eax
Bien sûr, Nasman, tu as parfaitement raison. Cependant, de mon côté, il y a une chose qui me fascine : les conseils d'optimisation qui permettent de grappiller quelques cycles, mais qui oublient ce qui fait réellement gagner des performances au code.
Ce qui fait vraiment gagner en performances et qui sont à peu près accessibles à l'être humain :
-- faire attention à l'alignement dans les caches (ça c'est plutôt fait dans le code de Dzouille) ;
-- éloigner autant que possible les instructions qui dépendent d'autres instructions les unes des autres afin d'utiliser au mieux les capacités de parallélisme du processeur (assez délicat dans l'exemple de Dzouille) ;
-- dérouler les boucles (ce que Dzouille ne l'a pas du tout fait).
Et ça, ça rapporte autrement plus que xor eax,eax à la place de mov ax,0.
Après, il faut aussi savoir qu'un processeur 16 bits manipule mieux les données 16 bits, un processeur 32 bits manipule mieux les données de 32 bits et ainsi de suite (alignement dans le bus et tout ça). Cela ressemble à une lapalissade, mais cela signifie qu'on a souvent intérêt à utiliser les registres équivalents.
Cela dit, Dzouille, autant la première version que tu as postée ne me plaisait pas trop, autant je trouve ta dernière version plutôt bien.
À bientôt.
Le Farfadet Spatial
Edit : j'ai supprimé les preuves comme quoi j'ai appris l'assembleur sur des machines 16 bits...
Dernière modification par Le Farfadet Spatial (Le 24/04/2008, à 20:20)
Hors ligne
Pages : 1