Vous êtes sur la page 1sur 26

Introduction l'Assembleur GNU

Sous un systme GNU/Linux sur Intel 80386 Par Issam Abdallah


Date de publication : 18 fvrier 2013 Dernire mise jour : 15 octobre 2013

Ce tutoriel va vous donner la description minimale pour coder en assembleur GNU sous un systme GNU/Linux en utilisant le jeu d'instructions Intel 80386.

Introduction l'Assembleur GNU par Issam Abdallah

I - Introduction..............................................................................................................................................................3 II - Dfinitions prliminaires......................................................................................................................................... 3 II-A - Les systmes de numration........................................................................................................................3 II-B - Le code ASCII...............................................................................................................................................5 III - L'assemblage et l'dition de liens sous Linux...................................................................................................... 6 IV - Syntaxe de l'assembleur...................................................................................................................................... 8 IV-A - Les sections.................................................................................................................................................8 IV-B - Les commentaires....................................................................................................................................... 8 IV-C - Les dclarations.......................................................................................................................................... 8 IV-D - Les symboles...............................................................................................................................................8 Le symbole . ................................................................................................................................................9 IV-E - Les Constantes............................................................................................................................................9 Les nombres entiers......................................................................................................................................... 9 Les caractres.................................................................................................................................................10 Les chanes de caractres............................................................................................................................. 10 IV-F - Les expressions......................................................................................................................................... 10 Prfixes............................................................................................................................................................10 Infixes.............................................................................................................................................................. 10 IV-G - Syntaxe des instructions 80386 (IA-32)....................................................................................................11 Les oprandes.................................................................................................................................................11 L'ordre des oprandes.................................................................................................................................... 11 IV-H - Les directives.............................................................................................................................................11 .ascii string_1, string_2 ...................................................................................................................... 12 .asciz string_1, string_2 ..................................................................................................................... 12 .byte expression_1, expression_2 ..............................................................................................................12 .word expression_1, expression_2 .............................................................................................................12 .quad expression_1, expression_2 ............................................................................................................ 12 .int expression_1, expression_2 .................................................................................................................12 .long expression_1, expression_2 ..............................................................................................................13 .fill repeat, size, value..................................................................................................................................... 13 .org new-lc, fill................................................................................................................................................. 13 .lcomm symbol, length.................................................................................................................................... 13 .global symbol................................................................................................................................................. 13 .set symbol, expression et .equ symbol, expression...................................................................................... 13 V - Exemples de codes assembleur......................................................................................................................... 14 V-A - Exemple 1 : tri bulle d'une liste d'entiers................................................................................................ 14 Dclaration des variables................................................................................................................................14 tape 1 : entrer la liste d'entiers au clavier....................................................................................................14 tape 2 : convertir les caractres du buffer................................................................................................... 15 tape 3 : trier la liste...................................................................................................................................... 16 tape 4 : afficher la liste trie.........................................................................................................................16 V-B - Exemple 2 : utiliser les sous-programmes en assembleur.........................................................................18 Le stack frame................................................................................................................................................ 18 Les tapes suivre........................................................................................................................................ 19 V-C - Exemple 3 : interfacer du code assembleur et du langage C....................................................................20 Le Makefile...................................................................................................................................................... 20 V-D - Exemple 4 : un programme damorage...................................................................................................21 Le BIOS...........................................................................................................................................................21 Le mode rel................................................................................................................................................... 22 Ltat interne du processeur en mode rel................................................................................................... 22 La mmoire..................................................................................................................................................... 22 Les registres....................................................................................................................................................22 Un programme damorage minimal............................................................................................................. 23 Assemblage et dition de liens.......................................................................................................................24 VI - Rfrences..........................................................................................................................................................26 VII - Remerciements.................................................................................................................................................. 26

-2-

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

I - Introduction
L'assembleur est un langage dit bas niveau, c'est--dire qu'il est trs proche du langage machine. Autrement dit, pour programmer en assembleur vous devez : apprendre une architecture : Intel par exemple ; avoir quelques connaissances basiques sur les systmes d'exploitation : Linux par exemple ; matriser un assembleur : l'assembleur GNU par exemple.

Apprendre une architecture, c'est comprendre le fonctionnement d'un processeur : les registres, l'adressage et l'organisation de la mmoire, les interruptions et tout ce que vous avez appris dans le cours d'architecture des ordinateurs. Vous avez, sans doute, une ide claire et suffisante sur l'architecture Intel (IA ou x86) pour aborder ce tutoriel. D'autre part, apprendre un assembleur c'est apprendre une syntaxe pour programmer. C'est l'objectif de ce tutoriel ! Un langage assembleur, ou simplement un assembleur, est une reprsentation symbolique du langage machine (donnes binaires et instructions du processeur). Il existe deux styles d'assembleurs : l'assembleur Intel : l'assembleur principal utilisant ce style est NASM ; l'assembleur AT&T : l'assembleur principal est l'assembleur GNU ou simplement as.

Ce tutoriel va vous donner la description minimale pour coder en assembleur GNU sous un systme GNU/Linux en utilisant le jeu d'instructions Intel 80386.

II - Dfinitions prliminaires II-A - Les systmes de numration


Pour tre traite par un circuit numrique (un processeur, une mmoire RAM), une information doit tre convertie en un format adaptable. Pour cela, elle doit tre reprsente dans un systme de numration caractris par une base b (b > 1 est un entier). Ainsi, on a une infinit de tels systmes. Les plus utiliss sont : le dcimal (b = 10), le binaire (b = 2), l'octal (b = 8), l'hexadcimal (b = 16). Tableau 1 : Les systmes de numration

-3-

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Dcimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Binaire 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

Octal 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17

Hexadcimal 0 1 2 3 4 5 6 7 8 9 A B C D E F

On crit un nombre N = an an1 a1 a0 , a1 a2 am dans un systme de numration de base b selon l'expression suivante : i n n1 1 0 1 2 m N = min (ai.b ) = an.b + an1.b a1.b + a0.b , a1.b + a2.b am.b Avec i le poids (position) du chiffre (digit) ai dans le nombre N. Exemples : 3 2 1 0 b = 10 et N = 2193 : 219310 = 2.10 + 1.10 + 9.10 + 3.10 = 2000 + 100 + 90 + 3 = 2193 ; 3 2 1 0 b = 2 et N = 1011 : 10112 = 1.2 + 0.2 + 1.2 + 1.2 = 8 + 0 + 2 + 1 = 11 ; 3 2 1 0 b = 16 et N = F3C9 : F3C916 = 15.16 +3.16 +12.16 +9.16 = 61440+768+192+9 = 62409 ; 1 0 1 2 b = 2 et N = 10,11 : 10,112 = 1.2 + 0.2 + 1.2 + 1.2 = 2 + 0 + 0,5 + 0,25 = 2,75.

