Description
Voici comment lire un fichier text en assembleur X64 sous linux.
Code source
Voici le code que je vais détailler par la suite :
section .data
filename db 'fichier.txt', 0
section .text
global _start
_start:
; Ouvrir le fichier
mov rdi, filename ; le nom du fichier dans RDI
mov rsi, 0 ; syscall en mode read only
mov rdx, 0 ; mode par défaut
mov rax, 2 ; syscall numéro 2 pour open
syscall
mov r8, rax ; sauvegarder le descripteur de fichier
; Vérifier si l'ouverture du fichier a réussi
cmp r8, 0 ; compare la valeur dans r8 à 0
jl .error ; jump si 0 ou - que 0
; Lire le contenu du fichier et l'afficher
mov rdi, r8 ; descripteur de fichier
mov rsi, rsp ; pointeur de mémoire où stocker les données lues (utilisation de la pile)
mov rdx, 1024 ; nombre maximal d'octets à lire
mov rax, 0 ; syscall numéro 0 pour read
syscall
; Afficher le contenu lu
mov rdi, 1 ; file descriptor pour stdout
mov rsi, rsp ; pointeur de mémoire où se trouve le contenu lu
mov rdx, rax ; longueur du contenu lu
mov rax, 1 ; syscall numéro 1 pour write
syscall
; Fermer le fichier
mov rdi, r8 ; descripteur de fichier
mov rax, 3 ; syscall numéro 3 pour close
syscall
; Terminer le programme
mov rax, 60 ; syscall numéro 60 pour exit
xor rdi, rdi ; code de sortie 0
syscall
.error:
; Gestion des erreurs
mov rdi, r8 ; code d'erreur
mov rax, 60 ; syscall numéro 60 pour exit
syscall
Comme vu précédemment l’instruction filename db ‘fichier.txt’, 0 stocke la chaine de caractère ‘fichier.txt’ dans une variable appelé filename
1 - Ouverture du fichier
Cette section reprend l’ensemble des opérations à envoyé à l’os afin qu’il puisse ouvrir le fichier et stocker son ouverture dans un registre appelé r8.
; Ouvrir le fichier
mov rdi, filename ; le nom du fichier à ouvrir dans rdi
mov rsi, 0 ; sycall pour le mode read only
mov rdx, 0 ; prends les permissions par défaut du système
mov rax, 2 ; syscall numéro 2 pour passer en mode ouverture
syscall
mov r8, rax ; sauvegarder le descripteur de fichier
Le descripteur est utilisé pour stocké en quelque sorte le statut d’ouverture du fichier dans un registre r8 qui servira plus tard.
2 - Gestion des erreurs lors de la lecture
; Vérifier si l'ouverture du fichier a réussi
cmp r8, 0 ; compare la valeur dans r8 à 0
jl .error ; jump si 0 ou - que 0
l’instruction cmp r8, 0 donne l’équivalent du tableau suivant :
r8 | 0 | Resultat |
---|---|---|
r8>0 | 0 | n>0 |
0 |
0 | 0 |
r8<0 | 0 | n<0 |
La comparaison se fait comme un “-“ mathématique ce qui revient à faire “la valeur de r8 - 0” si cette valeur est inférieur ou égale à 0 alors le bit de signe appelé SF sera mis à 0 ou moins et l’instruction “jl” se déclanchera. A noté que ce bit est “un indicateur de statut” et non pas une variable ou un registre à proprement parlé sa valeur est donc tout le temps définie et mise à jour avec cmp
jl .error : est l’équivalent de (jump if less than) soit “saute si plus petit que” 0 ou égale à 0.
3 - Lecture du fichier
; Lire le contenu du fichier et l'afficher
mov rdi, r8 ; place le descripteur du fichier dans le registre de destination
mov rsi, rsp ; pointeur de mémoire où stocker les données lues (utilisation de la pile)
mov rdx, 1024 ; nombre maximal d'octets à lire
mov rax, 0 ; syscall numéro 0 pour read
syscall
mov rsi, rsp : permet de pointer le haut de la pile afin d’y stocké le contenu
mov rdx, 1024 : Cette instruction indique au système d’exploitation de lire jusqu’à 1024 octets depuis le descripteur de fichier (rdi) et de les stocker à l’adresse mémoire pointée par rsi (c’est-à-dire au sommet de la pile).
NB : rdi est le registre utilisé courrament pour stocké la destination rsi est le registre utilisé courrament pour stocké la source donc mov rdx, 1024 revient à lire 1024 octet depuis rdi et de les stockés dans rsi.
4 - afficher le contenu sur la sortie standard
; Afficher le contenu lu
mov rdi, 1 ; sortie standard comme dans le "hello world"
mov rsi, rsp ; stock l'adresse du haut de la pile là où le fichier à été précédemment stocké
mov rdx, rax ; longueur du contenu lu
mov rax, 1 ; syscall numéro 1 pour write
syscall
rax stock la valeur de retour précédente qui dans notre cas la taille du fichier lu jusqu’à un maximum de 1024 octets.
5 - fermer le fichier
; fermer le fichier
mov rdi, r8 ; descripteur de fichier qui a été stocké précédement dans r8
mov rax, 3 ; syscall numéro 3 pour close
syscall
Ferme le fichier permet de supprimer la valeur de r8 et de libérer un descripteur de fichier.
6 - fermer le programme
; Terminer le programme
mov rax, 60 ; demande à l'os lors du syscall de sortir de l'application pour signifié qu'elle a terminé
xor rdi, rdi ; code de sortie 0 pour dire que tout a bien fonctionné
syscall
7 - gestion des erreurs
.error:
; Gestion des erreurs
mov rdi, r8 ; code d'erreur contenu dans r8 sera présent dans le echo $?
mov rax, 60 ; demande à l'os lors du syscall de sortir de l'application pour signifié qu'elle a terminé
syscall