Description
Dans cet article, je vais détaillé comment j’ai écris un code ASM x64 afin d’afficher une input d’un utilisateur précédé d’un texte.
Code source final
section .data
text db 'texte :',0
section .bss
buffer resb 10 ; Réserve un espace de 10 octets pour stocker l'entrée de l'utilisateur
section .text
global _start
_start:
; Enregistrer dans une variable
mov rax, 0 ; syscall pour lire l'entrée de la sortie standard
mov rdi, 0 ; file descriptor 0 is stdin
mov rdx, 10 ; défini la taille maximale de l'entrée
mov rsi, buffer ; pointeur vers la zone de mémoire tampon
syscall
; Afficher "texte :"
mov rax, 1 ; syscall number for sys_write
mov rdi, 1 ; file descriptor 1 is stdout
mov rsi, text ; pointeur vers la chaîne de texte
mov rdx, 7 ; longueur de la chaîne
syscall
; Afficher la valeur saisie
mov rax, 1 ; syscall number for sys_write
mov rdi, 1 ; file descriptor 1 is stdout
mov rsi, buffer ; pointeur vers la zone de mémoire tampon
mov rdx, 10 ; longueur de la chaîne
syscall
; Sortir du programme
mov rax, 60 ; syscall number for sys_exit
xor rdi, rdi ; code de sortie 0
syscall
1 - Enregistrer l’input dans une variable
section .bss
buffer resb 10 ; Réserve un espace de 10 octets pour stocker l'entrée de l'utilisateur
Pour pouvoir géré par la suite l’input, il faut allouer un espace mémoire. 10 octets non rempli sont donc réservé à la variable buffer.
; Enregistrer dans une variable
mov rax, 0 ; syscall pour sys_read
mov rdi, 0 ; file descriptor 0 is stdin
mov rdx, 10 ; défini la taille maximale de l'entrée
mov rsi, buffer ; pointeur vers la zone de mémoire tampon
syscall
Le premier mov décrit comment le systême doit intéragir, dans ce cas ci sys_read.
Ce sys_read prend 3 paramètres au total.
Ce sys_read prend l’un de ses paramètres un “descripteur” stocké dans rdi qui correspond au descripteur stdin qui est l’équivalent de “lire l’entrée”.
Il prend aussi un pointeur vers la zone de mémoire où l’input doit être stocké dans notre cas l’instruction mov rsi,buffer spécifie l’adresse mémoire déjà définie où stocker l’input.
En dernier paramètre il prend aussi la taille maximal d’octets qu’il devra lire, ce qui se fait par l’opération mov rdx, 10 qui défini la taille maximal de l’entrée
2 - afficher le texte
Comme dans le hello world précédent.
## 3 - afficher ma variable avec l’input
; Afficher la valeur saisie
mov rax, 1 ; syscall number for sys_write
mov rdi, 1 ; file descriptor 1 is stdout
mov rsi, buffer ; pointeur vers la zone de mémoire tampon
mov rdx, 10 ; longueur de la chaîne
syscall
Ma variable buffer possède a présent la valeur d’input qui a été placé via le 1 er point. Donc pour l’afficher il suffit d’effectuer les même opérations que pour afficher n’importe quelle texte.
4 - sortie du programme
remettre à 0 le code de sortie et mettre à jour rax pour le passer en mode sys_exit comme dans les programmes précédent.
Code source - broken
Afin d’arriver au code source fonctionnel du dessus, j’ai commencé à écrire ma version sans aide pour voir si j’avais bien compris les concepts.
Voici donc une version cassé :
section .data
input db "", 0 ;
texte db 'texte :',0 ;
section .text
global _start
_start:
; enregistrer dans une variable
mov rax, 0 ; syscall pour afficher l'entrée
mov rdi, 0 ; syscall pour lire l'entrée de la sortie standar
mov rdx, 10 ; défini la taille maximal de l'entrée
mov rsi, input ; écrit dans ma variable input
syscall
; afficher "texte :"
mov rax, 1 ; syscall number for sys_write
mov rdi, 1 ; file descriptor 1 is stdout
mov rsi, texte ; pointer to the string
mov rdx, 7 ; length of the string
syscall
; afficher la valeur
mov rax, 1 ; syscall number for sys_write
mov rdi, 1 ; file descriptor 1 is stdout
mov rsi, input ; pointer to the string
mov rdx, 10 ; length of the string
syscall
; sortir du programme
mov rax, 60 ; syscall number for sys_exit
xor rdi, rdi ; exit code 0
syscall
J’ai mis pas mal de temps à comprendre ce qui n’allait pas puis j’ai réalisé que ma variable “input” qui remplace “buffer” du code précédent est définie comme ayant seulement un espace suivi d’un 0.
Ce qui lui donne une taille de deux, lorsque j’essaie d’exécuter ce code.
Le code va essayé d’écrire sur une adresse mémoire qui n’a pas l’espace suffisant il va donc overflow et écrire sur la variable définie après qui se trouve être mon texte.
Voici en image ce que cela donne :