En fait, nous avons converti les quatre nombres N reprsents dans les systmes de numration de bases b au format dcimal. Il est clair que la base b d'un systme de numration est gale au nombre de chiffres (digits) qui peuvent tre utiliss pour reprsenter un nombre. Ainsi, le systme binaire utilise deux digits {0 , 1}, le systme dcimal utilise dix digits {0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9} et ainsi de suite. D'autre part, pour adapter un systme de numration un circuit numrique, il faut associer un niveau de tension (voltage) chaque chiffre. Imaginez que nous dcidions d'utiliser le systme dcimal pour construire un circuit numrique. Il faut donc utiliser dix niveaux de tension. Ce qui nous donne un circuit trs compliqu. Par contre, le systme binaire, ayant la plus faible base (b = 2), est le plus adapt. Il ncessite seulement deux niveaux de tension, par exemple : 0V pour le digit 0 et 5V pour le digit 1. Pour cette raison, les 0 et les 1 sont les deux seuls symboles du langage machine.

-4-

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

II-B - Le code ASCII


Le code ASCII (American Standard Code for Information Interchange) est un code alphanumrique utilis pour l'change des informations entre deux ou plusieurs ordinateurs ou entre un ordinateur et ses priphriques. Le processeur ne comprend pas la reprsentation humaine des caractres. Il utilise le codage ASCII (une squence de 0 et 1), pour identifier les diffrents caractres alphanumriques. Par exemple, lorsque vous appuyez sur la touche A de votre clavier, le processeur reoit son code ASCII. Le codage ASCII standard utilise 7 bits pour reprsenter les caractres de l'alphabet (minuscule et majuscule), les chiffres dcimaux, les caractres de ponctuation et les caractres de contrle : Tableau 2 : La table ASCII standard

-5-

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Dcimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

Caractre NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT ff CR SO SI DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US Space ! $ % & ' ( ) *

Dcimal 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

Caractre + , . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U

Dcimal 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

Caractre V W X Y Z [ \ ] ^ _ a b c d e f g h i j k l m n o p q r s t u v w x y z { | } DEL

III - L'assemblage et l'dition de liens sous Linux


Le code suivant est celui du programme classique permettant d'afficher, sur la console, le message Hello, World ! :
1. 2. .saut : 3. $msg_ : 4. len = . - $msg_ 5. .data .byte '\n .asciz "Hello, World !" .bss

-6-

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

6. 7. 8. 9. _start : 10. 11. /* afficher : 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. exit : 26. 27. 28.

.text .global _start # jmp exit Hello, World ! */ movl $$msg_,%ecx movl $len,%edx movl $1,%ebx movl $4,%eax int $0x80 movl movl movl movl

# appel systme

$.saut,%ecx $1,%edx $1,%ebx $4,%eax ; int $0x80

movl $0,%ebx movl $1,%eax int $0x80

Le code est crit en assembleur GNU. Il utilise le jeu d'instructions du processeur Intel 80386, le premier processeur 32 bits d'Intel. Nous en discuterons dans la section 5. Dans cette section, nous allons juste montrer comment le faire tourner sur la machine. Pour gnrer un fichier excutable partir du code source, nous utiliserons un programme dit assembleur et un programme dit diteur de liens (linker). Sous un systme GNU/Linux, l'assembleur est le programme as et l'diteur de liens est le programme ld (loader). Le schma suivant montre les tapes suivre pour gnrer l'excutable :

L'assembleur as prend comme entre le fichier hello.s, ayant obligatoirement l'extension .s, pour gnrer le fichier objet hello.o. son tour, l'diteur de liens va lier les diffrents morceaux du code objet et affecter chacun son adresse d'excution (run-time address) et produire l'excutable. Celui-ci est au format ELF (Executable Linkable Format). C'est le format des fichiers binaires utiliss par les systmes UNIX. C'est l'alternative l'ancien format a.out (assembler output). Si vous voulez changer le nom de l'excutable (de a.out un nom de votre choix), vous pouvez passer l'option -o hello au programme ld. C'est la mme option utilise par le compilateur gcc. Notre makefile contient les commandes (rules) suivantes :
1. hello : hello.o 2. ld -o hello hello.o 3. hello.o : hello.s 4. as -o hello.o hello.s 5. 6. clean : 7. rm -fv hello.o

-7-

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

L'excutable n'est que l'image mmoire du programme. Il dcrit comment le programme (les sections .text, .data) sera charg dans la mmoire (par le noyau). Voici les commandes d'assemblage, d'dition de liens et d'excution :
1. #make 2. #./hello

IV - Syntaxe de l'assembleur
Reprenons le code source du programme hello.s. Il contient trois sections : .data, .bss et .text. Chaque section contient un ensemble de dclarations et des lignes de commentaires.

IV-A - Les sections


Un programme crit en assembleur GNU peut tre divis en trois sections. Trois directives assembleur sont rserves pour dclarer ces sections : 1 2 3 .text (read only) : la section du code. Elle contient les instructions et les constantes du programme. Un programme assembleur doit contenir au moins la section .text ; .data (read-write) : la section des donnes (data section). Elle dcrit comment allouer l'espace mmoire pour les variables initialisables du programme (variables globales) ; .bss (read-write) : contient les variables non initialises. Dans notre code, cette section est vide. On peut donc l'liminer. L'ordre de sections dans le code source n'est pas significatif. N'importe quelle section peut tre vide !

IV-B - Les commentaires


Il existe deux mthodes pour commenter un code source. Les commentaires crits entre /* et */ peuvent occuper plusieurs lignes. Un commentaire prfix par un # ne peut occuper qu'une seule ligne.

IV-C - Les dclarations


Les dclarations peuvent prendre quatre formats :
1. 2. label_1 : 3. label_2 : 4. 5. .nom directive .nom directive attribut expression instruction op1 , op2 , ...

Une dclaration se termine par le caractre saut de ligne \n ou par le caractre ; . Une dclaration peut commencer par une tiquette (label). Une tiquette peut tre suivie d'un symbole cl qui dtermine le type de la dclaration. Si le symbole cl est prfix par un point, alors la dclaration est une directive assembleur. Les attributs d'une directive peuvent tre un symbole prdfini, une constante ou une expression.

