Nasm+alink pour un compilateur C

Résolu
roygrizzly Messages postés 17 Date d'inscription mardi 25 janvier 2005 Statut Membre Dernière intervention 11 mai 2006 - 10 avril 2006 à 18:51
roygrizzly Messages postés 17 Date d'inscription mardi 25 janvier 2005 Statut Membre Dernière intervention 11 mai 2006 - 11 mai 2006 à 15:13
Salut a tous,

Je suis en train de programmer un compilateur pour un sous language C pour mes cours. Je travaille sous cygwin car on est obligé.
Tout mon programme fonctionne, je suis a la phase génération du code assembleur mais j'ai un problème a la création de l'exécutable.
Mon code asm généré pour int a=5; est :

section .data
a DW 0
section .text
PUSH 5
POP AX
MOV [a],AX

int 0x20

qui est écrit dans le fichier a.asm
je fais "nasmw.exe -f obj a.asm" afin d'avoir le fichier objet, ça marche
puis je fais "ALINK.EXE a.obj " et ça me sort:
ALINK v1.6 (C) Copyright 1998-9 Anthony A.J. Williams.
All Rights Reserved

Loading file a.obj
matched Externs
matched ComDefs
Warning, no entry point specified
Warning - no stack

je ne sais pas pourquoi, je n'ai pas trouvé de réponse sur internet (peut-etre que j'ai mal cherché) ou soit mon code asm est faux (vu que j'y connais rien)

MERCI

14 réponses

roygrizzly Messages postés 17 Date d'inscription mardi 25 janvier 2005 Statut Membre Dernière intervention 11 mai 2006
5 mai 2006 à 16:38
Salut, je t'ai envoyé un message en privé pour que tu m'aides à afficher quelque chose à l'écran.

Pour clore la discution au sujet du compilateur, j'ai un code C:
int fonction(){
return 5;
}
int main(){
return fonction();
}
qui génère:
extern ExitProcess
import ExitProcess Kernel32.dll
extern MessageBoxA
import MessageBoxA user32.dll

segment code public use32 class=CODE
..start:
call main
pop ax
push byte 0
call [ExitProcess]
ret
;--------------------------
printf:
push byte 0
push dword Titre
push dword [esp+4]
push byte 0
call [MessageBoxA]
ret 12
;--------------------------

fonction:
pop edx
;return 5
PUSH 5
push edx
ret

main:
pop ecx
;bloc
;return
;appel fonction
call fonction
pop ax
push ax
push ecx
ret

segment data public use32 class=DATA
Titre db "Affichage des messages :",0

Tampon resd 100

et pour compiler et assembler c'est :
nasm -fobj a.asm -o a.obj
alink -oPE a.obj -o a.EXE

Merci beaucoup pour ton aie, j'ai bien avancé grâce à toi !!
3
cs_Nasman Messages postés 202 Date d'inscription mardi 17 mai 2005 Statut Membre Dernière intervention 29 septembre 2008 3
11 avril 2006 à 09:00
Bonjour roygrizzly,


Pour le mode de compilation que tu as spécifié (-fobj), il te faut définir le point d'entrée de la façon suivante:

..start:


Ceci te supprimera le "Warning, no entry point specified". Sauf erreur de ma part, c'est le seul label autorisé pour ce mode de compilation.

Je pense que le "Warning - no stack" apparait parce que tu n'as pas réservé de place (resd xxx, par exemple) dans tes variables - mais c'est pas grave.

Peux-tu également préciser quel type de fichiers exécutables tu veux obtenir (16 bits, 32 bits, PE, mode réel ou virtuel...). Suivant le cas ton exécutable fonctionnera ou pas. Quelle est l'option de format que tu spécifie avec alink ?


A+
0
roygrizzly Messages postés 17 Date d'inscription mardi 25 janvier 2005 Statut Membre Dernière intervention 11 mai 2006
11 avril 2006 à 18:01
Bonjour,

Merci pour ta réponse rapide.
J'obtiens donc le code

section .data
a DW 0
section .text
..start:
PUSH 5
POP AX
MOV [a],AX

int 0x20

si je suit tes conseils et là, il n'y a plus d'erreurs a part le "Warning - no stack".
L'exécutable est créé mais il ne fonctionne pas, comme tu l'as dit ce dois être un problème de type, mais je ne connais pas du tout les différences entre les différents types d'exécutables que tu m'a listé. 16 et 32 bits fonctionnent sous WinXP normalement? meme si le 32 est plus conseillé?
Tu pourrais m'expliquer ce qu'est PE, mode réel ou virtuel STP.
Pour expliquer simplement je veux un exe qui s'éxecute quand je fais "./a.exe" sous cygwin.

Encore merci
0
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
12 avril 2006 à 23:55
salut,





qu'entends tu par ne fonctionne pas;
tu as un message d'erreur ou la fenetre dos apparait et disparait aussitot.

@++
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_patatalo Messages postés 1466 Date d'inscription vendredi 2 janvier 2004 Statut Modérateur Dernière intervention 14 février 2014 2
13 avril 2006 à 00:27
tu trouvera la différence mode réel / réel virtuel ou v86 dans la doc intel.
intel386. dans ton moteur de recherche.

le format PE ( portable executable ) est un format 32 bits ( mode protégé du processeur cf eax,ecx,... )
le format LE ( linear executable ) est un format qui mélange 32 bits et 16 bits ( .vxd ou os2 )
le format MZ ( dos ), le vieux de la vieille est un format 16bits ( mode réel cf ax,cx,...).

pour avoir des informations sur le format PE, tape "iczelion" dans ton moteur de recherche

essai de taper alink /? tout simplement sur ta console.

pour un fichier source simple en 16bits, fait un .com (plus besoin de linker).
[ORG 0x100]
entry:
jmp thecode
datas:
dw 0
thecode:
mov ..,..
...

nasmw.exe -f bin -o a.com a.asm

@++
0
roygrizzly Messages postés 17 Date d'inscription mardi 25 janvier 2005 Statut Membre Dernière intervention 11 mai 2006
13 avril 2006 à 08:03
salut,
il y a le message suivant quand je fais un obj puis le liker
./a.exe
Impossible d'excuter C:\CYGWIN\HOME\ADMINISTRATEUR\A.EXE

[ORG 0x100]
entry:
jmp thecode
datas:
a dw 0
thecode:
push 5
pop AX
mov [a],AX

nasmw.exe -f bin -o a.com a.asm -> pas d'erreurs
./a.com
Impossible d'excuter C:\CYGWIN\HOME\ADMINISTRATEUR\A.COM

alink /? ne fonctionne pas vu que je suis sous cygwin mais alink -h donne:

ALINK v1.6 (C) Copyright 1998-9 Anthony A.J. Williams.
All Rights Reserved

Usage: ALINK [file [file [...]]] [options]

Each file may be an object file, a library, or a Win32 resource
file. If no extension is specified, .obj is assumed. Modules are
only loaded from library files if they are required to match an
external reference.
Options and files may be listed in any order, all mixed together.

The following options are permitted:

@name Load additional options from response file name
-c Enable Case sensitivity
-c+ Enable Case sensitivity
-c- Disable Case sensitivity
-p Enable segment padding
-p+ Enable segment padding
-p- Disable segment padding
-m Enable map file
-m+ Enable map file
-m- Disable map file
----Press Enter to continue---
-h Display this help list
-H "
-? "
-L ddd Add directory ddd to search list
-o name Choose output file name
-oXXX Choose output format XXX
Available options are:
COM - MSDOS COM file
EXE - MSDOS EXE file
PE - Win32 PE Executable
-entry name Use public symbol name as the entry point
----Press Enter to continue---
Options for PE files:
-base addr Set base address of image
-filealign addr Set section alignment in file
-objectalign addr Set section alignment in memory
-subsys xxx Set subsystem used
Available options are:
console Select character mode
con "
char "
windows Select windowing mode
win "
gui "
native Select native mode
posix Select POSIX mode
-subsysver x.y Select subsystem version x.y
-osver x.y Select OS version x.y
-stub xxx Use xxx as the MSDOS stub
-dll Build DLL instead of EXE
-stacksize xxx Set stack size to xxx
-stackcommitsize xxx Set stack commit size to xxx
-heapsize xxx Set heap size to xxx
-heapcommitsize xxx Set heap commit size to xxx

Merci
0
roygrizzly Messages postés 17 Date d'inscription mardi 25 janvier 2005 Statut Membre Dernière intervention 11 mai 2006
24 avril 2006 à 16:35
salut, j'aimerai vraiment qu'on me donne une solution parceque je suis toujours bloqué et puis je dois rendre mon projet dans 3 semaines !

je rapelle mon problème :
j'ai créé un compilateur qui créé un fichier .asm contenant de l'assembleur et je voudrais faire ./xxx.exe sous CYGWIN pour lancer mon application!!!

Merci!!
0
cs_Nasman Messages postés 202 Date d'inscription mardi 17 mai 2005 Statut Membre Dernière intervention 29 septembre 2008 3
24 avril 2006 à 17:14
Bonjour roygrizzly,

Je ne connais pas CYGWIN mais en effectuant des recherches sur le net j'ai cru comprendre que CYGWIN était un émulateur UNIX.
Peut être que cygwin s'attend à trouver un exécutable pour unix (qui tournera avec l'OS du système en fait) et qu'il te jette peut-être à cause de celà.


