Les débuts ne sont jamais facile Toujours un ELF, bien entendu! Installer les logiciels nécessaires Etape 2. Si vous avez du mal à comprendre son fonctionnement, n’hésitez pas à me contacter. Enfin, les lignes 12 à 14 de cet exemple montrent comment sont effectués les appels aux fonctions.
| Nom: | nasm linux |
| Format: | Fichier D’archive |
| Système d’exploitation: | Windows, Mac, Android, iOS |
| Licence: | Usage Personnel Seulement |
| Taille: | 33.10 MBytes |
Avec le fonctionnement par défaut, main n’est qu’une fonction comme les autres. Ensuite on va placer des données dans le bon ordre de préférence! Je fais partie des cinq gus dans un garage qui font des mails à la chaîne. En résumé, write va écrire count octets pointés par buf dans le descripteur fd. J’obtiens ces messages quand je compile le 2eme programme;. La sortie de notre programme, qui était un simple ret ne fait que quitter la fonction main.
Je tiens d’abord à préciser une chose: Il est plutôt destiné à ceux qui le connaissent déjà et qui désirent découvrir comment l’utiliser sous linux. Les outils nécessaires seront, outre votre éditeur de texte favori, l’assembleur Nasm ainsi que ld ou gccqui l’inclut.
Nasm (Linux)
Bien sûr, vous pouvez aussi vous munir d’un debugger et d’un compilateur C pour voir le code qu’il pond. Je vais commencer par donner l’exemple, que je commenterai ensuite. Lorsqu’il s’agit d’un programme aussi petit, ca permet d’avoir directement une vue d’ensemble.

Ce simple exemple nous donne déjà une belle quantité d’informations. Ce sont les segments de notre futur exécutable. Nous utilisons ici les sections. Il est à noter qu’il existe bien d’autres types de segments sectionscomme. Le système leur réservera de la place en mémoire lors de l’exécution du programme, mais elles ne prennent pas le moindre octet dans le binaire lui-même. Le premier permet de spécifier une fonction qui se trouve en fait à l’extérieur de notre source. Le second spécifie quels sont les symboles qui seront utilisables depuis l’extérieur.
Enfin, les lignes 12 à liinux de cet exemple montrent comment sont effectués les appels aux fonctions.
Les arguments sont push és sur la pile ligne 12 avant l’appel ligne 13et c’est l’appelant qui les dépile ligne L’exemple ici ne le montre pas, mais les arguments sont mis sur la pile en commençant par le dernier. C’est à dire que si nous avons une fonction qui prend deux arguments:. Le code de retour est habituellement donné dans EAX.
Si vous faites de l’assembleur avec pour objectif la réalisation d’une intro en 4kb, vous aurez constaté un petit problème: Mais tout n’est pas perdu. Certains vous diront qu’il faut commencer à se prendre la tête avec les en-têtes ELF, utiliser l’option -f bin de nasm pour générer directement tout l’exécutable, etc.
Rassurez-vous, ces mesures ne sont à prendre qu’en dernier recours. Réduire la taille du code est bien évidemment votre travail. C’est à vous de trouver les optimisations nécessaires. De même, évitez autant que possible l’utilisation des fonctions externes. Il reste bien sûr des cas où elles sont inévitables, mais chaque fois que vous pouvez le faire, tentez de les éliminer.
Voyons maintenant quelques méthodes qui nous permettront de réduire la taille de notre lnux. Je ne parlerai ici que des méthodes applicable de manière générale, pas des optimisations propres à ce programme-ci. La première chose à faire est de strip er l’exécutable man strip vous en dira plus long sur cette commande, si vous ne la connaissez pas encore. C’est bien, mais ce n’est pas encore tout à fait ça. Cela nous laisse un peu plus d’un kilo-octet pour le code et les nask.
Comptez l’initialisation graphique, peut-être également une gestion de la carte son, il ne vous reste vraiment plus grand chose.
L’assembleur sous linux
Je sais, le titre a l’air un peu compliqué, mais ne vous inquiétez pas, c’est presque aussi simple. Vous savez peut-être que main n’est le point d’entrée linuxx programme que parce que c’est le comportement par défaut de linnux.
Heureusement, on peut lui demander de fonctionner différemment. Avec le fonctionnement par défaut, main n’est qu’une fonction comme les autres. La sortie de notre programme, qui était un simple ret ne fait que quitter la fonction main. Cela signifie qu’en réalité, il y a une partie du code, dans cet exécutable, qui n’est pas de nous et qui se charge d’appeler notre main!
Il est bien évident que nous devons nous en débarrasser. Opérons quelques modifications à notre code. Comme vous le constatez, pas grande différence. Et voilà, vous venez de faire un appel système. Sous Linux, ces appels se font par l’intermédiaire de l’interruption 0x L’appel numéro 1 est celui qui demande au système la fermeture du programme.
Rien de bien compliqué jusqu’à présent. Cependant, si vous tentez de compiler ceci de la même manière que pour l’exemple du chapitre 2, vous risquez d’avoir une mauvaise surprise au moment de l’édition des linuc. Voici la marche à suivre:. L’argument -nostdlib permet de s’affranchir du code lknux lors de l’édition des liens.
Le -lc est l’habituelle demande de lien avec une bibliothèque externe, nécessaire ici car c’est elle qui contient ,inux.