IV-D - Les symboles


Un symbole est une squence de caractres choisis parmi :
-8-

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

1 2 3

Les lettres de l'alphabet : a .. z, A .. Z ; Les chiffres dcimaux : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ; Les caractres : . $. Un symbole ne doit jamais commencer par un chiffre. De plus, la casse est significative. Ainsi, on peut utiliser les symboles msg, Msg et MSg dans le mme programme : ils pointent vers des zones mmoires diffrentes. L'assembleur GNU rserve un ensemble de symboles cls pour les directives. Le symbole saut n'est pas rserv. Donc on peut l'utiliser pour dclarer le symbole .saut.

Une tiquette est un symbole suivi, immdiatement, du caractre : . Elle a deux usages : 1 Si l'tiquette est crite dans la section du code (.text), alors le symbole reprsente une valeur du location counter de la section .text (le Program Counter ou le registre EIP du 80386). Ainsi, si on dcommente la ligne 10 du code du programme Hello, World ! ci-dessus, le message ne sera pas affich. son excution, l'instruction jmp va charger le registre EIP avec l'adresse indique par le symbole exit et continuera l'excution la nouvelle location ; Si l'tiquette est crite dans la section de donnes (.data), alors le symbole reprsente une adresse dans la zone mmoire des donnes. Par exemple, le symbole $msg_ reprsente l'adresse du premier octet (code ASCII) du message Hello, World ! dans la zone mmoire des donnes.

Le symbole .
Le symbole spcial . peut tre utilis comme une rfrence une adresse au moment de l'assemblage. Exemple : Avant d'excuter l'appel systme (ligne 18), il faut charger le registre EDX avec la taille len du message $msg_. L'expression suivante permet de calculer et charger dans len cette taille :
1. len = . - $msg_

Ici, le symbole . fait rfrence l'adresse de l'octet situ juste aprs le message dans la zone mmoire des donnes. Donc, len est gale 13. C'est exactement le nombre d'octets de notre message.

IV-E - Les Constantes Les nombres entiers


Un nombre entier peut tre reprsent dans plusieurs systmes de numration. L'assembleur GNU en identifie quatre : le binaire, le dcimal, l'octal et l'hexadcimal. 1 2 3 4 Un nombre binaire est un 0b ou 0B suivi de zro ou plusieurs chiffres binaires {0, 1}. Exemple : 0b10011. Un nombre octal est un 0 suivi de zro ou plusieurs chiffres octaux {0, 1, 2, 3, 4, 5, 6, 7}. Exemple : 09122. Un nombre dcimal ne doit pas commencer par 0. Il contient zro ou plusieurs chiffres dcimaux {0..9}. Exemple : 97340. Un nombre hexadcimal est un 0x ou 0X suivi de zro ou plusieurs chiffres hexadcimaux {0..9, A, B, C, D, E, F}. Exemple : 0x6FC9D.

-9-

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Les caractres
Comme le montre le tableau 2, chaque caractre est identifi par son code ASCII. Dans un code assembleur, on dfinit un caractre en crivant son code ASCII appropri. En utilisant, la syntaxe de l'assembleur GNU, un caractre peut tre crit comme une apostrophe suivie immdiatement de son symbole. Exemple : 'A est le code ASCII 65 de A ; '9 dsigne le code ASCII 100 de 9.

Les chanes de caractres


Une chane de caractres (string) est une squence de caractres crite entre guillemets. Elle reprsente un tableau contigu d'octets en mmoire. Exemple : Hello, World ! . La manire d'obtenir des caractres spciaux dans une chane de caractres est de les chapper en les faisant prcder d'un antislash \ . Exemple : Dans le programme hello.s, nous avons utilis deux appels systme : le premier pour afficher le message et le second pour excuter un saut de ligne. En fait, nous pouvons crire le saut de ligne dans le message et utiliser un seul appel systme pour afficher la fois le message et effectuer le saut de ligne. C'est en chappant le caractre saut de ligne dans le message. Nous utilisons la mme mnmonique pour symboliser un saut de ligne, en langage C :
1. printf (#Hello, World !\n#) ;

Le caractre n , lorsqu'il est prfix par un antislash, est quivalent au code ASCII (10) du caractre saut de ligne. Les caractres spciaux du langage C sont les mmes en assembleur GNU. Le compilateur gcc du langage C utilise le programme as pour assembler un code source C.

IV-F - Les expressions


Une expression spcifie une adresse ou une valeur numrique. Une expression entire est un ou plusieurs arguments dlimits par des oprateurs. Les arguments sont des symboles, des chiffres ou des sous-expressions. Une sousexpression est une expression crite entre deux parenthses. Les oprateurs peuvent tre des prfixes ou des infixes :

Prfixes
Les oprateurs prfixes prennent un argument absolu. as propose deux oprateurs de prfixe : L'oprateur # complment bit--bit (bitwise not). Exemple : 0b10001110 = 10001110 = 01110001 ; L'oprateur ngation - (complment deux) : N = N + 1. Exemple : N = 142 = 0b10001110, 142 = 01110001 + 1 = 01110010.

Infixes
Un oprateur de type infixe prend deux arguments : , /, %, <, <<, >, >>, +, , == Exemples d'expressions :

- 10 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

1. 2. 3. 4.

len = . - msg SYSSIZE = 0x80000 SYSSEG = 0x1000 ENDSEG = SYSSEG + SYSSIZE

# ENDSEG = 0x81000

IV-G - Syntaxe des instructions 80386 (IA-32) Les oprandes


Les registres : les oprandes de type registre doivent tre prfixs par un %. Exemples : %eax, %ax, %al, %ah, %ebx, %ecx, %edx, %esp, %ebp, %esi, %edi Les oprandes immdiats : les oprandes de ce type doivent tre prfixs par un $. Exemples : $4, $0x79ff03C3, $0b10110, $07621, $msg Les oprandes mmoire : lorsqu'un oprande rside dans le segment de donnes du programme, le processeur doit calculer son adresse effective (EA : Effective Address) en se basant sur l'expression suivante : EA = base + scale * index + disp. L'assembleur GNU utilise la syntaxe AT &T qui traduit l'expression prcdente en celle-ci : EA = disp (base, index, scale) avec : disp : un dplacement facultatif. disp peut tre un symbole ou un entier sign ; scale : un scalaire qui multiplie index. Il peut avoir la valeur 1, 2, 4 ou 6. Si le scale n'est pas spcifi, il est substitu par 1 ; base : un registre 32 bits optionnel. Souvent, on utilise EBX et EBP (si l'oprande est dans la pile) comme base ; index : un registre 32 bits optionnel. Souvent, on utilise ESI et EDI comme index.

