Académique Documents
Professionnel Documents
Culture Documents
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.
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.
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.
-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.
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.
-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.
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
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
-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.
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
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.
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.
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.
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.
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.
-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.
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.
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.
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.
1. 2. 3. 4.
# ENDSEG = 0x81000
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
Cet ordre doit tre respect avec le reste des instructions : sub, add
- 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.
Le premier lment est le nombre 23 et il est situ l'adresse tab_byte, suivi par le code ASCII du caractre %
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.
- 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.
1. tab_int :
.int 3*6,16,190,-122
Dfinit un tableau contenant 256 quad-mots l'adresse idt. Chaque lment du tableau contient zro comme valeur.
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.
.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.
- 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.
1. 2.
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.
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.
## ECX = l'adresse du buffer ## EDX = la taille du buffer ## clavier (stdin) ## appel systeme 3 : read
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.
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.
## 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
## 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.
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.
## incrmenter la position
movl %ecx,list(,%edi,4)
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).
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.
(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
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.
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.
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.
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.
1. 2.
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.
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.
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.
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.
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.
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.
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 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.
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.
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.
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.
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.