Avouez que c’est déjà mieux! Il reste maintenant un peu plus de 2. Et pourtant, il est tellement simple de faire mieux Au long de mes pérégrinations sur le net, je suis tombé sur la page des ELFkickers voir la section des liens.
C’est une compilation d’outils très pratiques, qui tournent tous autour du format ELF. L’un d’entre eux, en particulier, a retenu mon attention: Dans la même veine que stripil permet un travail plus en profondeur. Il retire non seulement les symboles inutiles, mais simplifie également liunx en-têtes ELF et retire les sections inutiles.
Et pourtant, ce n’est même pas fini. Une astuce supplémentaire Vous vous en doutez sans doute, un bon moyen pour mettre plus de données dans un fichier de petite taille passe par la compression.
Le problème, c’est qu’un décompresseur, ça prend de la place. Sauf bien sûr s’il n’est pas réellement inclus dans l’exécutable.
Et il existe un compresseur disponible sur linud toute machine Linux: Alors pourquoi ne pas lui demander de faire le travail pour nous? Mais il est toujours plus propre d’avoir un seul fichier exécutable, plutôt qu’un exécutable et un fichier compressé.

Je vous donne lijux astuce telle quelle, sans entrer dans les détails. Si vous avez du mal à comprendre son fonctionnement, n’hésitez pas à me contacter. Certains esprits grincheux contesteront et diront que l’utilisateur n’a pas forcément un accès en écriture dans le répertoire et ils auront raison.
Or, c’est indispensable pour écrire le fichier décompressé. Ca augmente légèrement la taille du script, mais dans une bien faible mesure. N’oubliez cependant pas de modifier également la valeur de skip lors du dd. L’autre nasj est celui impliqué par la commande dd: Soit on s’arrange avec une redirection, soit on se dit que ça n’est pas dérangeant.
Nous en arrivons donc à un exécutable de octets.
Il ,inux évidemment possible de faire beaucoup mieux. Par exemple, remplacer le puts par un appel système, comme proposé au chapitre 3. Comme je suis gentil et serviable, j’ai mis en annexepour ceux qui seraient intéressés, un exemple de Hello World qui utilise les appels systèmes.
Il est aussi possible de jouer avec les en-têtes, et arriver au final à un exécutable de moins de bytes. Mais j’estime que cette dernière solution n’a pas sa place dans ce tutoriel, qui se veut plus généraliste. Peut-être une prochaine fois? Ce point-ci offre moins d’intérêt au point de vue assembleur pur.
Certes, il est indispensable à la réalisation d’une animation graphique, mais il consiste surtout à appeler quelques fonctions externes. Il faudra cependant faire attention: Il est parfois intéressant d’écrire une première fois l’initialisation en C et de demander une sortie assembleur à gcc grâce à l’option -S pour voir de quelle manière il travaille.
Nous aurons également besoin de quelques variables. Elles n’auront pas à avoir de valeur précise lors du lancement du programme, leur place est donc tout indiquée: Nous avons ici deux variables différentes, pour les buffers. Il est en effet plus facile de travailler en 32 bits en interne et de faire une conversion après, si nécessaire. Il n’y aura que très peu de commentaires, dans cette section. Nnasm la place, je donnerai chaque fois le code C correspondant.
Il faut maintenant obtenir le screenla fenêtre root et le contexte graphique gc. En C, trois macros nous permettent de les avoir facilement. Ces valeurs sont en fait des membres de structures. Si vous êtes motivés, allez voir dans les headers de la xlib.
Une fois qu’on a tout ceci, on peut enfin faire quelque chose de visible! Je parle de l’ouverture d’une fenêtre, bien sûr. Une fois de plus, référez-vous à la mage de manuel pour plus de détails sur les paramètres de la fonction. Une fois que nous avons une fenêtre, il oinux encore la « mapper » au display. Cette fonction permet également de faire passer notre fenêtre au premier plan.
Une oinux ceci fait, il ne reste plus grand chose.