La taille des oprandes peut tre code dans le dernier caractre de l'instruction : b indique une taille de 8 bits, w indique une taille de 16 bits et l indique une taille de 32 bits. Exemples :
1. movb $0x4f,%al 2. movw $0x4ffc,%ax 3. movl $0x9cff83ec,%eax # 8-bit # 16-bit # 32-bit

L'ordre des oprandes


L'assembleur GNU utilise la syntaxe AT &T. Ainsi, une instruction mov doit tre crite comme suit :
1. mov source,destination

Cet ordre doit tre respect avec le reste des instructions : sub, add

IV-H - Les directives


Les directives sont des pseudo-oprations. Elles sont utilises pour simplifier, pour le programmeur, quelques oprations complexes telles que l'allocation de la mmoire. Comme on l'a dit dans la section prcdente, le nom d'une directive est un symbole cl prfix par un point. Il existe plus de 70 directives dfinies par l'assembleur GNU. Les plus utilises sont :

- 11 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

.ascii string_1, string_2


Dfinit zro ou plusieurs chanes de caractres spares par des virgules.
1. msg1 : 2. bootMsg : .ascii "Hello, World !\ n" .ascii "Loading system ..."

.asciz string_1, string_2


Dfinit zro ou plusieurs chanes de caractres spares par des virgules et dont chacune se termine par le caractre '\0. Ainsi, ces deux dclarations sont quivalentes :
1. msg1 : 2. msg2 : .ascii "Hello, World !\0" .asciz "Hello, World !"

.byte expression_1, expression_2


Dfinit et initialise un tableau d'octets.
1. tab_byte : .byte 23,'%,0xff,9,'\b

Le premier lment est le nombre 23 et il est situ l'adresse tab_byte, suivi par le code ASCII du caractre %

.word expression_1, expression_2


Dfinit et initialise un tableau de mots binaires (16 bits ou word).
1. descrp : 2. 3. 4. .word .word .word .word 0x07ff 0x0000 0x9200 0x00C0

Avec les processeurs de la famille x86, l'adresse d'un mot, double mot ou d'un quad-mot (64 bits) est l'adresse de son LSB (Least Significant Byte). Ainsi, le quad-mot 0x00C09200000007ff se trouve l'adresse indique par descrp. C'est l'adresse de l'octet 0x07ff.

.quad expression_1, expression_2


Dfinit et initialise un tableau de quad-mots.
1. _gdt : 2. 3. 4. .quad .quad .quad .quad 0x0000000000000000 0x00c09A00000007ff 0x00C09200000007ff 0x0000000000000000

Un .quad est quivalent quatre .word successifs.

.int expression_1, expression_2


Dfinit et initialise un tableau d'entiers (quatre octets).

- 12 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

1. tab_int :

.int 3*6,16,190,-122

.long expression_1, expression_2


Dfinit et initialise un tableau d'entiers (quatre octets).
1. matrix3_3 : 2. 3. .long 22,36,9 .long 10,91,0 .long 20,15,1

.fill repeat, size, value


Rserve repeat adresses contigus dans la mmoire et les charge avec les valeurs value de taille size.
1. idt : .fill 256,8,0

Dfinit un tableau contenant 256 quad-mots l'adresse idt. Chaque lment du tableau contient zro comme valeur.

.org new-lc, fill


Avance le location counter de la section courante l'adresse new-lc.
1. 2. 3. _start : 4. 5. .text .global .org 510,0 .word 0xAA55 _start

Avance le compteur de programme (registre EIP) de la section text (code segment) l'adresse 510 puis crit le mot 0xAA55 (la signature d'un secteur d'amorage). Les octets 0..509 sont chargs avec des zros.

.lcomm symbol, length


Dclare un symbole local et lui attribue length octets sans les initialiser.
1. 2. .bss .lcomm buffer,1024

La directive doit tre crite dans la section .bss.

.global symbol
Dclare un symbole global et visible pour l'diteur de liens ld.
1. .global _start,main

Par dfaut, l'diteur de liens ld reconnat le symbole global _start comme point d'entre. Donc ce symbole doit tre dclar dans la section de code.

.set symbol, expression et .equ symbol, expression


Ceux deux directives sont similaires l'expression : symbol = expression.

- 13 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

1. 2.

.set SYSSIZE,0x80000 .equ SYSSEG,0x1000

V - Exemples de codes assembleur V-A - Exemple 1 : tri bulle d'une liste d'entiers
Le programme utilise la mthode de tri bulle pour trier une liste d'entiers positifs entrs au clavier. La liste trie sera ensuite affiche sur la console.

Dclaration des variables


1. 2. 3. 4. 5. 6. 7. 8. 9. saut : space : msg1 : msg2 : .data .byte '\n .byte 0x20 .ascii " << " .ascii " >> " .bss .lcomm buffer,1024 .lcomm list,100 .lcomm stack,1024

buffer : une mmoire tampon pour stocker temporairement les caractres entrs au clavier ; list : c'est un tableau d'entiers qui peut stocker une liste de 25 nombres entiers (quatre octets) ; stack : pour rserver 1024 octets dans la pile (stack) du programme.

tape 1 : entrer la liste d'entiers au clavier


1. msg_1 : 2. movl $msg1,%ecx 3. movl $4,%edx 4. movl $1,%ebx 5. movl $4,%eax 6. int $0x80 7. 8. kybd : 9. movl $buffer,%ecx 10. movl $1024,%edx 11. movl $0,%ebx 12. movl $3,%eax 13. int $0x80 14. 15. # Compter les octets de buffer 16. 17. movl $0,%esi 18. count : 19. movl buffer(%esi),%ebx 20. incl %esi 21. 22. cmp %bl,line 23. jne count ## ## ## ## ## ECX = l'adresse du message EDX = la taille du message l'cran (stdout) appel systme 4 : write Exception : ID = 0x80

## ECX = l'adresse du buffer ## EDX = la taille du buffer ## clavier (stdin) ## appel systeme 3 : read

## EA = Scale * Index + Displacement

