Compilation avec sh3eb-elf
Posté le 04/11/2018 11:28
Je dois rendre un projet pour mon école (une calculatrice qui gère le nombre infini) et comme bonus je me suis dit "bah je fais un add-in sur calto comme ça je n'ai pas grand-chose à faire, je prends tout les fichiers .c + un main.c fait en 2 secondes puis paf j'ai une bonne note" mais le hic c'est que mon fichier utilise
<stdlib.h> && <unistd.h> et
sh3eb-elf refuse de compiler.Je suppose qu'il suffit d'ajouter (ou d'enlever) un flag, histoire de préciser qu'on veux certaines libs...
Bref je préfère ouvrir un topic, on sais jamais ça pourra peut-être aider des personnes
Voila mon Makefile:
#!/usr/bin/make -f
# ---
# PROJECT: Bistro-matic
# Author: Yatis
# ---
# ---
# set compilation tools
# ---
cc = sh3eb-elf
cflags = -m3 -mb -mrenesas -ffreestanding -nostdlib -W -Werror -Wextra -Wall -fno-builtin
libfx = -lgcc -L . -lfx -O2
wrapper = g1a-wrapper
header = -I include/ -I ../include
icon = icon.bmp
supp-bss = -R .comment -R .bss
link_direction = -T addin.ld
# ---
# set all binary name
# ---
name = bistro.g1a
name-bin = bistro.bin
name-elf = bistro.elf
# ---
# set all compil file
# ---
asm = assembler src/asm_custom.s crt0.s
src = ../src/priority/eval_expr.c ../src/priority/memory.c ../src/priority/exe_equation.c \
../src/priority/token.c ../src/priority/set_equation.c ../src/priority/set_equation.c \
../src/error/error.c ../src/infinite/get_infin_nbr.c ../src/infinite/infadd.c \
../src/infinite/infmult.c ../src/infinite/infin_add/calcul.c \
../src/infinite/infin_add/tools.c ../src/infinite/infdiv.c ../src/infinite/infmod.c \
../src/infinite/op_basic.c src/main.c
obj = $(src:.c=.o)
# ---
# build rule
# ---
all: $(name)
bistro-full: $(name) send
$(name): $(obj)
$(cc)-gcc $(link_direction) -x $(asm) -o $(name-elf) $(obj) $(header) $(libfx)
$(cc)-objcopy $(supp-bss) -O binary $(name-elf) $(name-bin)
$(wrapper) $(name-bin) -o $@ -i $(icon)
%.o: %.c
$(cc)-gcc $(cflag) -c -o $@ $<
send: $(name)
p7 send $<.g1a
# ---
# clean rule
# ---
clean:
rm -rf $(name)
fclean: clean
rm -rf $(name-bin)
rm -rf $(name-elf)
rclean:
rm -rf $(name-bin)
rm -rf $(name-elf)
re: clean all
.PHONY: re clean fclean
Je sais qu'il est moche, donc au passage il serait possible de me donner des conseils ?
PS: en relisant mes
cflags je me suis trouvé face a
-nostdlib je suppose que c'est lui la cause de mes soucis (?)
Citer : Posté le 05/11/2018 17:03 | #
Ça, ça m'étonnerait...
int main(void)
{
f();
}
void f(void)
{
puts("Hello, World!");
}
λ gcc a.c -o a
a.c: In function ‘main’:
a.c:5:2: warning: implicit declaration of function ‘f’ [-Wimplicit-function-declaration]
f();
^
a.c: At top level:
a.c:8:6: warning: conflicting types for ‘f’
void f(void)
^
a.c:5:2: note: previous implicit declaration of ‘f’ was here
f();
^
Surtout que la déclaration implicite est avec valeur de retour int (c'est le défaut) donc ici il y a un clash entre les deux déclarations.
Citer : Posté le 05/11/2018 17:29 | #
Ah oui en effet j'ai ça, mais ça reste qu'un warning, donc on peut se passer des prototypes non ?
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 05/11/2018 17:54 | #
Eh bien... non ! Comme tu peux le voir, ça ne marche pas du tout :
int main(void)
{
show(1234.567);
return 0;
}
void show(float f)
{
printf("%f\n", f);
}
λ gcc a.c -o a
a.c: In function ‘main’:
a.c:5:2: warning: implicit declaration of function ‘show’ [-Wimplicit-function-declaration]
show(1234.567);
^~~~
a.c: At top level:
a.c:9:6: warning: conflicting types for ‘show’
void show(float f)
^~~~
a.c:5:2: note: previous implicit declaration of ‘show’ was here
show(1234.567);
^~~~
el@realm in /tmp
λ ./a
-0.000000
Citer : Posté le 05/11/2018 18:02 | #
Pas d'erreur de compilation, ne veux pas dire pas de bugs
Citer : Posté le 05/11/2018 18:07 | #
Bizarre ça, parce que mes fonctions non prototypées dans casiopython marchent parfaitement
Pourquoi ça marche pas d'ailleurs, tu avais dit que la déclaration implicite retourne un int (au lieu d'un void) mais là la valeur de retour n'est pas utilisée ?
(mais je note que ne pas utiliser des prototypes peut faire des erreurs, je savais pas ça)
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 05/11/2018 18:09 | #
Parce que 1.0 est un double par défaut, et que de toute façon les arguments flottants sont tous des double en absence de prototype. J'aurais même pu mettre int f et afficher avec %d, mais je voulais que ça paraisse moins évident.
Donc en fait, main() envoie 8 octets et show() ne lit que les 4 premiers.
Citer : Posté le 06/11/2018 14:53 | #
ZeZombye j'image pas la fiabilité et la maintenabilité de ton code xD
D'ailleurs Lephe, comment je pourrais déassembler facilement avec sh3eb-elf ?
Et merci au passe j'ai réussi à compiler (j'avais effectivement oublié un -nostdlib quelque part^^)
Citer : Posté le 06/11/2018 15:29 | #
Tu peux utiliser sh3eb-elf-objdump, mais il ne supporte pas toutes les instructions (les multiplications ne passent pas), sinon le fxSDK a un désassembleur approprié pour reverse-engineerer l'OS.
Citer : Posté le 10/11/2018 00:58 | #
Mais du coup : pourquoi GCC ne supporte pas l'absence de prototypes ? Dans le tuto d'openclassrooms ils disent que les prototypes sont parce que les compilateurs étaient pas assez puissants, mais par exemple le java utilise pas de prototypes et ça marche sans aucun problème.
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 10/11/2018 09:11 | #
Eh bien... il y une raison fondamentale pour ça.
Comme tu le sais, quand on compile un projet qui fait plusieurs fichiers, tous les fichiers sont compilés indépendamment, et tu peux même n'en compiler qu'une partie ou en supprimer la moitié et compiler l'autre moitié. C'est vraiment indépendant. Ensuite seulement, les fichiers sont linkés.
Lorsque le compilateur produit le code assembleur pour un fichier, s'il y a un appel de fonction, il doit générer des instructions assembleur pour charger les paramètres dans des registres ou sur la pile, et faire l'appel. Pour ça il a besoin de connaître certaines choses sur la fonction, en particulier le type de ses paramètres.
Tu l'as vu plus haut : si je passe un double (8 octets) à la fonction, GCC va par exemple stocker le paramètre sur deux registres de 4 octets. Mais si par malheur la fonction prend un float (4 octets), alors la seule façon correcte de procéder est de convertir le double en float et de le stocker sur un seul registre.
À cause de ce genre de raisons (mais pas que : arguments variadiques), il est impossible pour GCC de deviner comment il doit disposer les arguments dans la mémoire avant de réaliser l'appel s'il ne connaît pas le prototype de la fonction. Et il ne peut pas essayer de lire le code de la fonction plus loin, puisqu'elle est dans un autre fichier. Parfois elle est même dans une bibliothèque... dont on n'a que le binaire, pas les sources. Là, c'est dead impossible. Donc il est essentiel de prototyper.
À partir du moment où tu es obligé d'avoir un prototype pour les fonctions externes, ça ne sert plus à rien d'ajouter une fonctionnalité pour ne pas avoir à ajouter les prototypes pour les fonctions du même fichier. Surtout qu'avoir les prototypes permet de faire plusieurs choses de bon goût :
* Inclure le header qui contient les prototypes dans le fichier qui implémente les fonctions, ce qui permet au compilateur de vérifier que tu as bien écrit deux fois la même chose ;
* Avoir une description de l'API à un endroit et une implémentation ailleurs ;
* Compiler en une seule passe...
Citer : Posté le 10/11/2018 09:13 | #
Regarde la date de création des deux languages, applique la loi de Moore à ton problème, tu devrais trouver une solution tout seul
Et maintenant que le C est un language fortement typé, c'est trop tard pour changer, et puis, c'est aussi un des trucs qui rend les programmes en C plus rapide (en fait à la base, je vois même pas à quelle moment tu t'es dis qu'il y avait possibilité de faire une comparaison entre un language impératif bas-niveau, et un autre orienté objet haut-niveau... )
Citer : Posté le 10/11/2018 15:11 | #
Ben si, c'est chiant les prototypes (à chaque fois qu'on change ou ajoute un argument dans une fonction, on doit modifier aussi son prototype sinon ça bugge)
Du coup si j'ai bien compris, sans prototype GCC est obligé de "deviner" les arguments de la fonction, et du coup ça crashe parfois ?
Ecrivez vos programmes basic sur PC avec BIDE
Citer : Posté le 10/11/2018 15:13 | #
Ben si, c'est chiant les prototypes (à chaque fois qu'on change ou ajoute un argument dans une fonction, on doit modifier aussi son prototype sinon ça bugge)
Sinon ça quoi ? Ça renvoie une erreur de compilation, pas la mort non plus...
Ni GCC ni toi ni personne ne peut deviner les arguments. Si tu essaies, tu te planteras souvent.