Cet article à pour but, non pas de vous formez à l'assembleur(mon autre article devrait y suffire) mais à vous parler des différentes possibilités pour implanter de l'assembleur dans un programme.
La première possibilité est de tout simplement d'utiliser un véritable assembleur et programmer votre programme entièrement en assembleur. Pour cela il vous faut un compilateur, je vous conseille nasm que vous pourrez trouver à : http://www.web-sites.co.uk/nasm/ . Les possibilités de l'assembleur nasm sont très vastes et une des ses particularités est qu'il est possible d'utiliser les fonctions C standard de linux!!
;***********EXEMPLE*************
global main
extern printf
section .data
texte DB "Hello Dear!",0dh,0ah,0
section .text
main:
push dword texte
call printf
pop eax
ret
;*******************************
Pour compiler:
nasm -o temp.o -f elf fichier.asm
;Compile le prog(-f elf veut dire format ELF, le format exec standard de linux)
gcc temp.o -o prog
;Et le link
./prog
;Pour l'exécuter
Étudions maintenant cet exemple:
*global main
main est le point de départ du programme car nous utilisons le linker de gcc et le point de départ doit être appelé main
*extern printf
Nous utiliserons la fonction printf de la librairie c standard
*section .data
La section de donne
*section .text
La section du programme lui-même
*main:
Le point de départ
*push dword texte
Ici nous ne plaçons qu'un seul argument sur la pile mais nous aurions pu en mettre plusieurs, sachez dans ce cas que l'on met d'abord le dernier argument sur la pile pour arriver au premier.
*pop eax
En assembleur nous devons enlever nous même les arguments de la pile. Si nous avions passer 2 arguments nous aurions 2 pop.
*ret
Termine le programme
Pour bien vous faire comprendre l'ordre dans lequel il faut passer les arguments voila l'équivalent d'un printf("Hello Dear %s!\n",bouda);
;************ EXEMPLE **************
global main
extern printf
section .data
texte DB "Hello Dear %s!",0dh,0ah,0
bouda DB "Sherlock"
section .text
main:
push dword bouda
push dword texte
call printf
pop eax
pop eax
ret
;*********************************
Vous avez déjà eu un aperçu de la puissance de nasm...
Nasm est très pratique et puissant, c'est vrai, cependant je vais quand même pas écrire tout mon programme en assembleur ??? Non évidemment, et la gcc, superbe compilateur, vous propose une solution très intéressante...l'assembleur inline... Pour l'utiliser on utilise une......fonction qui est définit comme suit:
asm("
vos commandes assembleurs
encore une là
et pis là
");
L'assembleur inline utilise une syntaxe légèrement différente de nasm:
Quand vous utilisez un registre vous devez impérativement le faire précéder d'un '%'.
ex: mov %eax,123
Si vous désirez utiliser une variable dans votre code assembleur , celle ci devra être globale...
Pour indiquer un "pointeur" et non une valeur vous devez utilisez un '$'.
Pour vous mettre dans le bain:
// **********************************EXEMPLE************************************
#include <stdio.h>
#include <string.h>
char mychar[50];
int fun;
void main()
{
strcpy(mychar,"Hello BipBip:%d!\n");
fun=5;
asm("
push fun
push $mychar
call printf
pop %eax
");
}
// *****************************************************************************
Bon, nous avons vu comment faire de l'assembleur tout seul, de l'asm inline, il manque plus qu'à mixer les deux c'est à dire diviser le programme en deux parties, d'un coté 100% assembleur et de l'autre 100% C/C++ .
Pour cela nous créons deux parties différentes, l'un en C/C++ devra contenir:
extern nom_de_la_fonction(paramètres);
De l'autre nous aurons l'assembleur pur... Les paramètres sont passé comme à une fonction C normale c'est à dire à l'aide de push:
push dernier_parametre
push premier_param
call fonction
Et la commencent les problèmes......vous devez laisser la pile dans un état intact et tout a la fois sauvegarder les valeurs des registres pour ne pas perturber le fonctionnement du programme....a l'exception de eax qui n'a pas besoin d'être sauvegarde car il contient la valeur de retour de la fonction...
Pour accéder au paramètres nous utiliserons
mov eax,[esp+4]
mov ebx,[esp+8]
et ainsi de suite, eax recevant le premier argument....
notre programme s'écrira donc comme suit:
// *****************************Prog.c*********************************
#include <stdio.h>
extern incit(unsigned int number,unsigned int number2);
void main()
{
unsigned int number;
unsigned int addnumber;
number = 38122;
addnumber = 25;
printf("The Number is:%d\n", number);
number = incit(number,addnumber);
printf("The Number is:%d\n", number);
}
// *********************************************************************
Et voici la partie assembleur
; *************************** Fonctions.asm ****************************
global incit
section .text
incit:
push ebx
mov eax,[esp+8]
;vous noterez que nous ajoutons encore 4 a la valeur de
;esp du fait que nous avons pusher un argument sur la pile
mov ebx,[esp+12]
add eax,ebx
pop ebx
ret
*********************************************************************
pour Les linker, rien de plus simple:
nasm -o temp.o -f elf Fonctions.asm
gcc Prog.c temp.o -o Prog -O2 -Wall
Et voila un programme qui effectue une addition(je sais, c'est impressionant).
Il y a UNE interruption sous linux, eh oui!
C'est l'interruption 80h qui est en fait l'équivalent de syscall en fonction
C standard....pour l'utiliser, c'est simple:
Vous mettez dans eax le numéro de la fonction que vous voulez utiliser
Et les paramètres dans respectivement(du premier au dernier):
ebx,ecx,edx,esi,edi
Pour savoir quels sont les fonctions disponibles a partir de cette interruption je vous conseille de regarder dans la source de votre kernel ( /linux/include/asm/unistd.h )
Il y en a en tout 190!
Voila un petit exemple qui utilise l'interruption 80h pour créer un répertoire.
;********************************Exemple.asm*******************************
global main
extern printf
section .data
RepName DB "/tmp/BabyBoom",0
Chaine DB "Répertoire /tmp/BabyBoom crée...",0dh,0ah,0
section .text
main:
mov eax,39
mov ebx,dword RepName
mov ecx,0
int 80h
push dword Chaine
call printf
pop eax
ret
;**************************************************************************
Voila, je crois que je vais m'arrêter la pour l'assembleur sous linux :).
DarkBug
Sans peut-être le savoir, dans la vie de tout les jours nous utilisons les systèmes numériques. Le système le plus connu est sans doute celui sous la forme décimale ou, qui serait synonyme de dire Base 10. Ce système coexiste avec le binaire ainsi que l'hexadécimal et l'octal(Complètement inutile). L'hexadécimal étant une abréviation du binaire puisqu'un chiffre comme 99999 serais trop long a exprimer. Le binaire est belle et bien pour le langage machine, etc. L'hexadécimal est souvent utiliser pour l'adressage en mémoire et en assembleur. Je n'aie jamais rencontrer quelque chose qui touchait a l'octal c'est pourquoi je ne vais pas en parler. Peut-être vous n'avez jamais entendu parler de ce jargon mais n'aillez pas peur ceci est relativement facile et si vous ne comprenez réellement pas le concept je crois que vous devriez me contacter tout simplement ou lire d'autre article sinon de lâcher et d'aller vers d'autres horizons que l'informatique. Sans plus tarder voici les systèmes numériques...
Sans peut-être le savoir, dans la vie de tout les jours nous utilisons les systèmes numériques. Le système le plus connu est sans doute celui sous la forme décimal ou, qui serait synonyme de dire Base 10. Ce système coexiste avec le binaire ainsi que l'hexadécimal et l'octal(Complètement inutile). L'hexadécimal étant une abréviation du binaire puisqu'un chiffre comme 99999 serais trop long a exprimer. Le binaire est belle et bien pour le langage machine, etc. L'hexadécimal est souvent utiliser pour l'adressage en momerie et en assembleur. Je n'est jamais rencontrer quelque chose qui touchait a l'octal c'est pourquoi je ne vais pas en parler. Peut-être vous n'avez jamais entendu parler de ce jargon mais n'aillez pas peur ceci est relativement facile et si vous ne comprenez réellement pas le concept je crois que vous devriez me contacter tout simplement ou lire d'autre article sinon de lâcher et d'aller vers d'autres horizons que l'informatique. Sans plus tarder voici les systèmes numériques...
Prenons comme exemple le chiffre 1287,nous tous savons que 7 est les unités, 8 les dizaines, 2 les centaines et 1 les milliers, autrement dit ce chiffre pourrais être représenter de la manière suivante:
(1 * 1000) + (2 * 100) + (8 * 10) + (7 * 1)
Rendu a ce point nous pouvons observer que ce système est de base 10(Donc décimal). Le principe est qu'en partant de la gauche le chiffre vaut 1,ensuite on le multiplie par sa base, donc le rang 2 vaudrais 10 ainsi de suite. Voici un petit tableau illustrant cette relation avec tout le bases :
Base / Rangs |
0 |
1 |
2 |
3 |
Décimal |
1 |
10 |
100 |
1000 |
Hexadécimal |
1 |
16 |
256 |
4096 |
Binaire |
1 |
2 |
4 |
16 |
Octal |
1 |
8 |
64 |
512 |
Cette table vous sera utile lors de la conversion XXX --> Décimal C'est vraiment simple vous avez juste a développer votre nombre, comme fait précédemment. Avant tout je vais donner les unités pour l'hexadécimal:
DEC |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
HEX |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
*** XXX ---> Décimal ***
Bon maintenant nous sommes prêt. Pour faire les conversions XXX --> Décimal vous devez développer votre nombre. Prenons A4CFh,le h confirme que c'est la forme hexadécimal qui est utilise.(b pour binaire) Si on développe ceci donne:
(10 * 4096) + (4 * 256) + (12 * 16) + (15 * 1)
Ce qui nous donne un résultat en Décimal de 42 191. Donc pour rendre n'importe quel systèmes numériques en Décimal on dois développer avec sa base(Soit 8,2 ou 16)
*** Décimal ---> XXX ****
Ensuite ceci est tout aussi simple. Vous prenez le nombre décimal et vous le diviser par la base du système donc vous voulez obtenir de la conversion.
Exemple: Je veut transformer 1000(Décimal) en Binaire
1000 / 2 Reste 0, Quotient 500
500 / 2 Reste 0, Quotient 250
250 / 2 Reste 0, Quotient 125
125 / 2 Reste 1, Quotient 62
62 / 2 Reste 0, Quotient 31
31 / 2 Reste 1, Quotient 15
15 / 2 Reste 1, Quotient 7
7 / 2 Reste 1, Quotient 3
3 / 2 Reste 1, Quotient 1
1 / 2 Reste 1, Quotient 0
Le résultat est: 1111101000
A refaire par 8 pour un résultat en octal, pat 16 pour un résultat en Hexadécimal
Pour le reste je vous conseille de développer en décimal et de le convertir selon le système que vous avez besoin. Voici une table qui vous simplifiera la vie:
Hexadécimal <-> Binaire
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111
Bon voici la fin de la partie sur les systèmes numériques je crois que c'est complet et que j'ai fait le tour d'environ tout ses subtilités. Je vous conseille fortement de vous procurer une calculatrice si vous prévoyez en faire une grande usage. Si des erreurs techniques se sont glisser dans cette article j'aimerais que vous me contacter pour m'en faire part.
Contrairement aux systèmes numériques je ne crois pas que l'algèbre Booléen soi utiliser fréquemment (Quotidiennement). C'est opération sont orienter pour opérer sur des champs de bits. Sans plus tarder je vais vous présenter les quatre arguments les plus utiliser de l'algèbre booléen.
Cet opérateur est utiliser pour combiner deux champs de bits. Sans plus tarder je vous montre un exemple:
OR 01100111b,00110011b
Les b indiquent que c'est un nombre binaire. Le résultat sera: 01110111b. Pourquoi? Bien c'est très simple chaque fois que l'on r encontre deux 1 bien c'est 1 si on rencontre 0 et 1 c'est 1 si on rencontre 0 et 0 c'est 0. Ce qui ce résume part cette table:
OR | 1 | 0
---+----+-----------
1 | 1 | 1
0 | 1 | 0
Cet opérateur est utiliser pour renverser tous les bits dans un champ. N'ayant plus rien a dire sur cet opérateur je vous refile l'exemple a sa table.
NOT 11110000b
Le résultat sera sans doute: 00001111b. Pourquoi? Et bien je crois que vous avez déjà saisie, mais je l'explique quand même. Si l'opérateur rencontre un 1 il renverse pour un 0 sinon le contraire. Voici la table.
NOT | 1 | 0
-----+-----------+--------
| 0 | 1
AND est utiliser pour combiner (??) 2 champs de bits mais différemment. Voici l'exemple:
AND 11110001b,11110000b
Le résultat sera donc: 11110000b. Pourquoi? Et bien comme OR on combine les 2 champs mais cette fois-ci nous devons avoir deux 1 pour obtenir 1 sinon le résultat est zéro. Voici la table.
AND | 1 | 0
------+----------+---------
1 | 1 | 0
0 | 0 | 0
Xor est peut-être l'opérateur le plus complexe de cet gamme , mais reste simple pareille. Voici un exemple:
Xor 11110000b,10101010b
Le résultat sera sans doute:01011010b. Pourquoi? Parce que chaque bits positif dans le deuxième paramètre inverse l'équivalent dans le 1er. Voici la table.
XOR | 1 | 0
-----+-----------+----------
1 | 0 | 1
0 | 1 | 0
Bon voici la fin de la section de l'algèbre booléenne et de mon article, si par malheur des erreurs techniques ce serait glisser parmi la théorie j'aimerais me faire aviser merci...
Nitrogen
***CONTACT***
Email: the_mac_@geocities.com
Icq: 31925098
Irc: Undernet: #Securiweb