Les registres %eax, %ebx, %ecx, %edx doivent tre initialiss correctement avant l'excution de l'instruction int $0x80. L'instruction int n gnre une exception immdiatement aprs son excution. Une exception est une interruption logicielle (ou encore une interruption programme). L'ID (Interrupt Identifier) de l'exception est cod dans l'instruction (n). Le noyau Linux utilise le nombre 128 (0x80) pour identifier les interruptions programmes des autres interruptions (NMI, Divide Error, Trap). Ainsi, l'instruction int $0x80 (ou int $128) permet notre programme (application) d'accder au matriel (clavier, cran) en excutant

- 14 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

un appel systme. Le fichier /usr/include/asm-x86/unistd 32.h liste tous les appels systme Linux (pour une machine occupe par un processeur de la famille x86). On va utiliser les appels systme 1, 3 et 4. Le registre %eax doit explicitement contenir le numro de l'appel systme. galement, le registre %ebx doit contenir le descripteur (file descriptor) du priphrique. Les instructions 8..13 vont charger le buffer avec la liste des caractres (les entiers), en excutant l'appel systme 3 (read). Les entiers entrs au clavier doivent tre spars par un espace (seulement un !). En excutant les instructions 17..23, le processeur va calculer le nombre de caractres entrs et le charger dans le registre %esi. Pour illustrer, supposons qu'on a entr la liste : 19 208 9756 101 229. Le buffer contient 18 caractres :

Le caractre saut de ligne doit tre entr la fin pour valider la saisie.

tape 2 : convertir les caractres du buffer


On a dit, au dbut de ce tutoriel, que l'ordinateur utilise le codage ASCII pour changer de l'information avec les priphriques d'entre/sortie. Ainsi, et comme le montre le schma ci-dessus, la liste des entiers est reue par l'ordinateur comme un flux (stream) de codes ASCII. Chaque code reprsente un caractre. Donc, pour qu'on puisse effectuer des traitements (arithmtiques, comparaisons) sur des entiers, nous devons d'abord convertir le buffer en une liste d'entiers. C'est l'objectif des lignes de code suivantes :
1. 2. 3. 4. new_elem : 5. 6. 7. 8. 9. 10. 11. 12. new_char : 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. decl %esi movl $0,%edi ## index dans le buffer ## index dans la liste

movl $10,%esp movl $0,%ebp subl %eax,%eax subl %ecx,%ecx

## multiplier par 10 ## compter le poids de chaque chiffre ## nettoyer EAX ## nettoyer ECX

addl %eax,%ecx subl %eax,%eax decl %esi cmpl $0,%esi jl out movb buffer(%esi),%al cmp $32,%al je if_space subl $48,%eax

## ajouter le nouveau chiffre dans ECX

## si ESI = 0, on termine ## AL <- un nouveau chiffre ## si buffer (%esi) = space ## nombre = ascii - 48

- 15 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

27. 28. 29. 30. 31. 32. 33. 34. mult_10 : 35. 36. 37. 38. 39. 40. 41. 42. if_space : 43. 44. 45. 46. 47. 48. 49. out : 50. 51.

incl %ebp cmpl $1,%ebp je new_char movl %ebp,%ebx

## incrmenter la position

## multiplier EAX par 10 n (poids) fois

mul %esp decl %ebx cmpl $1,%ebx jg mult_10 je new_char

movl %ecx,list(,%edi,4) incl %edi jmp new_elem

## sauvegarder le contenu de ECX

movl %ecx,list(,%edi,4)

## sauvegarder le dernier nombre

Cette portion de code va demander au processeur de parcourir le buffer en partant de l'adresse buffer(18). buffer(%esi) est l'EA d'un caractre dans le buffer : EA = disp + base = buffer + %esi = buffer(base, 0, 1) = buffer(%esi) On dcrmente ESI de 1 (ligne 1). Puis, tant que ESI > 0, le processeur procde comme suit : charger l'octet l'adresse buffer(%esi) dans le registre %al et le comparer 32 (le code ASCII du caractre SPACE) ; si le contenu de %al est diffrent de 32, on soustrait 48 de %al (voir tableau 2). Ensuite, on multiplie (lignes 34..40) le rsultat (%al - 48 ) n fois par 10 (n est le poids du chiffre). Le rsultat de la multiplication sera charg dans %ecx. On doit l'ajouter au contenu de %ecx, parce que la multiplication utilise explicitement les registres %eax et %edx. %ecx doit tre nettoy chaque fois que l'on rencontre un espace. un jmp if_space est excut, si %al est gal 32. %ecx contient la somme de tous les chiffres de chaque nombre aprs la multiplication par 10. Cette somme n'est autre que le code binaire (32 bits) du nombre. On le sauvegarde l'adresse : EA = disp + scale * index = list + %edi * 4 = list(0, index, 4) = list(,%edi,4) Le scale est gal 4 parce que la taille d'un entier est de quatre octets !

Pour bien fixer les ides, on va prendre comme exemple le nombre 229. Pour le convertir, le processeur doit effectuer le calcul suivant : 229 = (50 48) 102 + (50 48) 101 + (57 48) 100 = 2 100 + 2 10 + 9 1 Le registre %edi contient le nombre d'entiers de la nouvelle liste (list).

tape 3 : trier la liste


Voir le programme sort.c.

tape 4 : afficher la liste trie


Pour afficher un lment de la liste, l'ordinateur doit envoyer le code ASCII de chacun de ses chiffres au priphrique de sortie standard (l'cran, fd = 1). D'autre part, les entiers de la liste sont stocks dans la mmoire au format binaire
- 16 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

(32 bits). On doit donc les convertir en un flux de caractres. Autrement dit, on doit calculer les codes ASCII (48..57) de chacun de ces chiffres. C'est l'objectif de cette portion de notre code :
1. 2. 3. screen : 4. 5. 6. 7. 8. 9. next2 : 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. movl %edi,%esi movl $10,%ebx movl list(,%esi,4),%eax movl $stack,%esp movl $0,%edx divl %ebx decl %esp addl $48,%edx movb %dl,(%esp) cmpl $0,%eax jg next2 movl $stack,%edx subl %esp,%edx movl %esp,%ecx movl $1,%ebx movl $4,%eax int $0x80 movl $1,%edx movl $space,%ecx movl $1,%ebx movl $4,%eax int $0x80 decl %esi cmpl $0,%esi jge screen ## ## ## ## edx edx edx ecx <-<-<-<-taille de 991 : 0xf0000100 - 0xf00000f4 0xc = 12 octets adresse de 991 dans la pile

## division non signe

Les proprits de la pile vont nous faciliter cette tche. Une conversion dcimal-dcimal (division entire par 10) nous permettra d'extraire les chiffres de chaque entier. Pour avoir le code ASCII de chaque chiffre, on doit ajouter 48 son code obtenu par division entire (divl). Le schma suivant montre la conversion du nombre 269 :