Si c'est celà, je pense qu'il te faudrait créer un exécutable UNIX (ou linux) avec les options -felf et utiliser un autre linker que alink qui ne génère que des exécutables pour DOS ou windows.


En espérant que tu trouveras la solution (et que je n'ai pas dit trop de bétises !!!)


A+
0
cs_Nasman Messages postés 202 Date d'inscription mardi 17 mai 2005 Statut Membre Dernière intervention 29 septembre 2008 3
11 mai 2006 à 09:18
Bonjour roygrizzly,

J'ai jeté un coup d'oeil au dernier code mis et je me pose quelques questions:

A priori la partie en assembleur ne doit pas faire grand chose à part manipuler les adresses de retour après les call (ces adresses sont restituées néanmoins).
Les différents sauts seraient les suivants:
Start: saut à main
main: saut à fonction
fonction: place 5 sur la pile
retour à main
retour à start, met 5 dans ax et termine avec ExitProcess (+code 0)
retour au système

La routine printf n'est pas exécutée ici.
A ce propos la MessageBox n'affiche que le Titre (le texte affiché ne contient qu'un zéro terminal). En effet en entrée de printf esp pointe sur l'adresse de retour, le push byte zéro décrémente esp de 4, le push dword Titre décrémente encore esp de 4.
Au début de l'instruction push dword [esp+4], esp pointe sur Titre et esp+4 pointe sur byte 0 (en fait c'est un dword 0 qui est pushé).
L'argument texte (adresse d'une chaine) est remplacé par zéro. Pour afficher un message placé sur la pile il faut un décalage d'au moins 12 (0xC) car
esp pointe sur Titre
esp+4 pointe sur byte 0
esp+8 pointe sur adresse de retour
esp+12 pointe sur le dernier push avant le call (le message peut s'y trouver).

A+
0
roygrizzly Messages postés 17 Date d'inscription mardi 25 janvier 2005 Statut Membre Dernière intervention 11 mai 2006
11 mai 2006 à 13:47
Bonjour,
La partie assembleur est à l'image du programme C, si on ne fais pas d'affichage, les variables sont justes modifiées et c'est tout. De plus le code est généré par mon compilateur, donc il fait des choses pas très utiles comme "pop ax" suivi immédiatement de "push ax". Mais c'est pas un problème du tout.
La routine printf n'est pas utilisé car je ne l'appellai pas dans mon code C. Maintenant cette routine ne sera pas mise si il n'y a pas d'appel.
pour apeller printf dans le main je fais :

push dword 0x00000031
push dword 0x39393939
push dword 0x38383838
call printf

normalement c'est 888899991 qui doit s'afficher comme message non?
j'utilise 3 dword car en C les entiers ne peuvent pas avoir plus des 11 chiffres plus un "-" si négatif
je n'affiche que des entiers car mon compilateur n'accepte que les entiers

a+
0
cs_Nasman Messages postés 202 Date d'inscription mardi 17 mai 2005 Statut Membre Dernière intervention 29 septembre 2008 3
11 mai 2006 à 14:07
Rebonjour,

As tu essayé la routine printf avec les paramètres pour afficher 888899991 comme tu l'indiques. A moins que je me trompe, si printf correspond à ce qui suit
printf:
push byte 0
push dword Titre
push dword [esp+4]
push byte 0
call [MessageBoxA]
ret 12

rien ne devrait apparaitre dans la Messagebox. Je pense qu'il faut remplacer la ligne
push dword [esp+4] par
lea eax,[esp+12] ;calcule eax:=esp+12 (adresse du début de la chaine)
push eax

Tiens moi au courant

A+
0
roygrizzly Messages postés 17 Date d'inscription mardi 25 janvier 2005 Statut Membre Dernière intervention 11 mai 2006
11 mai 2006 à 14:29
Voilà un code qui marche (chez moi en tout cas):



extern ExitProcess

import ExitProcess Kernel32.dll

extern MessageBoxA

import MessageBoxA user32.dll



segment code public use32 class=CODE

..start:

call main

pop ecx

pop eax

push ecx

push eax

call [ExitProcess]

ret



printf:

lea eax,[esp+4] ;eax vaut esp+4

push byte 0

push dword Titre

push dword eax

push byte 0

call [MessageBoxA]

ret 12



main:

push dword 0x00000031

push dword 0x39393939

push dword 0x38383838

call printf

pop ecx

push 0; return 0

push ecx

ret



segment data public use32 class=DATA

Titre db "Affichage des messages :",0



Tampon resd 100
0
cs_Nasman Messages postés 202 Date d'inscription mardi 17 mai 2005 Statut Membre Dernière intervention 29 septembre 2008 3
11 mai 2006 à 14:49
Effectivement en mettant lea eax,[esp+4] au début de printf, esp+4 pointe bien sur ta chaine de données. Si tu le fais après les deux push, il te faudra ajouter 8 d'où le [esp+12]

Nota: le ret12 en fin de la procédure permet de vider la pile des données que tu as mises avant l'appel.

A+

A+
0
roygrizzly Messages postés 17 Date d'inscription mardi 25 janvier 2005 Statut Membre Dernière intervention 11 mai 2006
11 mai 2006 à 15:13
Merci pour tes explications! c'est sympa. J'ai presque fini mon projet, encore quelques petites choses à règler.

a+
0
Rejoignez-nous