- 17 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Les instructions 19..20 permettent de calculer le nombre d'octets empils (12 octets pour le nombre 269). Le registre %edx doit contenir ce nombre pour excuter l'appel systme. Le registre %ecx pointe vers le TOS (Top Of Stack), c'est--dire vers le premier chiffre. l'excution de l'appel systme, le processeur va afficher 2 puis 6 puis 9 (c'est exactement 269) puis un espace.

V-B - Exemple 2 : utiliser les sous-programmes en assembleur


Le but de l'exemple est de montrer le passage des paramtres travers la pile un sous-programme (fonction ou procdure). Une telle opration doit suivre quelques rgles (conventions) pour rendre efficace la communication entre le programme appelant et le sous-programme appel. Ces rgles vont prciser : comment le sous-programme va reprer et utiliser les paramtres passs ; comment le programme appelant va reprer les valeurs de retour ; comment utiliser les variables locales dans le sous-programme.

Le stack frame
Le processeur alloue, dynamiquement, un espace de stockage dans la pile pour chaque sous-programme. Cet espace est appel stack frame. Il sera utilis par le sous-programme pour stocker ses variables locales. Tout comme les variables automatiques en langage C, les variables locales seront perdues aprs le retour du sous-programme. Le stack frame sera compltement libr aprs l'excution de l'instruction RET. Le registre %esp pointe vers le TOS. Le registre %ebp contient l'adresse du premier lment.

- 18 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Les tapes suivre


Les tapes ncessaires pour invoquer efficacement un sous-programme partir du programme principal (ou partir d'un sous-programme) sont :
1. 2.

empiler les paramtres ; appeler le sous-programme ; enregistrer et mettre jour le registre %ebp, dans le sous-programme :
push %ebp movl %esp,%ebp

sauvegarder le contexte : empiler le contenu des registres du processeur pour ne pas les perdre durant l'excution du sous-programme ; excuter le sous-programme : au cours de cette tape, le registre %esp ne doit pas tre modifi. Le registre %ebp est utilis pour se rfrer aux donnes dans la pile ; librer l'espace mmoire allou aux variables locales ; restaurer les anciennes valeurs des registres ; restaurer la valeur de %ebp : cette tape va dtruire le stack frame. crire ces deux lignes de code avant l'instruction RET :

- 19 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

1. 2.

movl %ebp,%esp pop %ebp

charger l'adresse de retour dans %eip : en excutant l'instruction RET. Tout simplement, elle va charger le nouveau TOS dans le registre %esp ; nettoyer la pile : en dpilant les paramtres empils pendant l'tape 1.

Le code somme.c montre comment effectuer un passage par adresse et un passage par valeur en langage C. Cependant, le code somme.s montre ces deux mthodes de passage des paramtres en assembleur GNU. Ce programme fait appel la fonction C printf(). L'exemple 3 va expliquer comment le faire.

V-C - Exemple 3 : interfacer du code assembleur et du langage C


Cet exemple montre comment utiliser correctement une fonction C de la bibliothque standard GNU libc dans un code crit en assembleur GNU. Les deux programmes date.c et date.s utilisent les fonctions scanf et printf pour saisir et afficher la date : le programme date.c montre comment appeler une fonction standard dans un code C ; le programme date.s montre comment l'appeler dans un programme assembleur GNU.

En langage C, les paramtres sont passs entre parenthses : printf(param,) et scanf(param,). Ce n'est pas le cas en assembleur : les paramtres doivent tre passs travers la pile ! L'ordre des paramtres dans la pile est significatif ! Vous devez le respecter ! Ainsi, les stack frames des deux fonctions doivent tre organiss comme suit : Adresse 0(%ebp) 4(%ebp) 8(%ebp) 12(%ebp) 16(%ebp) 20(%ebp) Paramtre l'ancien EBP adresse de retour adresse de format (pformat et sformat) valeur/adresse de la variable jour valeur/adresse de la variable mois valeur/adresse de la variable an

Les valeurs de retour de scanf et printf sont passes au programme principal (main) par le registre EAX. Les tapes 3-9 d'appel des sous-programmes en assembleur sont invisibles, puisque nous ne sommes pas responsables de l'implmentation de la fonction standard. On va juste y faire appel !

Le Makefile
Pour construire l'excutable partir d'un code source crit purement en assembleur, on a utilis les programmes as et ld. C'est le cas de l'exemple 1. Mais pour assembler et faire l'dition de liens d'un programme assembleur invoquant des fonctions C, on doit utiliser un compilateur. Sous Linux, le compilateur C est le programme gcc.
1. date : date.o 2. gcc -gstabs -o date date.o 3. 4. date.o : date.s 5. gcc -c -o date.o date.s 6. clean : 7. rm -fv date date.o
- 20 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Le compilateur gcc va transformer (compiler) notre code (C + assembleur) en un code cible (code assembleur). Puis il va faire appel as pour assembler et ld pour construire l'excutable. Le point d'entre de ld doit tre le symbole global main. Cest ladresse partir de laquelle le processeur commencera le fetch des instructions lorsque le code sera charg en mmoire et excut. tri.s Dans cet exemple, on va rcrire le code de lexemple 1. Mais cette fois-ci, on va utiliser la fonction standard printf pour afficher la liste des entiers. De plus, on va utiliser la fonction saisir() pour saisir au clavier une liste dentiers et la fonction trier() pour trier la liste (voir le fichier func.c). Notre code devient plus simple et plus structur. Pour terminer la saisie des entiers (fonction saisir()), entrez le nombre -1 puis appuyez sur la touche Enter.

V-D - Exemple 4 : un programme damorage


Un secteur damorage (Boot Sector) est, gnralement, constitu des 512 premiers octets dun support de stockage (disquette, disque dur, CD/DVD, flash disk) qui peut contenir un programme damorage (Bootstrap program). Pour un CD/DVD, une disquette ou un disque dur, un tel secteur nest autre que le premier secteur (piste 0, tte 0, secteur 1). Dautre part, un programme damorage est un programme 16 bits excutable, qui sera charg par le programme de dmarrage du BIOS, dans la mmoire RAM durant la squence damorage de lordinateur. travers cet exemple, on va montrer comment crire un tel programme et comment le faire tourner sur une machine occupe par un processeur de la famille x86 (x86-32 ou x86-64). Vous pouvez tlcharger le code source de lexemple ici : http://asm.developpez.com/telecharger/detail/id/3506/Un-programme-d-amorcage Il contient deux fichiers sources : hello.s : un programme damorage permettant dafficher sur lcran le message Hello, World ! ; rtc.s : un programme damorage permettant de lire lhorloge temps rel (RTC :Real Time Clock) de lordinateur et de lafficher sur lcran.

Le BIOS
Pour une machine compatible avec lIBM PC, le BIOS (Basic Input Output System) est le premier programme (microcode ou firmware) excut par le processeur juste aprs la mise sous tension de lordinateur. Le programme (les routines) BIOS est stock dans une mmoire non volatile (ROM) intgre la carte mre. Il a deux fonctions principales : 1 2 excuter les tests POST (Power-On Selft-Test) : vrifier lintgrit du programme BIOS lui-mme, tester la RAM, tester les autres priphriques de lordinateur ; chercher un priphrique amorable (bootable) pour dmarrer le systme (charger le noyau du systme en mmoire). Cest en vrifiant, dans lordre, le secteur damorage de chaque priphrique connect lordinateur et configur dans la liste (du BIOS) des priphriques damorage. Lorsque le BIOS rencontre un secteur damorage, il charge le programme stock dedans, dans la mmoire et lui transfre le contrle.

- 21 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Le mode rel
Le 80386 a introduit aux processeurs de la famille x86 la capacit fonctionner en trois modes : mode protg, mode virtuel et mode rel (ou mode 8086). Ce qui nous intresse, dans cet exemple, cest le mode rel. Cest le mode de fonctionnement du processeur immdiatement aprs la mise de lordinateur sous tension. Dans ce mode, certains registres du processeur sont initialiss, par INTEL, des valeurs prdfinies. En outre, la protection, les interruptions et la pagination sont dsactives et lespace mmoire complet est disponible. Ainsi, le processeur peut excuter uniquement des programmes 16 bits. Cet tat du processeur est adquat pour excuter un programme damorage.

Ltat interne du processeur en mode rel


En mode rel, un processeur de la famille x86 (x86-32 ou x86-64) excute uniquement des codes 16 bits conus pour le 80286 et le 8086. Par consquent, son architecture interne est presque identique celle du 8086.

La mmoire
Quelle que soit la taille de la mmoire de votre ordinateur, dans le mode rel le processeur peut adresser seulement 1Mo + 64Ko de RAM. Les 64Ko sont utiliss pour adresser les priphriques dentres/sorties. Le processeur peut, alors, seulement manipuler des octets et des mots (16 bits). Cet espace mmoire peut tre localis dans nimporte quelle zone dans la mmoire physique, condition quelle ne soit pas rserve par INTEL.

Les registres
Le tableau suivant montre comment certains registres (le 30486, le Pentium I et tous les processeurs de la famille P6) sont initialiss en mode rel : Registre EFLAGS EIP CS DS,SS,ES,FS,GS GDTR,IDTR Contenu 0x0002 0xFFF0 Slecteur : 0xF000 Base : 0xFFFF0000 Limite : 0xFFFF Base : 0x00000000 Limite : 0xFFFF Base : 0x00000000 Limite : 0xFFFF

Pour plus de dtails, jetez un coup dil sur le chapitre 9 dans ce document : http://download.intel.com/design/processor/manuals/253668.pdf En mode protg, un processeur de la famille x86 utilise la rgle suivante pour calculer une adresse physique : Adresse linaire = Adresse physique = Base + Offset On la appele adresse physique parce quen mode rel la pagination sera dsactive.

- 22 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Dautre part, en mode rel ladresse physique est normalement calcule en utilisant cette rgle : Adresse logique = Offset : Base[segment selector] Adresse physique = Base x 16 + Offset Cependant, la rinitialisation du processeur (RESET), ladresse de Base est gale 0xFFFF0000 (voir le tableau ci-dessus). Ainsi, ladresse de dpart est forme par addition de la valeur de ladresse de base et le contenu du registre EIP (offset). Ainsi : Adresse physique = 0xFFFF0000 + 0xFFF0 = 0xFFFFFFF0 Juste aprs la mise sous tension de lordinateur, le processeur utilise la premire rgle pour localiser et excuter le programme BIOS. Ensuite, le processeur va suivre la rgle normale pour la traduction des adresses en mode rel (processeur 8086). La premire instruction qui sera excute par le processeur, aprs RESET, devrait tre ladresse physique 0xFFFFFFF0. Cette instruction va amener le processeur excuter un saut (JMP) vers le programme BIOS. Lorsque celui-ci prend le contrle, il commence par excuter les tests POST. Une fois ces tests passs avec succs, le programme BIOS va chercher un priphrique amorable pour dmarrer le systme.

Un programme damorage minimal


Pour vrifier si un support de stockage est amorable ou non, le BIOS teste simplement les deux derniers octets (octets 510 et 511) du secteur damorage. Si ces deux octets contiennent la valeur 0xAA55 (Boot Signature) alors le BIOS considrera ce priphrique comme amorable. Alors, il chargera les 512 octets du code ladresse physique 0x7C00 de la mmoire et lui transfrera le contrle (JMP 0x7C00). ce stade, le rle du BIOS se termine. Le code suivant est celui dun programme damorage minimal :
1. .code16 2. .data 3. .text 4. .global _start 5. 6. _start : 7. 8. .org 510,0 9. signature : 10. .word 0xaa55

Un support de stockage, dont le secteur damorage contient le binaire de ce programme, sera certainement amorable. Mais, comme vous voyez, ce programme ne fera rien son excution (un cran noir et vide sera affich). Il va juste rendre votre support de stockage amorable. La directive .org a t dj explique. Le directive .code16 va demander lassembleur dassembler un code 16 bits (mode rel). En fait, tout Linuxien a un programme damorage prt sur son ordinateur. Cest le stage1 de chargeur de boot GRUB. Ce fichier est stock dans le rpertoire /usr/lib/grub/stage1. Son rle est dinitialiser le processeur au dmarrage et de charger en mmoire le noyau GRUB (stage2). Pour tester un programme damorage, vous pouvez utiliser une machine virtuelle au lieu de redmarrer votre ordinateur plusieurs fois. Le logiciel VirtualBox, par exemple, vous permettra den crer une. En cas de problme de dmarrage dune machine virtuelle sur un flash disk, visitez cette page :

- 23 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

http://www.twm-kd.com/software/boot-virtualbox-machine-from-a-usb-flash-drive Exemple 1 : hello.s


1. 2. 3. 4. _start : 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. msg : 19. 20. 21. signature 22. .code16 .text .global_start mov %cs,%ax mov %ax,%ds mov %ax,%es mov %ax,%ss mov $0x100,%ax mov %ax,%sp mov $0x2f,%bl mov $0,%dh mov $0,%dl mov $0x1301,%ax mov $msg,%bp mov $13,%cx int $0x10 # ax = 0x7c0 # ds = 0x7c0 # es = 0 x7c0 # ss = 0 x7c0 # 256 words dans la pile (512 octets) # sp = 256 (TOS) # # # # # colonne 0 ligne 0 afficher une chane de caractres offset du message ES:BP taille du message

.asciz "hello, world !" .org 510 .word 0xaa55

Comme on la dit, au dmarrage de lordinateur ce programme sera charg dans la mmoire ladresse 0x7C00 et prendra le contrle. Le registre CS (base) sera charg avec la valeur 0x7C0 et le contenu de EIP (offset) sera 0. Ainsi, le processeur commencera la recherche des instructions (fetch) et lexcution partir de ladresse physique : CS x 16 + EIP = 0x07C0 x 0x10 + 0x0000 = 0x7C00 Notre programme possde les mmes segments de donnes de pile et de code (DS = SS = ES = CS = 0x7C0). On a utilis linterruption 0x10 du BIOS pour afficher notre message. Une liste des interruptions est disponible sur cette page : http://www.ctyme.com/intr/int.htm Vous pouvez choisir un autre segment de pile.

Assemblage et dition de liens


On donne les commandes dassemblage et ddition de liens :
as -o hello.o hello.s ld --oformat binary -Ttext 7c00 -Tdata 7c00 -o hello hello.o

On a utilis loption -oformat pour spcifier lditeur de liens le format binaire du fichier de sortie (hello). Le format binaire doit tre choisi. Si on dite les liens sans utiliser cette option, la taille du fichier gnr dpassera 512 octets. Quand on passe cette option lditeur de liens, il va gnrer un fichier de sortie au format binaire (raw binary). Autrement dit, il va gnrer un code machine sans en-ttes (headers) ayant exactement une taille 512 octets. galement, les options -Ttext et -Tdata sont utilisEs pour indiquer lditeur de liens que les sections de texte et de donnes doivent tre chargES ladresse 0x7C00. Pour dsassembler le fichier gnr et afficher les informations quil contient, vous pouvez utiliser la commande suivante :
objdump -b binary -mi8086 -D hello
- 24 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Loption -b va spcifier le format de fichier dentre (binaire). Loption -m va spcifier larchitecture pour laquelle on va dsassembler. Nous avons spcifi larchitecture i8086. Finalement, pour tester votre programme vous devez le copier dans le secteur damorage dun flash disk par exemple. Connectez votre flash disk, puis vrifiez son nom avec la commande fdisk -l. Le nom doit commencer par le prfixe sdb suivi par son numro. Soyez prudent, les noms qui commencent par sda sont rservs pour les partitions de disque dur de votre ordinateur. Une confusion et vous risqueriez deffacer les donnes stockes sur une partition ou dendommager votre systme ! Pour copier le fichier binaire dans le secteur d'amorage de votre flash disk, utilisez la commande :
dd_rescue hello /dev/sdb

Exemple 2 : rtc.s Dans cet exemple, nous allons crire un programme damorage qui, son excution, va lire lhorloge temps rel (RTC) de lordinateur en utilisant linterruption BIOS numro 0x1A et lafficher au format hh:mm:ss. A lexcution de cette interruption, le processeur va lire lhorloge RTC et stocker sa valeur au format BCD (Binary Coded Decimal), dans les registres CX et BX :

Pour afficher lhorloge, nous devons, dabord, convertir chacun de ses chiffres cods au format BCD en son code ASCII appropri. Le codage BCD utilise 4 bits pour coder chaque chiffre dcimal. Tandis que le codage ASCII utilise 8 bits (tendu) ou 7 bits (standard). Le tableau suivant donne le codage BCD et le codage ASCII des chiffres dcimaux : Dcimal 0 1 2 3 4 5 6 7 8 9 BCD 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 ASCII (dcimal) 48 49 50 51 52 53 54 55 56 57 ASCII (binaire) 00110000 00110001 00110010 00110011 00110100 00110101 00110110 00110111 00111000 00111001

Les bits 0-3 de chaque code ASCII dun chiffre sont gaux son code BCD. Le sous programme bsd_to_ascii va raliser cette conversion (voir le code source rtc.s). Pour lillustrer, nous allons prendre un exemple. Supposons que lhorloge lue soit 23:45:37. Le contenu des registres CX et BX sera :

- 25 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Introduction l'Assembleur GNU par Issam Abdallah

Nous allons expliquer comment convertir lheure (h2h1) du format BCD au format ASCII. tape 1 : Dcalage logique (SHR) de 4 bits du contenu du registre AL : SHR $4, %al : 0010 0011 4 = 0000 0010 tape 2 : Addition de 48 : 0000 0010 + 00110000 = 110010 = 5010 = ASCII(2) Ensuite, on charge le contenu de AL dans la mmoire ladresse rtc(%si). tape 3 : Maintenant, nous allons convertir h2. Tout dabord, on charge le contenu du registre CH dans AL. Ensuite, on ajuste le contenu de AL avec linstruction AAA : AAA : 0010 0011 ==> 0000 0011 tape 4 : Addition de 48 : 0000 0011 + 00110000 = 0011 0011 = 5110 = ASCII(3) Ensuite, on charge le contenu de AL dans la mmoire ladresse rtc(%si). Les mmes tapes seront utilises pour convertir les minutes et les secondes. Utilisez les mmes commandes (exemple 1) pour assembler, diter les liens et tester cet exemple.

VI - Rfrences
Intel 80386 Programmer's Reference Manual ; le manuel de l'assembleur GNU ; le manuel du linker ld ; PC Assembly Language, par Paul A. Carter.

VII - Remerciements
Je remercie Obsidian pour sa relecture technique et zoom61 pour sa relecture orthographique.

- 26 -

Les sources prsentes sur cette page sont libres de droits et vous pouvez les utiliser votre convenance. Par contre, la page de prsentation constitue une uvre intellectuelle protge par les droits d'auteur. Copyright 2013 Issam Abdallah. Aucune reproduction, mme partielle, ne peut tre faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu' trois ans de prison et jusqu' 300 000 de dommages et intrts.

Vous aimerez peut-être aussi