-
Assembleur 64bits
Bienvenue sur la page consacrée au langage Assembleur.
Il est particulièrement difficile d'obtenir un code en assembleur correct avec les intelligences artificielles actuelles.
Les IA ont beaucoup de mal à générer un code assembleur fonctionnel, que ce soit ChatGPT4, Claude, Haiku etc.. et pour de nombreuses raisons (différences entre noyaux, conceptualisation très difficile à partir de langages de haut niveau etc..)
Voici donc quelques petits exemples fonctionnels d'interaction avec le shell de FreeBSD à montrer aux IA pour obtenir le résultat attendu pour d'autres programmes (plus complexes).
En gros, vous copier/collez ces exemples avec vos demandes pour qu'elles s'inspirent de ces bouts de code qui sont fonctionnels.
A savoir, les exemples ci-dessous sont écrits pour FreeBSD avec une architecture x86_64 (64 bits ET NON 32 bits... c'est volontaire étant donné qu'il est beaucoup plus difficile d'écrire en 64 bits qu'en 32).
Ils devront être adaptés pour Linux (les numéros d'appels système ne sont pas les mêmes).. (et je ne parle pas de windows...).
L'idée, c'est juste de se marrer un coup, mais c'est relativement instructif quand même !
Vous y trouverez :
- Premier programme 64 bit en assembleur sous FreeBSD : afficher du texte sur le terminal
- Comparatif de chaîne de caractères
- Exécuter une commande du système
- Enchaîner des commandes du système
- Comparatif de chaîne de caractères et exécution de commande système
- Compter le nombre de caractères d'un fichier
- Perroquet (répète ce qu'on lui écrit, avec ajustement de la longueur de l'entrée)
- Addition/soustraction/multiplication/division (non interactives)
- Afficher 'hello world' dans une fenêtre graphique (gtk)
- Faire apparaître un bouton OK avec gtk
- Afficher le contenu d'un fichier
- Question/Réponse (aimez-vous le chou ? [o/n])
- Créer un menu avec plusieurs propositions et y répondre
- Vérifier l'existence d'un fichier
- Vérifier l'existence d'une ressource (dossier ou fichier)
- Test de connexion internet : Afficher "Connexion réussie" ou "Echec de la connexion" en fonction
- Faire la mise-à-jour du système
- Vérifier l'existence d'un utilisateur (sys_getlogin) -
Par majekla le 9 Octobre 2024 à 13:46
Vérifier l'existence d'un utilisateur sur le système et afficher un résultat selon
Créez le programme check_user.asm :
section .data
user db 'marcel',0 ; Nom de l'utilisateur à vérifier
msg_exist db "L'utilisateur existe", 10, 0 ; Message si l'utilisateur existe
len_exist equ $ - msg_exist ; Longueur du message si l'utilisateur existe
msg_not_exist db "L'utilisateur n'existe pas", 0xA, 0 ; Message si l'utilisateur n'existe pas
len_not_exist equ $ - msg_not_exist ; Longueur du message si l'utilisateur n'existe pas
section .bss
login resb 256 ; Buffer pour stocker le nom de l'utilisateur connecté
section .text
global _start
_start:
; Appel système pour obtenir le nom de l'utilisateur connecté
mov eax, 49 ; Numéro de l'appel système sys_getlogin (49)
lea rdi, [login] ; Pointeur sur le buffer pour le nom d'utilisateur
mov rsi, 256 ; Taille du buffer
syscall ; Appel système
; Comparer le nom d'utilisateur obtenu avec 'majekla'
mov rdi, user ; Pointeur sur le nom d'utilisateur à vérifier
mov rsi, login ; Pointeur sur le nom d'utilisateur obtenu
call strcmp ; Appel à strcmp
test eax, eax ; Vérifier le résultat de strcmp
jz user_exists ; Sauter si les chaînes sont identiques
; Si l'utilisateur n'existe pas
mov rax, 4 ; sys_write
mov rdi, 1 ; stdout
mov rsi, msg_not_exist ; Message à afficher
mov rdx, len_not_exist ; Longueur du message
syscall ; Appel système pour afficher le message
jmp exit ; Aller à la fin du programme
user_exists:
; Si l'utilisateur existe
mov rax, 4 ; sys_write
mov rdi, 1 ; stdout
mov rsi, msg_exist ; Message à afficher
mov rdx, len_exist ; Longueur du message
syscall ; Appel système pour afficher le message
exit:
; Terminer le programme
mov rax, 1 ; sys_exit
xor rdi, rdi ; Code de retour
syscall ; Appel système
; Fonction strcmp (compare deux chaînes)
strcmp:
push rdi ; Sauvegarder RDI
push rsi ; Sauvegarder RSI
push rcx ; Sauvegarder RCX
xor rcx, rcx ; RCX = 0
cld ; Effacer la direction flag pour l'incrémentation
strcmp_loop:
lodsb ; Charger le byte à [RSI] dans AL et incrémenter RSI
scasb ; Comparer AL avec le byte à [RDI] et incrémenter RDI
jne strcmp_done ; Si non égal, fin de la boucle
test al, al ; Vérifier si nous avons atteint la fin de la chaîne
jnz strcmp_loop ; Si non, continuer la boucle
xor eax, eax ; Les chaînes sont identiques
jmp strcmp_cleanup ; Nettoyer et retourner
strcmp_done:
mov eax, 1 ; Les chaînes sont différentes
sub al, [rdi - 1] ; Calculer la différence
strcmp_cleanup:
pop rcx ; Restaurer RCX
pop rsi ; Restaurer RSI
pop rdi ; Restaurer RDI
ret ; Retourner- Assembler
nasm -f elf64 check_user.asm -o check_user.o
- Linker
ld check_user.o -o check_user
- Lancer le programme
./check_user
votre commentaire -
Par majekla le 9 Octobre 2024 à 13:40
Le but ici est d'enchaîner l'exécution des commandes freebsd-update -F fetch et freebsd-update -F install silencieusement et d'afficher la chaîne "- le système est à jour" à la fin :
Créer le programme update_system.asm :section .data
message3 db "- système à jour", 10, 0
message3_len equ $ - message3
command db '/bin/sh', 0
arg1 db '-c', 0
arg2_1 db 'freebsd-update -F fetch >/dev/null 2>&1 && freebsd-update -F install >/dev/null 2>&1', 0
argv dq command, arg1, arg2_1, 0
envp dq 0
section .text
global _start
_start:
; Exécuter les commandes freebsd-update
mov rdi, command
mov rsi, argv
call execute_command
; Afficher le message final
mov rax, 4
mov rdi, 1
lea rsi, [message3]
mov rdx, message3_len
syscall
; Terminer le programme
mov rax, 1
xor rdi, rdi
syscall
execute_command:
; Sauvegarder les arguments sur la pile
push rdi
push rsi
; Créer un nouveau processus
mov rax, 2
syscall
; Vérifier si nous sommes dans le processus parent ou enfant
test rax, rax
jz child_process
; Processus parent, attendre que le processus enfant termine
mov rdi, rax
xor rsi, rsi
xor rdx, rdx
mov rax, 7
syscall
; Restaurer les arguments et retourner
pop rsi
pop rdi
ret
child_process:
; Restaurer les arguments
pop rsi
pop rdi
; Exécuter la commande dans le processus enfant
mov rax, 59
lea rdx, [envp]
syscall
; Si execve échoue, sortir avec un code d'erreur
mov rax, 1
mov rdi, 1
syscall- Assembler
nasm -f elf64 update_system.asm -o update_system.o
- Linker
ld update_system.o -o update_system
- Lancer le programme
./update_system
votre commentaire -
Par majekla le 9 Octobre 2024 à 13:16
On rentre dans l'exécution des processus parents/enfants encore une fois.
L'exécution d'une commande permettant de vérifier si on accède à internet doit afficher un résultat, quel que soit le cas de figure (êtes-vous connectés à internet ou non)Créez le programme check_internet.asm :
section .data
command db '/bin/sh', 0
arg1 db '-c', 0
arg2 db 'fetch -q -o /dev/null https://www.freebsd.org 2>/dev/null', 0
argv dq command, arg1, arg2, 0
envp dq 0
success_msg db 'Connexion réussie', 10, 0
success_msg_len equ $ - success_msg
failure_msg db 'Échec de la connexion', 10, 0
failure_msg_len equ $ - failure_msg
section .bss
wstatus resq 1
section .text
global _start
_start:
mov rax, 2 ; sys_fork
syscall
test rax, rax
jz child_process
; Processus parent
mov rdi, rax ; PID de l'enfant
mov rsi, wstatus ; Pointeur vers le statut
xor rdx, rdx ; Options
mov rax, 7 ; sys_wait4
syscall
; Vérifier le code de retour
mov rax, [wstatus]
and rax, 0xFF00
shr rax, 8
test rax, rax
jnz connection_failure
; Afficher le message de succès
mov rax, 4 ; sys_write
mov rdi, 1 ; stdout
mov rsi, success_msg
mov rdx, success_msg_len
syscall
jmp exit_program
connection_failure:
; Afficher le message d'échec
mov rax, 4 ; sys_write
mov rdi, 1 ; stdout
mov rsi, failure_msg
mov rdx, failure_msg_len
syscall
exit_program:
mov rax, 1 ; sys_exit
xor rdi, rdi ; Code de sortie 0
syscall
child_process:
mov rax, 59 ; sys_execve
mov rdi, command
mov rsi, argv
mov rdx, envp
syscall
; Si execve échoue, sortir avec un code d'erreur
mov rax, 1 ; sys_exit
mov rdi, 1 ; Code de sortie 1 (erreur)
syscall- Assembler
nasm -f elf64 check_internet.asm -o check_internet.o
- Linker
ld check_internet.o -o check_internet
- Lancer le programme
./check_internet
votre commentaire -
Par majekla le 1 Mai 2024 à 19:18
Comment compter le nombres de caractères d'un fichier et afficher le résultat.
Le problème ici, c'est le comptage dynamique... j'avoue ne pas encore savoir comment faire.
Alors je définis un tampon de 1024- Ecrire le programme count.asm :
section .data
filename db '/tmp/test', 0 ; Nom du fichier à lire
buffer_size equ 1024 ; Taille du buffer pour lire le fichier
read_msg db 'Nombre de caractères : ', 0
read_msg_len equ $ - read_msg
newline db 10, 0 ; Caractère de retour à la ligne
section .bss
buffer resb buffer_size ; Buffer pour stocker les données lues
count resq 1 ; Compteur de caractères (64 bits)
num_str resb 21 ; Buffer pour le nombre converti en chaîne
section .text
global _start
_start:
; Ouvrir le fichier en lecture seule
mov rax, 5 ; sys_open
lea rdi, [filename] ; Pointeur vers le nom du fichier
mov rsi, 0 ; Flags (O_RDONLY)
mov rdx, 0 ; Mode (non utilisé en lecture)
syscall
; Vérifier si l'ouverture a réussi
test rax, rax
js exit ; Si rax est négatif, erreur lors de l'ouverture
; Stocker le descripteur de fichier
mov rdi, rax ; Descripteur de fichier dans rdi pour les appels suivants
; Initialiser le compteur à zéro
xor rax, rax
mov [count], rax
read_loop:
; Lire du fichier dans le buffer
mov rax, 3 ; sys_read
lea rsi, [buffer] ; Pointeur vers le buffer
mov rdx, buffer_size ; Nombre de bytes à lire
syscall
; Vérifier si la fin du fichier a été atteinte
test rax, rax
jz display_result ; Si rax est zéro, fin du fichier
; Ajouter le nombre de bytes lus au compteur
add [count], rax
; Continuer la lecture
jmp read_loop
display_result:
; Convertir le compteur en chaîne
mov rax, [count] ; Charger le compteur
lea rdi, [num_str] ; Pointeur vers le buffer de la chaîne
call int_to_string ; Convertir le nombre en chaîne
; Afficher le message
mov rax, 4 ; sys_write
mov rdi, 1 ; Descripteur de fichier stdout
lea rsi, [read_msg] ; Message à afficher
mov rdx, read_msg_len ; Longueur du message
syscall
; Afficher le nombre de caractères
mov rax, 4 ; sys_write
mov rdi, 1 ; Descripteur de fichier stdout
lea rsi, [num_str] ; Pointeur vers la chaîne du nombre
mov rdx, 21 ; Longueur maximale de la chaîne du nombre
syscall
; Afficher un retour à la ligne
mov rax, 4 ; sys_write
mov rdi, 1 ; Descripteur de fichier stdout
lea rsi, [newline] ; Caractère de retour à la ligne
mov rdx, 1 ; Longueur du caractère
syscall
; Fermer le fichier
mov rax, 6 ; sys_close
syscall
exit:
; Terminer le programme
mov rax, 1 ; sys_exit
xor rdi, rdi ; Code de sortie
syscall
; Fonction pour convertir un nombre entier en chaîne de caractères
int_to_string:
mov rcx, 10 ; Base décimale
mov rbx, rdi ; Sauvegarder le pointeur vers le buffer de la chaîne
add rdi, 20 ; Pointer vers la fin du buffer
mov byte [rdi], 0 ; Terminer la chaîne avec un null terminator
convert_loop:
xor rdx, rdx ; Clear rdx avant la division
div rcx ; Diviser rax par 10, résultat dans rax, reste dans rdx
add dl, '0' ; Convertir le reste en caractère ASCII
dec rdi ; Déplacer le pointeur de la chaîne vers la gauche
mov [rdi], dl ; Stocker le caractère
test rax, rax ; Vérifier si rax est zéro
jnz convert_loop ; Continuer si non zéro
mov rax, rbx ; Restaurer le pointeur vers le début du buffer
ret- Assembler
nasm -f elf64 count.asm
- Linker
ld count.o -o count
- Lancer le programme
./user
votre commentaire -
Par majekla le 1 Mai 2024 à 15:15
Scénario No.1 :
- Afficher "Je vais executer la commande 'ls'"
- Exécuter la commande 'ls'- Ecrire le programme 2cmds.asm suivant :
section .data
message db "Je vais exécuter la commande 'ls'", 10, 0 ; Message à afficher
message_len equ $-message
command db '/bin/ls', 0 ; Commande à exécuter
argv dq command, 0 ; Tableau d'arguments pour ls
envp dq 0 ; Tableau d'environnement vide
section .text
global _start
_start:
; Afficher le message
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
lea rsi, [message] ; Adresse du message à afficher
mov rdx, message_len ; Longueur du message
syscall ; Appeler le système pour afficher le message
; Exécuter la commande 'ls'
mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
syscall ; Appeler le système pour exécuter la commande 'ls'
; Terminer le programme proprement
mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système pour terminer le programme- Assembler
nasm -f elf64 2cmds.asm
- Linker
ld 2cmds.o -o 2cmds
- Lancer le programme
./2cmds
Scénario No.2 :
- Afficher "Je vais executer la commande 'ls'"
- Exécuter la commande 'ls'
- Afficher "J'ai terminé!"Le processus n'est pas simple : c'est là qu'on voit apparaître les processus parents/enfants.
Il faut créer un processus enfant et le surveiller pour savoir quand il a fini, afin de pouvoir exécuter une nouvelle commande.- Ecrire le programme 2cmds.asm suivant :
section .data
message1 db 10
db "Je vais exécuter la commande 'ls' :", 10, 0 ; Message 1 à afficher
db 10
message1_len equ $-message1
message2 db 10
db "J'ai terminé !", 10, 0 ; Message 2 à afficher
db 10
message2_len equ $-message2
command db '/bin/ls', 0 ; Commande à exécuter
argv dq command, 0 ; Tableau d'arguments pour ls
envp dq 0 ; Tableau d'environnement vide
section .text
global _start
_start:
; Afficher le premier message
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
lea rsi, [message1] ; Adresse du message 1 à afficher
mov rdx, message1_len ; Longueur du message 1
syscall ; Appeler le système pour afficher le message
; Créer un nouveau processus
mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
syscall ; Appeler le système pour créer un processus enfant
; Vérifier si nous sommes dans le processus parent ou enfant
test rax, rax
jz execute_command ; Si RAX est 0, nous sommes dans le processus enfant
; Nous sommes dans le processus parent, attendre que le processus enfant termine
wait_child:
mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
xor rdi, rdi ; Attendre n'importe quel enfant
xor rsi, rsi ; Pas de statut
xor rdx, rdx ; Pas d'options
syscall ; Appeler le système
; Afficher le deuxième message
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
lea rsi, [message2] ; Adresse du message 2 à afficher
mov rdx, message2_len ; Longueur du message 2
syscall ; Appeler le système pour afficher le message
; Terminer le programme proprement
mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système pour terminer le programme
execute_command:
; Exécuter la commande 'ls' dans le processus enfant
mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
syscall ; Appeler le systèmeScénario No.3 :
- Exécuter la commande 'ls' une première fois
- Exécuter la commande 'ls' une seconde fois, lorsque l'exécution de la première commande est terminé.
Idem, il faut créer un processus enfant et le surveiller pour savoir quand il a fini, afin de pouvoir exécuter une nouvelle commande.- Ecrire le programme 2cmds.asm suivant :
section .data
command db '/bin/ls', 0 ; Commande à exécuter avec un caractère nul à la fin
argv dq command, 0 ; Tableau d'arguments pour ls (seulement le nom du programme)
envp dq 0 ; Tableau d'environnement vide
section .text
global _start
_start:
; Créer un nouveau processus
mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
syscall ; Appeler le système pour créer un processus enfant
; Vérifier si nous sommes dans le processus parent ou enfant
test rax, rax
jz execute_command ; Si RAX est 0, nous sommes dans le processus enfant
; Nous sommes dans le processus parent, attendre que le processus enfant termine
wait_child:
mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
xor rdi, rdi ; Attendre n'importe quel enfant
xor rsi, rsi ; Pas de statut
xor rdx, rdx ; Pas d'options
syscall ; Appeler le système
; Exécuter la commande une seconde fois dans le processus parent
execute_command:
mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
syscall ; Appeler le système
; Terminer le programme proprement
mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système
Scénario No.4 :
- Afficher "Je vais exécuter la commande 'ls' 2 fois : "
- Exécuter la commande 'ls' une première fois
- Exécuter la commande 'ls' une seconde fois, lorsque l'exécution de la première commande est terminé.
- Afficher "J'ai terminé"- Ecrire le programme 2cmds.asm suivant :
section .data
message1 db 10
db "Je vais exécuter la commande 'ls' 2 fois : ", 10 ; Message 1 à afficher
db 10
message1_len equ $-message1
message2 db 10
db "J'ai terminé !", 10, 0 ; Message 2 à afficher
db 10
message2_len equ $-message2
command db '/bin/ls', 0 ; Commande à exécuter
argv dq command, 0 ; Tableau d'arguments pour ls
envp dq 0 ; Tableau d'environnement vide
section .text
global _start
_start:
; Afficher le premier message
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
lea rsi, [message1] ; Adresse du message 1 à afficher
mov rdx, message1_len ; Longueur du message 1
syscall ; Appeler le système pour afficher le message
; Créer un premier processus enfant
mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
syscall ; Appeler le système pour créer un premier processus enfant
; Vérifier si nous sommes dans le processus parent ou enfant
test rax, rax
jz execute_second_ls ; Si RAX est 0, nous sommes dans le premier processus enfant
; Nous sommes dans le processus parent, attendre que le premier processus enfant termine
wait_first_child:
mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
xor rdi, rdi ; Attendre n'importe quel enfant
xor rsi, rsi ; Pas de statut
xor rdx, rdx ; Pas d'options
syscall ; Appeler le système
; Créer un deuxième processus enfant
mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
syscall ; Appeler le système pour créer un deuxième processus enfant
; Vérifier si nous sommes dans le processus parent ou deuxième enfant
test rax, rax
jz execute_second_ls ; Si RAX est 0, nous sommes dans le deuxième processus enfant
; Nous sommes dans le processus parent, attendre que le deuxième processus enfant termine
wait_second_child:
mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
xor rdi, rdi ; Attendre n'importe quel enfant
xor rsi, rsi ; Pas de statut
xor rdx, rdx ; Pas d'options
syscall ; Appeler le système
; Afficher le deuxième message
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; Écrire sur la sortie standard (1 = stdout)
lea rsi, [message2] ; Adresse du message 2 à afficher
mov rdx, message2_len ; Longueur du message 2
syscall ; Appeler le système pour afficher le message
; Terminer le programme proprement
mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système
execute_second_ls:
; Exécuter la commande 'ls' dans le processus enfant
mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
syscall ; Appeler le système
Scénario No.5 :
- Afficher le message "Looking for pkg, please wait..."
- Vérifier l'existence de la ressource "/usr/local/sbin/pkg" avec une conditionnelle :
--- Si /usr/local/sbin/pkg n'existe pas, alors installer pkg en exécutant la commande "pkg install -y pkg && pkg update"
- Afficher un dernier message "Welcome to this desktop installation script for FreeBSD!".Bien entendu, si "/usr/local/sbin/pkg" n'est pas présent (ce qui déclenche alors l'installation de pkg) alors il faut s'assurer que chaque processus est terminé avant de passer au suivant.
(là, ça commence à devenir plus trappu !)section .data
path db '/usr/local/sbin/pkg', 0 ; Définir le chemin à vérifier
command db '/bin/sh', 0 ; Utiliser le shell pour exécuter la commande
arg1 db '-c', 0 ; Argument pour exécuter une commande
arg2 db 'pkg install -y pkg && pkg update', 0 ; Commande à exécuter si le chemin n'existe pas
argv dq command, arg1, arg2, 0 ; Tableau d'arguments pour execve
envp dq 0 ; Tableau d'environnement vide
install_msg db 10
db '-------------------------------------------------', 10
db '| Looking for pkg, please wait...', 10 ; Message d'installation
db 10
install_msg_len equ $-install_msg
welcome_msg db 10
db '-------------------------------------------------', 10
db '| Welcome to this desktop installation program for FreeBSD!', 10
db 10
welcome_msg_len equ $-welcome_msg
section .bss
statbuf resb 144 ; Buffer pour l'appel système stat
section .text
global _start
_start:
; Afficher le message d'installation
mov rax, 4 ; Numéro de l'appel système pour sys_write sous FreeBSD
mov rdi, 1 ; Descripteur de fichier pour la sortie standard (STDOUT)
mov rsi, install_msg ; Adresse du message à afficher
mov rdx, install_msg_len ; Longueur du message
syscall
; Vérifier si le chemin existe en utilisant 'stat'
mov rax, 188 ; Numéro de l'appel système pour 'stat' sous FreeBSD
lea rdi, [path] ; Adresse du chemin
lea rsi, [statbuf] ; Adresse du buffer stat
syscall
; Vérifier si stat a réussi
cmp rax, 0
je path_exists ; Sauter si le chemin existe
; Si stat échoue, le chemin n'existe pas, exécuter la commande dans un processus enfant
mov rax, 2 ; Le numéro de système pour sys_fork sur FreeBSD
syscall ; Appeler le système pour créer un processus enfant
; Vérifier si nous sommes dans le processus parent ou enfant
test rax, rax
jz execute_command ; Si RAX est 0, nous sommes dans le processus enfant
; Nous sommes dans le processus parent, attendre que le processus enfant termine
wait_child:
mov rax, 7 ; Le numéro de système pour sys_wait4 sur FreeBSD
xor rdi, rdi ; Attendre n'importe quel enfant
xor rsi, rsi ; Pas de statut
xor rdx, rdx ; Pas d'options
syscall ; Appeler le système
; Afficher le message de bienvenue
mov rax, 4 ; Numéro de l'appel système pour sys_write sous FreeBSD
mov rdi, 1 ; Descripteur de fichier pour la sortie standard (STDOUT)
mov rsi, welcome_msg ; Adresse du message à afficher
mov rdx, welcome_msg_len ; Longueur du message
syscall
; Terminer le programme
mov rax, 1 ; Numéro de l'appel système pour sys_exit sous FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système
execute_command:
; Exécuter la commande 'pkg install -y pkg && pkg update' dans le processus enfant
mov rax, 59 ; Numéro de l'appel système pour sys_execve sous FreeBSD
lea rdi, [command] ; Premier argument pour sys_execve, le chemin du programme
lea rsi, [argv] ; Deuxième argument, le tableau d'arguments
lea rdx, [envp] ; Troisième argument, le tableau d'environnement
syscall ; Appeler le système
path_exists:
; Afficher le message de bienvenue
mov rax, 4 ; Numéro de l'appel système pour sys_write sous FreeBSD
mov rdi, 1 ; Descripteur de fichier pour la sortie standard (STDOUT)
mov rsi, welcome_msg ; Adresse du message à afficher
mov rdx, welcome_msg_len ; Longueur du message
syscall
; Terminer le programme
mov rax, 1 ; Numéro de l'appel système pour sys_exit sous FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système
votre commentaire -
Par majekla le 1 Mai 2024 à 12:49
Ici, c'est un peu plus simple, nous allons "simplement" vérifier qu'une ressource existe (fichier ou dossier, indépendamment de leurs différences).
D'abord de façon statique : le chemin de la ressource à vérifier est inscrit directement dans le programme.- Ecrivez le programme checkpath.asm suivant :
section .data
path db '/usr/local/sbin/pkg', 0 ; Define the path to check
path_exists_msg db 'Le chemin existe.', 10
path_exists_len equ $ - path_exists_msg
path_not_exists_msg db "Le chemin n'existe pas.", 10
path_not_exists_len equ $ - path_not_exists_msg
section .bss
statbuf resb 144 ; Buffer for stat system call
section .text
global _start
_start:
; Call 'stat' to check if the path exists
mov rax, 188 ; syscall number for 'stat' in FreeBSD
lea rdi, [path] ; Address of the path
lea rsi, [statbuf] ; Address of the stat buffer
syscall
; Check if stat succeeded
cmp rax, 0
je path_exists
; If stat fails, the path does not exist
mov rax, 4 ; syscall number for 'write'
mov rdi, 1 ; stdout
mov rsi, path_not_exists_msg
mov rdx, path_not_exists_len
syscall
jmp exit
path_exists:
mov rax, 4 ; syscall number for 'write'
mov rdi, 1 ; stdout
mov rsi, path_exists_msg
mov rdx, path_exists_len
syscall
exit:
mov rax, 1 ; syscall number for 'exit'
xor rdi, rdi ; Exit code 0
syscall- Assembler
nasm -f elf64 checkpath.asm
- Linker
ld checkpath.o -o checkpath
- Lancer le programme
./checkpath
A présent, de façon dynamique : le programme doit demander à l'utilisateur d'entrer le chemin d'une ressource.
L'utilisateur entre un chemin absolu, et le programme doit déterminer si ce qui est pointé existe ou non et répondre.- Ecrivez le programme checkpath.asm suivant :
section .data
prompt_msg db 'Entrez le chemin du fichier ou du dossier : ', 0
prompt_len equ $ - prompt_msg
path_exists_msg db 'Le chemin existe.', 10
path_exists_len equ $ - path_exists_msg
path_not_exists_msg db "Le chemin n'existe pas.", 10
path_not_exists_len equ $ - path_not_exists_msg
buffer_size equ 4096
section .bss
input_path resb buffer_size
statbuf resb 144
section .text
global _start
_start:
; Affiche le message de prompt
mov rax, 4 ; syscall number pour 'write'
mov rdi, 1 ; stdout
mov rsi, prompt_msg
mov rdx, prompt_len
syscall
; Lire le chemin du fichier de l'utilisateur
mov rax, 3 ; syscall number pour 'read'
mov rdi, 0 ; stdin
lea rsi, [input_path]
mov rdx, buffer_size
syscall
; Calculer la longueur de l'entrée et supprimer le caractère de nouvelle ligne
mov rdi, rax
dec rdi
mov byte [rsi+rdi], 0
; Appel de 'stat' pour vérifier si le chemin existe
mov rax, 188 ; syscall number pour 'stat'
lea rdi, [input_path]
lea rsi, [statbuf]
syscall
; Vérifier si stat a réussi
cmp rax, 0
je path_exists
; Si stat échoue, cela signifie que le chemin n'existe pas
mov rax, 4
mov rdi, 1
mov rsi, path_not_exists_msg
mov rdx, path_not_exists_len
syscall
jmp exit
path_exists:
mov rax, 4
mov rdi, 1
mov rsi, path_exists_msg
mov rdx, path_exists_len
syscall
exit:
mov rax, 1 ; syscall number pour 'exit'
xor rdi, rdi ; Code de sortie 0
syscall
votre commentaire -
Par majekla le 1 Mai 2024 à 12:04
Le but est simple, utiliser l'appel système stat pour vérifier si un fichier existe sur le serveur.
Le programme doit demander à l'utilisateur d'entrer le chemin absolu d'un fichier, puis doit vérifier s'il existe et donner une réponse.- Ecrivez le programme checkfile.asm suivant :
section .data
prompt_msg db 'Entrez le chemin du fichier : ', 0
prompt_len equ $ - prompt_msg
file_exists_msg db 'Le fichier existe.', 10
file_exists_len equ $ - file_exists_msg
file_not_exists_msg db "Le fichier n'existe pas.", 10
file_not_exists_len equ $ - file_not_exists_msg
buffer_size equ 4096 ; Taille du buffer pour lire le chemin du fichier
section .bss
input_path resb buffer_size ; Buffer pour stocker le chemin du fichier
statbuf resb 144 ; Espace réservé pour la structure stat
section .text
global _start
_start:
; Affiche le message de prompt
mov rax, 4 ; syscall number pour 'write'
mov rdi, 1 ; stdout
mov rsi, prompt_msg
mov rdx, prompt_len ; Longueur du message de prompt
syscall
; Lire le chemin du fichier de l'utilisateur
mov rax, 3 ; syscall number pour 'read'
mov rdi, 0 ; stdin
lea rsi, [input_path]
mov rdx, buffer_size ; Nombre maximal de caractères à lire
syscall
; Calculer la longueur de l'entrée et supprimer le caractère de nouvelle ligne
mov rdi, rax ; sauvegarder la longueur lue dans rdi
dec rdi ; ajuster pour le caractère de retour chariot
mov byte [rsi+rdi], 0 ; supprimer le caractère de nouvelle ligne
; Appel de 'stat' pour vérifier si le fichier existe
mov rax, 188 ; syscall number pour 'stat'
lea rdi, [input_path] ; Premier argument : pointeur vers le chemin du fichier
lea rsi, [statbuf] ; Deuxième argument : pointeur vers la structure stat
syscall
; Vérifier si stat a réussi
cmp rax, 0
jne file_not_found
mov rax, 4 ; syscall number pour 'write'
mov rdi, 1 ; stdout
mov rsi, file_exists_msg
mov rdx, file_exists_len ; Longueur du message fichier existe
syscall
jmp exit
file_not_found:
mov rax, 4 ; syscall number pour 'write'
mov rdi, 1 ; stdout
mov rsi, file_not_exists_msg
mov rdx, file_not_exists_len ; Longueur du message fichier non trouvé
syscall
exit:
mov rax, 1 ; syscall number pour 'exit'
xor rdi, rdi ; Code de sortie 0
syscall- Assembler
nasm -f elf64 checkfile.asm
- Linker
ld checkfile.o -o checkfile
- Lancer le programme
./checkfile
votre commentaire -
Par majekla le 30 Avril 2024 à 19:06
Le programme doit présenter un menu avec 2 options (afficher le mot "pomme" ou afficher le mot "fraise")
L'utilisateur doit répondre en entrant le numéro d'index de l'un des 2 choix.
En fonction du choix, le programme renvoie le choix fait.
Je rajoute un petit bonus : effacer le shell au début de l'exécution du programme
Plusieurs versions de ce programme sont proposées ici, de la plus basique à la plus complexe (avec boucle en cas d'erreur de l'utilisateur et rupture de boucle)- Ecrivez le programme menu.asm suivant :
section .data
clear_screen db 0x1b, '[2J', 0x1b, '[H' ; Séquence d'échappement ANSI pour effacer l'écran
menu_prompt db '---------------------------', 10
db '| Menu |', 10
db '---------------------------', 10
db 10
db '| [1] - Afficher "pomme"', 10
db '| [2] - Afficher "fraise"', 10
db 10
db '---------------------------', 10
db '| Faîtes votre choix : ', 0
menu_prompt_len equ $-menu_prompt
apple_message db 10
db 'Vous avez opté pour une pomme', 10
db 10
apple_len equ $-apple_message
strawberry_message db 10
db 'Vous avez opté pour une fraise', 10
db 10
strawberry_len equ $-strawberry_message
section .bss
user_choice resb 2 ; Réserve 2 octets pour le choix de l'utilisateur (caractère + newline)
section .text
global _start
_start:
; Effacer l'écran
mov rax, 4
mov rdi, 1
mov rsi, clear_screen
mov rdx, 4
syscall
; Afficher le menu
mov rax, 4
mov rdi, 1
mov rsi, menu_prompt
mov rdx, menu_prompt_len
syscall
; Lire le choix de l'utilisateur
mov rax, 3
mov rdi, 0
mov rsi, user_choice
mov rdx, 2
syscall
; Vérifier le choix de l'utilisateur
mov al, byte [user_choice]
cmp al, '1'
je display_apple
cmp al, '2'
je display_strawberry
; Si le choix n'est ni '1' ni '2', terminer le programme
jmp exit
display_apple:
; Afficher "pomme"
mov rax, 4
mov rdi, 1
mov rsi, apple_message
mov rdx, apple_len
syscall
jmp exit
display_strawberry:
; Afficher "fraise"
mov rax, 4
mov rdi, 1
mov rsi, strawberry_message
mov rdx, strawberry_len
syscall
jmp exit
exit:
; Terminer le programme
mov rax, 1
xor rdi, rdi
syscall- Assembler
nasm -f elf64 menu.asm
- Linker
ld menu.o -o menu
- Lancer le programme
./menu
Maintenant, comment gérer le fait que l'utilisateur se trompe et entre autre chose que 1 ou 2 ?
Eh bien, pour tout autre choix, il faut que le programme lui réponde qu'il n'a pas compris.
D'abord la version simple : le programme quitte après avoir affiché qu'il n'a pas compris.section .data
clear_screen db 0x1b, '[2J', 0x1b, '[H' ; Séquence d'échappement ANSI pour effacer l'écran
menu_prompt db '---------------------------', 10
db '| Menu |', 10
db '---------------------------', 10
db 10
db '| [1] - Afficher "pomme"', 10
db '| [2] - Afficher "fraise"', 10
db 10
db '---------------------------', 10
db '| Faîtes votre choix : ', 0
menu_prompt_len equ $-menu_prompt
apple_message db 10
db 'Vous avez opté pour une pomme', 10
db 10
apple_len equ $-apple_message
strawberry_message db 10
db 'Vous avez opté pour une fraise', 10
db 10
strawberry_len equ $-strawberry_message
invalid_choice_message db 10
db "Je n'ai pas compris votre choix", 10
db 10
invalid_choice_len equ $-invalid_choice_message
section .bss
user_choice resb 2 ; Réserve 2 octets pour le choix de l'utilisateur (caractère + newline)
section .text
global _start
_start:
; Effacer l'écran
mov rax, 4
mov rdi, 1
mov rsi, clear_screen
mov rdx, 4
syscall
; Afficher le menu
mov rax, 4
mov rdi, 1
mov rsi, menu_prompt
mov rdx, menu_prompt_len
syscall
; Lire le choix de l'utilisateur
mov rax, 3
mov rdi, 0
mov rsi, user_choice
mov rdx, 2
syscall
; Vérifier le choix de l'utilisateur
mov al, byte [user_choice]
cmp al, '1'
je display_apple
cmp al, '2'
je display_strawberry
; Si le choix n'est ni '1' ni '2', afficher un message d'erreur
mov rax, 4
mov rdi, 1
mov rsi, invalid_choice_message
mov rdx, invalid_choice_len
syscall
jmp exit
display_apple:
; Afficher "pomme"
mov rax, 4
mov rdi, 1
mov rsi, apple_message
mov rdx, apple_len
syscall
jmp exit
display_strawberry:
; Afficher "fraise"
mov rax, 4
mov rdi, 1
mov rsi, strawberry_message
mov rdx, strawberry_len
syscall
jmp exit
exit:
; Terminer le programme
mov rax, 1
xor rdi, rdi
syscallMaintenant, il faut pouvoir offrir une seconde (voir troisième) chance à l'utilisateur qui s'est trompé.
Nous allons donc introduire une boucle !section .data
clear_screen db 0x1b, '[2J', 0x1b, '[H' ; Séquence d'échappement ANSI pour effacer l'écran
menu_prompt db '---------------------------', 10
db '| Menu |', 10
db '---------------------------', 10
db 10
db '| [1] - Afficher "pomme"', 10
db '| [2] - Afficher "fraise"', 10
db 10
db '---------------------------', 10
db '| Faîtes votre choix : ', 0
menu_prompt_len equ $-menu_prompt
apple_message db 10
db 'Vous avez opté pour une pomme', 10
db 10
apple_len equ $-apple_message
strawberry_message db 10
db 'Vous avez opté pour une fraise', 10
db 10
strawberry_len equ $-strawberry_message
invalid_choice_message db 10
db "Je n'ai pas compris votre choix", 10
db "Veuillez faire un autre essai : ", 0
invalid_choice_len equ $-invalid_choice_message
section .bss
user_choice resb 2 ; Réserve 2 octets pour le choix de l'utilisateur (caractère + newline)
section .text
global _start
_start:
; Effacer l'écran
mov rax, 4
mov rdi, 1
mov rsi, clear_screen
mov rdx, 4
syscall
; Afficher le menu
mov rax, 4
mov rdi, 1
mov rsi, menu_prompt
mov rdx, menu_prompt_len
syscall
loop :
; Lire le choix de l'utilisateur
mov rax, 3
mov rdi, 0
mov rsi, user_choice
mov rdx, 2
syscall
; Vérifier le choix de l'utilisateur
mov al, byte [user_choice]
cmp al, '1'
je display_apple
cmp al, '2'
je display_strawberry
; Si le choix n'est ni '1' ni '2', afficher un message d'erreur et reboucler
mov rax, 4
mov rdi, 1
mov rsi, invalid_choice_message
mov rdx, invalid_choice_len
syscall
jmp loop
display_apple:
; Afficher "pomme"
mov rax, 4
mov rdi, 1
mov rsi, apple_message
mov rdx, apple_len
syscall
jmp exit
display_strawberry:
; Afficher "fraise"
mov rax, 4
mov rdi, 1
mov rsi, strawberry_message
mov rdx, strawberry_len
syscall
jmp exit
exit:
; Terminer le programme
mov rax, 1
xor rdi, rdi
syscallEnfin, la dernière version : si l'utilisateur se trompe 3 fois, le programme doit lui Ciao et quitter !
section .data
clear_screen db 0x1b, '[2J', 0x1b, '[H' ; Séquence d'échappement ANSI pour effacer l'écran
menu_prompt db '---------------------------', 10
db '| Menu |', 10
db '---------------------------', 10
db 10
db '| [1] - Afficher "pomme"', 10
db '| [2] - Afficher "fraise"', 10
db 10
db '---------------------------', 10
db '| Faîtes votre choix : ', 0
menu_prompt_len equ $-menu_prompt
apple_message db 10
db 'Vous avez opté pour une pomme', 10
db 10
apple_len equ $-apple_message
strawberry_message db 10
db 'Vous avez opté pour une fraise', 10
db 10
strawberry_len equ $-strawberry_message
invalid_choice_message db 10
db "Je n'ai pas compris votre choix", 10
db "Veuillez faire un autre essai : ", 0
invalid_choice_len equ $-invalid_choice_message
max_attempts_message db 10, 10
db 'Trop de tentatives invalides. Au revoir !', 10
db 10
max_attempts_len equ $-max_attempts_message
section .bss
user_choice resb 2 ; Réserve 2 octets pour le choix de l'utilisateur (caractère + newline)
attempt_count resb 1 ; Réserve 1 octet pour compter le nombre de tentatives invalides
section .text
global _start
_start:
mov byte [attempt_count], 0 ; Initialiser le compteur de tentatives invalides à 0
; Effacer l'écran
mov rax, 4
mov rdi, 1
mov rsi, clear_screen
mov rdx, 4
syscall
; Afficher le menu
mov rax, 4
mov rdi, 1
mov rsi, menu_prompt
mov rdx, menu_prompt_len
syscall
loop:
; Lire le choix de l'utilisateur
mov rax, 3
mov rdi, 0
mov rsi, user_choice
mov rdx, 2
syscall
; Vérifier le choix de l'utilisateur
mov al, byte [user_choice]
cmp al, '1'
je display_apple
cmp al, '2'
je display_strawberry
; Si le choix n'est ni '1' ni '2', afficher un message d'erreur et incrémenter le compteur de tentatives
mov rax, 4
mov rdi, 1
mov rsi, invalid_choice_message
mov rdx, invalid_choice_len
syscall
inc byte [attempt_count] ; Incrémenter le compteur de tentatives invalides
cmp byte [attempt_count], 3 ; Vérifier si le compteur a atteint 3
je max_attempts_reached ; Sauter à max_attempts_reached si c'est le cas
jmp loop ; Reboucler si le compteur n'a pas atteint 3
max_attempts_reached:
; Afficher le message de tentatives maximales atteintes
mov rax, 4
mov rdi, 1
mov rsi, max_attempts_message
mov rdx, max_attempts_len
syscall
jmp exit ; Quitter le programme
display_apple:
; Afficher "pomme"
mov rax, 4
mov rdi, 1
mov rsi, apple_message
mov rdx, apple_len
syscall
jmp exit
display_strawberry:
; Afficher "fraise"
mov rax, 4
mov rdi, 1
mov rsi, strawberry_message
mov rdx, strawberry_len
syscall
jmp exit
exit:
; Terminer le programme
mov rax, 1
xor rdi, rdi
syscall
votre commentaire -
Par majekla le 30 Avril 2024 à 17:58
Le programme doit poser une question (aimez-vous le chou ? [o/n]).
L'utilisateur doit répondre "o" pour oui ou "n" pour non.
Selon la réponse, le programme fait un petit commentaire !- Ecrivez le programme question.asm suivant :
section .data
question db 'Aimez-vous le chou ? [o/n] ', 0
question_len equ $-question
like_message db 'moi aussi', 10 ; Message si la réponse est 'o'
like_len equ $-like_message
dislike_message db 'vous avez tort !', 10 ; Message si la réponse est 'n'
dislike_len equ $-dislike_message
section .bss
response resb 2 ; Réserve 2 octets pour la réponse (caractère + newline)
section .text
global _start
_start:
; Afficher la question
mov rax, 4
mov rdi, 1
mov rsi, question
mov rdx, question_len
syscall
; Lire la réponse de l'utilisateur
mov rax, 3
mov rdi, 0
mov rsi, response
mov rdx, 2
syscall
; Vérifier si la réponse est 'o' ou 'n'
cmp byte [response], 'o'
je like_response
cmp byte [response], 'n'
je dislike_response
; Si la réponse n'est ni 'o' ni 'n', terminer le programme
jmp exit
like_response:
; Afficher "moi aussi"
mov rax, 4
mov rdi, 1
mov rsi, like_message
mov rdx, like_len
syscall
jmp exit
dislike_response:
; Afficher "vous avez tort !"
mov rax, 4
mov rdi, 1
mov rsi, dislike_message
mov rdx, dislike_len
syscall
jmp exit
exit:
; Terminer le programme
mov rax, 1
xor rdi, rdi
syscall- Assembler
nasm -f elf64 question.asm -o question.o
- Linker
ld question.o -o question
- Lancer le programme
./question
Nous pouvons également définir un choix par défaut, au cas où l'utilisateur ne ferait que taper sur la touche ENTRER (une "entrée vide") au lieu d'écrire "o" ou "n".
Considérons que s'il fait cela, cela revient à répondre "o" (oui).
Cela revient à dire au programme que s'il reçoit le code 10 (nouvelle ligne), il doit exécuter like_response (o)section .data
question db 'Aimez-vous le chou ? [o/n] ', 0
question_len equ $-question
like_message db 'moi aussi', 10 ; Message si la réponse est 'o' ou entrée vide
like_len equ $-like_message
dislike_message db 'vous avez tort !', 10 ; Message si la réponse est 'n'
dislike_len equ $-dislike_message
section .bss
response resb 2 ; Réserve 2 octets pour la réponse (caractère + newline)
section .text
global _start
_start:
; Afficher la question
mov rax, 4
mov rdi, 1
mov rsi, question
mov rdx, question_len
syscall
; Lire la réponse de l'utilisateur
mov rax, 3
mov rdi, 0
mov rsi, response
mov rdx, 2
syscall
; Vérifier si la réponse est 'o', 'n' ou une entrée vide
cmp byte [response], 'o'
je like_response
cmp byte [response], 'n'
je dislike_response
cmp byte [response], 10 ; Vérifier si la réponse est une entrée vide (newline)
je like_response
; Si la réponse n'est ni 'o', ni 'n', ni une entrée vide, terminer le programme
jmp exit
like_response:
; Afficher "moi aussi"
mov rax, 4
mov rdi, 1
mov rsi, like_message
mov rdx, like_len
syscall
jmp exit
dislike_response:
; Afficher "vous avez tort !"
mov rax, 4
mov rdi, 1
mov rsi, dislike_message
mov rdx, dislike_len
syscall
jmp exit
exit:
; Terminer le programme
mov rax, 1
xor rdi, rdi
syscallNous allons maintenant aller encore un peu plus loin et gérer la casse !
Il faut que si l'utilisateur écrit O en majuscule, le programme le prenne pour un o minuscule.. Idem pour N
Toujours avec l'option par défaut sur o.section .data
question db 'Aimez-vous le chou ? [o/n] ', 0
question_len equ $-question
like_message db 'moi aussi', 10 ; Message si la réponse est 'o' ou entrée vide
like_len equ $-like_message
dislike_message db 'vous avez tort !', 10 ; Message si la réponse est 'n'
dislike_len equ $-dislike_message
section .bss
response resb 2 ; Réserve 2 octets pour la réponse (caractère + newline)
section .text
global _start
_start:
; Afficher la question
mov rax, 4
mov rdi, 1
mov rsi, question
mov rdx, question_len
syscall
; Lire la réponse de l'utilisateur
mov rax, 3
mov rdi, 0
mov rsi, response
mov rdx, 2
syscall
; Convertir la réponse en minuscule pour gérer la casse
mov al, byte [response]
call tolower
; Vérifier si la réponse est 'o', 'n' ou une entrée vide
cmp al, 'o'
je like_response
cmp al, 'n'
je dislike_response
cmp al, 10 ; Vérifier si la réponse est une entrée vide (newline)
je like_response
; Si la réponse n'est ni 'o', ni 'n', ni une entrée vide, terminer le programme
jmp exit
like_response:
; Afficher "moi aussi"
mov rax, 4
mov rdi, 1
mov rsi, like_message
mov rdx, like_len
syscall
jmp exit
dislike_response:
; Afficher "vous avez tort !"
mov rax, 4
mov rdi, 1
mov rsi, dislike_message
mov rdx, dislike_len
syscall
jmp exit
exit:
; Terminer le programme
mov rax, 1
xor rdi, rdi
syscall
tolower:
cmp al, 'A'
jb done
cmp al, 'Z'
ja done
add al, 32
done:
ret
votre commentaire -
Par majekla le 30 Avril 2024 à 12:43
Ici, nous allons simplement afficher sur la console le contenu du fichier /tmp/test créé précédemment.
- Créer le programme readfile.asm :
section .data
filename db '/tmp/test', 0 ; Nom du fichier à lire
buffer db 256 dup(0) ; Buffer pour stocker les données lues
bufferSize equ $-buffer ; Taille du buffer
section .bss
fileDescriptor resb 1 ; Descripteur de fichier
section .text
global _start
_start:
; Ouvrir le fichier en lecture seule
mov rax, 5 ; sys_open (FreeBSD)
lea rdi, [filename] ; Chemin du fichier
xor rsi, rsi ; Flags (O_RDONLY)
xor rdx, rdx ; Mode (pas utilisé en lecture)
syscall
mov [fileDescriptor], rax ; Sauvegarder le descripteur de fichier
read_loop:
; Lire le contenu du fichier
mov rax, 3 ; sys_read (FreeBSD)
mov rdi, [fileDescriptor] ; Descripteur de fichier
lea rsi, [buffer] ; Buffer pour recevoir les données
mov rdx, bufferSize ; Nombre d'octets à lire
syscall
test rax, rax ; Vérifier si la lecture a réussi
js read_error ; Si rax est négatif, il y a eu une erreur de lecture
jz end_read ; Si rax est zéro, nous avons atteint la fin du fichier
; Écrire le contenu lu sur stdout
mov rdi, 1 ; Descripteur de fichier pour stdout
mov rdx, rax ; Utiliser la valeur retournée par sys_read pour le nombre d'octets à écrire
mov rax, 4 ; sys_write (FreeBSD)
mov rsi, buffer ; Adresse du début du buffer
syscall
jmp read_loop ; Répéter la lecture jusqu'à ce que nous atteignions la fin du fichier
read_error:
; Gérer l'erreur de lecture
; Vous pouvez insérer ici le code pour gérer les erreurs de lecture
; Par exemple, afficher un message d'erreur et sortir du programme
jmp end_program
end_read:
; Fermer le fichier
mov rax, 6 ; sys_close (FreeBSD)
mov rdi, [fileDescriptor] ; Descripteur de fichier
syscall
end_program:
; Terminer le programme
mov rax, 1 ; sys_exit (FreeBSD)
xor rdi, rdi ; Code de sortie 0
syscall- Assembler
nasm -f elf64 readfile.asm -o readfile.o
- Linker
ld readfile.o -o readfile
- Lancer le programme
./readfile
votre commentaire -
Par majekla le 30 Avril 2024 à 12:34
Voici la liste des numéros d'appels système sur FreeBSD 14.
Il sont obtenus en décortiquant le fichier /usr/src/sys/kern/init_sysent.c
Ces numéros sont essentiels pour écrire des programmes en assembleur sous FreeBSD.0. syscall - nosys : Une instruction système non implémentée.
1. exit - sys_exit : Termine l'exécution du processus courant.
2. fork - sys_fork : Crée un nouveau processus en dupliquant le processus appelant.
3. read - sys_read : Lit des données à partir d'un descripteur de fichier.
4. write - sys_write : Écrit des données vers un descripteur de fichier.
5. open - sys_open : Ouvre un fichier ou un périphérique.
6. close - sys_close : Ferme un descripteur de fichier.
7. wait4 - sys_wait4 : Attend la terminaison d'un processus enfant.
8. old creat - creat : Crée un nouveau fichier ou réinitialise les attributs d'un fichier existant.
9. link - sys_link : Crée un lien vers un fichier.
10. unlink - sys_unlink : Supprime un lien vers un fichier.
11. obsolete execv - nosys : Une ancienne version de la fonction execv, non prise en charge.
12. chdir - sys_chdir : Change le répertoire de travail courant.
13. fchdir - sys_fchdir : Change le répertoire de travail courant via un descripteur de fichier.
14. freebsd11 mknod - mknod : Crée un nœud de périphérique spécial ou un fichier ordinaire.
15. chmod - sys_chmod : Modifie les permissions d'un fichier.
16. chown - sys_chown : Modifie le propriétaire et le groupe d'un fichier.
17. break - sys_break : Augmente la taille du segment de données.
18. freebsd4 getfsstat - getfsstat : Récupère des informations sur les systèmes de fichiers montés.
19. old lseek - lseek : Déplace le pointeur de fichier pour un descripteur de fichier donné.
20. getpid - sys_getpid : Récupère l'identifiant du processus appelant.
21. mount - sys_mount : Montre un système de fichiers.
22. unmount - sys_unmount : Démonte un système de fichiers.
23. setuid - sys_setuid : Change l'identifiant de l'utilisateur effectif.
24. getuid - sys_getuid : Récupère l'identifiant de l'utilisateur réel.
25. geteuid - sys_geteuid : Récupère l'identifiant de l'utilisateur effectif.
26. ptrace - sys_ptrace : Permet à un processus parent de surveiller et de contrôler un processus enfant.
27. recvmsg - sys_recvmsg : Reçoit un message sur un socket.
28. sendmsg - sys_sendmsg : Envoie un message sur un socket.
29. recvfrom - sys_recvfrom : Reçoit un message sur un socket à partir d'une adresse spécifiée.
30. accept - sys_accept : Accepte une connexion sur un socket.
31. getpeername - sys_getpeername : Récupère l'adresse de l'autre extrémité d'une connexion.
32. getsockname - sys_getsockname : Récupère l'adresse locale d'un socket.
33. access - sys_access : Vérifie les permissions d'accès à un fichier.
34. chflags - sys_chflags : Modifie les drapeaux d'un fichier.
35. fchflags - sys_fchflags : Modifie les drapeaux d'un fichier via un descripteur de fichier.
36. sync - sys_sync : Force l'écriture des données en mémoire sur le disque.
37. kill - sys_kill : Envoie un signal à un processus ou à un groupe de processus.
38. old stat - stat : Obtient des informations sur un fichier.
39. getppid - sys_getppid : Récupère l'identifiant du processus parent.
40. old lstat - lstat : Obtient des informations sur un fichier sans suivre les liens symboliques.
41. dup - sys_dup : Duplique un descripteur de fichier.
42. freebsd10 pipe - pipe : Crée un tube pour la communication inter-processus.
43. getegid - sys_getegid : Récupère l'identifiant du groupe effectif.
44. profil - sys_profil : Permet le profilage du processus.
45. ktrace - sys_ktrace : Permet la surveillance et le traçage des appels système.
46. old sigaction - sigaction : Associe une nouvelle action à un signal.
47. getgid - sys_getgid : Récupère l'identifiant du groupe réel.
48. old sigprocmask - sigprocmask : Modifie le masque de signaux du processus.
49. getlogin - sys_getlogin : Récupère le nom de connexion de l'utilisateur.
50. setlogin - sys_setlogin : Modifie le nom de connexion de l'utilisateur.
51. acct - sys_acct : Active ou désactive la collecte de statistiques d'utilisation des ressources pour un utilisateur.
52. old sigpending - sigpending : Obsolete, gestion des signaux en attente.
53. sigaltstack - sys_sigaltstack : Modifie la pile de signaux du processus.
54. ioctl - sys_ioctl : Contrôle les périphériques et d'autres opérations spéciales.
55. reboot - sys_reboot : Redémarre ou éteint le système.
56. revoke - sys_revoke : Révoque l'accès à un fichier ou un périphérique.
57. symlink - sys_symlink : Crée un lien symbolique vers un fichier.
58. readlink - sys_readlink : Lit la cible d'un lien symbolique.
59. execve - sys_execve : Exécute un programme.
60. umask - sys_umask : Modifie le masque de création de fichiers.
61. chroot - sys_chroot : Change le répertoire racine du processus.
62. old fstat - fstat : Obtient des informations sur un descripteur de fichier.
63. old getkerninfo - getkerninfo : Obsolete, récupère des informations sur le noyau.
64. old getpagesize - getpagesize : Obsolete, récupère la taille d'une page mémoire.
65. msync - sys_msync : Synchronise une région de mémoire avec le fichier associé.
66. vfork - sys_vfork : Crée un nouveau processus sans copier l'espace d'adressage.
67. obsolete vread - nosys : Une ancienne version de la fonction de lecture, non prise en charge.
68. obsolete vwrite - nosys : Une ancienne version de la fonction d'écriture, non prise en charge.
69. sbrk - sys_sbrk : Modifie la taille du segment de données du processus.
70. sstk - sys_sstk : Modifie la taille de la pile du processus.
71. old mmap - mmap : Alloue de la mémoire et associe un fichier à une région de mémoire.
72. freebsd11 vadvise - vadvise : Conseille sur le comportement d'accès à une région de mémoire virtuelle.
73. munmap - sys_munmap : Libère une région de mémoire allouée précédemment via mmap.
74. mprotect - sys_mprotect : Change les protections d'accès à une région de mémoire.
75. madvise - sys_madvise : Donne des conseils sur l'utilisation de la mémoire.
76. obsolete vhangup - nosys : Une ancienne fonction pour terminer un processus, non prise en charge.
77. obsolete vlimit - nosys : Obsolete, pour définir les limites de ressources d'un processus.
78. mincore - sys_mincore : Détermine si les pages de mémoire sont actuellement résidentes en mémoire physique.
79. getgroups - sys_getgroups : Récupère la liste des identifiants de groupe auxquels appartient un processus.
80. setgroups - sys_setgroups : Modifie la liste des identifiants de groupe auxquels appartient un processus.
81. getpgrp - sys_getpgrp : Récupère l'identifiant de groupe du processus appelant.
82. setpgid - sys_setpgid : Modifie le groupe de processus d'un processus.
83. setitimer - sys_setitimer : Définit les paramètres d'une minuterie d'intervalle.
84. old wait - wait : Obsolete, attend la fin de l'exécution d'un processus enfant.
85. swapon - sys_swapon : Active ou désactive un espace de swap.
86. getitimer - sys_getitimer : Récupère les paramètres d'une minuterie d'intervalle.
87. old gethostname - gethostname : Obsolete, récupère le nom de l'hôte.
88. old sethostname - sethostname : Obsolete, définie le nom de l'hôte.
89. getdtablesize - sys_getdtablesize : Récupère la taille de la table des descripteurs de fichiers.
90. dup2 - sys_dup2 : Duplique un descripteur de fichier vers un autre.
91. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
92. fcntl - sys_fcntl : Effectue diverses opérations sur un descripteur de fichier.
93. select - sys_select : Surveille un ensemble de descripteurs de fichiers pour l'activité.
94. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
95. fsync - sys_fsync : Synchronise les données d'un fichier avec le périphérique de stockage.
96. setpriority - sys_setpriority : Modifie la priorité d'un processus.
97. socket - sys_socket : Crée un point de communication de type socket.
98. connect - sys_connect : Établit une connexion vers une adresse spécifiée.
99. old accept - accept : Obsolete, accepte une connexion sur un socket.
100. getpriority - sys_getpriority : Récupère la priorité d'un processus.
101. old send - send : Obsolete, envoie des données sur un socket.
102. old recv - recv : Obsolete, reçoit des données d'un socket.
103. old sigreturn - sigreturn : Obsolete, retourne d'une routine de traitement de signal.
104. bind - sys_bind : Lie une adresse à un socket.
105. setsockopt - sys_setsockopt : Définit les options pour un socket.
106. listen - sys_listen : Place un socket en mode écoute pour les connexions entrantes.
107. obsolete vtimes - nosys : Obsolete, récupère les temps de processus, non pris en charge.
108. old sigvec - sigvec : Obsolete, manipule les vecteurs de signal.
109. old sigblock - sigblock : Obsolete, bloque les signaux spécifiés.
110. old sigsetmask - sigsetmask : Obsolete, modifie le masque de signaux du processus.
111. old sigsuspend - sigsuspend : Obsolete, suspend l'exécution du processus jusqu'à ce qu'un signal soit reçu.
112. old sigstack - sigstack : Obsolete, définit une nouvelle pile de signaux.
113. old recvmsg - recvmsg : Obsolete, reçoit des messages à partir d'un socket.
114. old sendmsg - sendmsg : Obsolete, envoie des messages sur un socket.
115. obsolete vtrace - nosys : Obsolete, trace l'exécution d'un processus, non pris en charge.
116. gettimeofday - sys_gettimeofday : Récupère la date et l'heure actuelles.
117. getrusage - sys_getrusage : Récupère les statistiques d'utilisation des ressources pour un processus ou un groupe de processus.
118. getsockopt - sys_getsockopt : Récupère les options pour un socket.
119. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
120. readv - sys_readv : Lit à partir d'un descripteur de fichier vers un tableau de tampons.
121. writev - sys_writev : Écrit à partir d'un tableau de tampons vers un descripteur de fichier.
122. settimeofday - sys_settimeofday : Définit la date et l'heure du système.
123. fchown - sys_fchown : Modifie le propriétaire et le groupe d'un fichier via un descripteur de fichier.
124. fchmod - sys_fchmod : Modifie les permissions d'un fichier via un descripteur de fichier.
125. old recvfrom - recvfrom : Obsolete, reçoit des données à partir d'un socket avec des informations d'adresse.
126. setreuid - sys_setreuid : Modifie les identifiants d'utilisateur réel et effectif.
127. setregid - sys_setregid : Modifie les identifiants de groupe réel et effectif.
128. rename - sys_rename : Renomme un fichier.
129. old truncate - truncate : Obsolete, ajuste la taille d'un fichier.
130. old ftruncate - ftruncate : Obsolete, ajuste la taille d'un fichier via un descripteur de fichier.
131. flock - sys_flock : Verrouille ou déverrouille un fichier.
132. mkfifo - sys_mkfifo : Crée un tube nommé (fifo).
133. sendto - sys_sendto : Envoie des données sur un socket vers une adresse spécifiée.
134. shutdown - sys_shutdown : Ferme une partie d'un socket.
135. socketpair - sys_socketpair : Crée une paire de sockets connectés.
136. mkdir - sys_mkdir : Crée un répertoire.
137. rmdir - sys_rmdir : Supprime un répertoire vide.
138. utimes - sys_utimes : Modifie les temps d'accès et de modification d'un fichier.
139. obsolete sigreturn - nosys : Obsolete, retourne d'une routine de traitement de signal, non pris en charge.
140. adjtime - sys_adjtime : Ajuste l'horloge du système.
141. old getpeername - getpeername : Obsolete, récupère l'adresse de l'autre extrémité d'une connexion.
142. old gethostid - gethostid : Obsolete, récupère l'identifiant de l'hôte.
143. old sethostid - sethostid : Obsolete, définie l'identifiant de l'hôte.
144. old getrlimit - getrlimit : Obsolete, récupère les limites de ressources du processus.
145. old setrlimit - setrlimit : Obsolete, définit les limites de ressources du processus.
146. old killpg - killpg : Obsolete, envoie un signal à un groupe de processus.
147. setsid - sys_setsid : Crée une nouvelle session de processus.
148. quotactl - sys_quotactl : Modifie les quotas de disque.
149. old quota - quota : Obsolete, interagit avec les quotas de disque.
150. old getsockname - getsockname : Obsolete, récupère l'adresse locale d'un socket.
151. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
152. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
153. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
154. nlm_syscall - lkmressys : Système d'appel pour le verrouillage réseau (NLM).
155. nfssvc - lkmressys : Système d'appel pour les services NFS.
156. old getdirentries - getdirentries : Obsolete, lit les entrées de répertoire dans un descripteur de fichier.
157. freebsd4 statfs - statfs : Obtient des informations sur le système de fichiers.
158. freebsd4 fstatfs - fstatfs : Obtient des informations sur un descripteur de fichier système de fichiers.
159. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
160. lgetfh - sys_lgetfh : Récupère un handle de fichier local.
161. getfh - sys_getfh : Récupère un handle de fichier.
162. freebsd4 getdomainname - getdomainname : Récupère le nom de domaine Internet du système.
163. freebsd4 setdomainname - setdomainname : Définit le nom de domaine Internet du système.
164. freebsd4 uname - uname : Récupère des informations sur le système d'exploitation et le matériel.
165. sysarch - sysarch : Interface pour des appels système spécifiques à l'architecture.
166. rtprio - sys_rtprio : Définit la priorité en temps réel d'un processus.
167. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
168. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
169. semsys - lkmressys : Système d'appel pour les opérations de sémaphore.
170. msgsys - lkmressys : Système d'appel pour les opérations de file de messages.
171. shmsys - lkmressys : Système d'appel pour les opérations de mémoire partagée.
172. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
173. freebsd6 pread - pread : Lit à partir d'un descripteur de fichier avec un décalage.
174. freebsd6 pwrite - pwrite : Écrit vers un descripteur de fichier avec un décalage.
175. setfib - sys_setfib : Définit le numéro de la table de routage pour le processus en cours.
176. ntp_adjtime - sys_ntp_adjtime : Ajuste l'horloge système avec les informations NTP.
177. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
178. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
179. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
180. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
181. setgid - sys_setgid : Modifie l'identifiant de groupe effectif.
182. setegid - sys_setegid : Modifie l'identifiant de groupe effectif et supplémentaire.
183. seteuid - sys_seteuid : Modifie l'identifiant de l'utilisateur effectif.
184. obsolete lfs_bmapv - nosys : Obsolete, non pris en charge.
185. obsolete lfs_markv - nosys : Obsolete, non pris en charge.
186. obsolete lfs_segclean - nosys : Obsolete, non pris en charge.
187. obsolete lfs_segwait - nosys : Obsolete, non pris en charge.
188. freebsd11 stat - stat : Obtient des informations sur un fichier.
189. freebsd11 fstat - fstat : Obtient des informations sur un descripteur de fichier.
190. freebsd11 lstat - lstat : Obtient des informations sur un fichier sans suivre les liens symboliques.
191. pathconf - sys_pathconf : Obtient des configurations de chemin système.
192. fpathconf - sys_fpathconf : Obtient des configurations de chemin pour un descripteur de fichier.
193. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
194. getrlimit - sys_getrlimit : Récupère les limites de ressources du processus.
195. setrlimit - sys_setrlimit : Définit les limites de ressources du processus.
196. freebsd11 getdirentries - getdirentries : Lit les entrées de répertoire dans un descripteur de fichier.
197. freebsd6 mmap - mmap : Alloue de la mémoire et associe un fichier à une région de mémoire.
198. __syscall - nosys : Appel système non spécifié.
199. freebsd6 lseek - lseek : Déplace le pointeur de fichier pour un descripteur de fichier donné.
200. freebsd6 truncate - truncate : Ajuste la taille d'un fichier.
201. freebsd6 ftruncate - ftruncate : Ajuste la taille d'un fichier via un descripteur de fichier.
202. __sysctl - sys___sysctl : Contrôle les paramètres du noyau à l'exécution.
203. mlock - sys_mlock : Verrouille une région de mémoire dans la mémoire principale.
204. munlock - sys_munlock : Déverrouille une région de mémoire précédemment verrouillée.
205. undelete - sys_undelete : Restaure un fichier supprimé.
206. futimes - sys_futimes : Modifie les temps d'accès et de modification d'un fichier via un descripteur de fichier.
207. getpgid - sys_getpgid : Récupère l'identifiant de groupe du processus parent.
208. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
209. poll - sys_poll : Surveille un ensemble de descripteurs de fichiers pour l'activité.
210-219. lkmnosys - lkmnosys : Système d'appel réservé pour une utilisation future, non implémenté.
220. freebsd7 __semctl - lkmressys : Contrôle les opérations sur les sémaphores.
221. semget - lkmressys : Obtient un ensemble de sémaphores.
222. semop - lkmressys : Effectue des opérations sur un ensemble de sémaphores.
223. obsolete semconfig - nosys : Obsolete, non pris en charge.
224. freebsd7 msgctl - lkmressys : Contrôle les opérations sur les files de messages.
225. msgget - lkmressys : Obtient une file de messages.
226. msgsnd - lkmressys : Envoie un message à une file de messages.
227. msgrcv - lkmressys : Reçoit un message d'une file de messages.
228. shmat - lkmressys : Attache un segment de mémoire partagée.
229. freebsd7 shmctl - lkmressys : Contrôle les opérations sur les segments de mémoire partagée.
230. shmdt - lkmressys : Détache un segment de mémoire partagée.
231. shmget - lkmressys : Alloue un segment de mémoire partagée.
232. clock_gettime - sys_clock_gettime : Récupère l'heure actuelle selon une horloge spécifiée.
233. clock_settime - sys_clock_settime : Modifie l'heure actuelle selon une horloge spécifiée.
234. clock_getres - sys_clock_getres : Récupère la résolution de l'horloge spécifiée.
235. ktimer_create - sys_ktimer_create : Crée un minuteur à haute résolution.
236. ktimer_delete - sys_ktimer_delete : Supprime un minuteur à haute résolution.
237. ktimer_settime - sys_ktimer_settime : Définit le temps d'expiration pour un minuteur à haute résolution.
238. ktimer_gettime - sys_ktimer_gettime : Récupère le temps restant avant l'expiration d'un minuteur à haute résolution.
239. ktimer_getoverrun - sys_ktimer_getoverrun : Récupère le nombre de débordements pour un minuteur à haute résolution.
240. nanosleep - sys_nanosleep : Suspend l'exécution du processus pendant une durée spécifiée.
241-243. Fournissent des fonctionnalités liées à l'horloge et au temps.
244. clock_nanosleep - sys_clock_nanosleep : Suspend l'exécution du processus jusqu'à ce que l'horloge spécifiée atteigne une certaine valeur.
245-246. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
247. clock_getcpuclockid2 - sys_clock_getcpuclockid2 : Récupère l'horloge CPU associée à un processus.
248. ntp_gettime - sys_ntp_gettime : Récupère l'heure et l'état de la synchronisation NTP.
249. reserved for local use - nosys : Réservé pour une utilisation locale, non implémenté.
250. minherit - sys_minherit : Modifie l'héritage de mémoire pour une région de mémoire virtuelle.
251. rfork - sys_rfork : Crée un nouveau processus léger (thread).
252. obsolete openbsd_poll - nosys : Obsolete, non pris en charge.
253. issetugid - sys_issetugid : Vérifie si le processus s'exécute sous un ID utilisateur ou de groupe non sûr.
254. lchown - sys_lchown : Modifie le propriétaire et le groupe d'un fichier ou d'un lien symbolique.
255. aio_read - sys_aio_read : Lit de manière asynchrone à partir d'un descripteur de fichier.
256. aio_write - sys_aio_write : Écrit de manière asynchrone vers un descripteur de fichier.
257. lio_listio - sys_lio_listio : Effectue une liste d'opérations I/O asynchrones.
258-270. Réservé pour une utilisation locale, non implémenté.
271-300. Fonctionnalités spécifiques au système d'exploitation ou réservées à des utilisations particulières.
301. modstat - sys_modstat : Obtient des informations sur les modules chargés dans le noyau.
302. modfnext - sys_modfnext : Obtient le prochain fichier objet de module dans la liste.
303. modfind - sys_modfind : Trouve un module noyau par son nom.
304. kldload - sys_kldload : Charge un module noyau.
305. kldunload - sys_kldunload : Décharge un module noyau.
306. kldfind - sys_kldfind : Trouve un module noyau par son adresse.
307. kldnext - sys_kldnext : Obtient le prochain module noyau dans la liste.
308. kldstat - sys_kldstat : Obtient des informations sur les modules noyau.
309. kldfirstmod - sys_kldfirstmod : Obtient le premier module noyau dans la liste.
310. getsid - sys_getsid : Obtient l'identifiant de session du processus spécifié.
311. setresuid - sys_setresuid : Modifie les identifiants d'utilisateur réels, effectifs et sauvegardés.
312. setresgid - sys_setresgid : Modifie les identifiants de groupe réels, effectifs et sauvegardés.
313. obsolete signanosleep - nosys : Obsolete, non pris en charge.
314. aio_return - sys_aio_return : Obtient le résultat d'une opération I/O asynchrone.
315. aio_suspend - sys_aio_suspend : Suspend le processus jusqu'à ce qu'une ou plusieurs opérations I/O asynchrones soient terminées.
316. aio_cancel - sys_aio_cancel : Annule une opération I/O asynchrone en attente.
317. aio_error - sys_aio_error : Obtient l'état d'une opération I/O asynchrone.
318-320. Appels système pour les opérations I/O asynchrones.
321. yield - sys_yield : Passe la main à un autre thread exécutable sur le même processeur.
322-323. Obsolete, non pris en charge.
324. mlockall - sys_mlockall : Verrouille toutes les pages en mémoire physique.
325. munlockall - sys_munlockall : Déverrouille toutes les pages précédemment verrouillées en mémoire physique.
326. __getcwd - sys___getcwd : Obtient le répertoire de travail actuel du processus.
327-334. Fonctionnalités liées à la planification des processus.
335. utrace - sys_utrace : Système de trace utilisateur.
336. freebsd4 sendfile - sendfile : Envoie un fichier via une socket.
337. kldsym - sys_kldsym : Obsolete, non pris en charge.
338. jail - sys_jail : Crée une prison pour les processus.
339. nnpfs_syscall - nnpfs_syscall : Système de fichiers non pris en charge.
340-346. Fonctionnalités liées aux signaux et à leur manipulation.
347-354. Fonctionnalités relatives aux listes de contrôle d'accès (ACL) étendues.
355-358. Fonctionnalités relatives aux attributs étendus des fichiers.
359. aio_waitcomplete - aio_waitcomplete : Attend la complétion d'opérations I/O asynchrones.
360-361. Obtient les identifiants d'utilisateur et de groupe réels, effectifs et sauvegardés.
362. kqueue - kqueue : Crée une file d'événements pour la surveillance des événements du noyau.
363. freebsd11 kevent - kevent : Obtient des événements à partir d'une file d'événements.
votre commentaire -
Par majekla le 29 Avril 2024 à 17:50
De la même façon que l'on a fait apparaître 'hello world' dans une fenêtre graphique avec gtk, faisons apparaître un bouton à cliquer 'OK'.
Attention, ici l'action du clic n'est pas définie.
- Créer le programme boutonOK.asm :section .data
window_title db "Cliquez-moi", 0
button_label db "OK", 0
section .text
global main
extern gtk_init, gtk_main, gtk_widget_show_all, gtk_window_new, gtk_window_set_title, gtk_button_new_with_label, gtk_container_add
main:
; Initialiser GTK
push rbp
mov rbp, rsp
sub rsp, 16
mov qword [rbp-16], 0 ; argc
mov qword [rbp-8], 0 ; argv
lea rdi, [rbp-16] ; argc
lea rsi, [rbp-8] ; argv
call gtk_init
; Créer la fenêtre
mov edi, 0 ; GTK_WINDOW_TOPLEVEL
call gtk_window_new
mov rbx, rax ; Sauvegarder le pointeur de fenêtre
; Définir le titre de la fenêtre
mov rdi, rbx
mov rsi, window_title
call gtk_window_set_title
; Créer le bouton
mov rdi, button_label
call gtk_button_new_with_label
mov r12, rax ; Sauvegarder le pointeur du bouton
; Ajouter le bouton à la fenêtre
mov rdi, rbx
mov rsi, r12
call gtk_container_add
; Afficher la fenêtre
mov rdi, rbx
call gtk_widget_show_all
; Exécuter la boucle principale de GTK
call gtk_main
; Nettoyer la pile
leave
ret
section .note.GNU-stack noalloc noexec nowrite progbits- Assembler
nasm -f elf64 boutonOK.asm -o boutonOK.o
- Linker
gcc -o boutonOK boutonOK.o `pkg-config --cflags --libs gtk+-3.0`
- Lancer le programme
./boutonOK
votre commentaire -
Par majekla le 29 Avril 2024 à 17:17
Oui, on peut manipuler gtk en assembleur, même si c'est un peu trapu !
- Créer le programme hellogtk.asm :
section .data
hello_str db "Hello, world!", 0
section .text
global main
extern gtk_init, gtk_main, gtk_main_quit, gtk_widget_show_all, gtk_window_new, gtk_window_set_title, gtk_label_new, gtk_container_add
main:
; Initialiser GTK
push rbp
mov rbp, rsp
sub rsp, 16
mov qword [rbp-16], 0 ; argc
mov qword [rbp-8], 0 ; argv
lea rdi, [rbp-16] ; argc
lea rsi, [rbp-8] ; argv
call gtk_init
; Créer la fenêtre
mov edi, 0 ; GTK_WINDOW_TOPLEVEL
call gtk_window_new
mov rbx, rax ; Sauvegarder le pointeur de fenêtre
; Définir le titre de la fenêtre
mov rdi, rbx
mov rsi, hello_str
call gtk_window_set_title
; Créer le label
mov rdi, hello_str
call gtk_label_new
mov rsi, rax
; Ajouter le label à la fenêtre
mov rdi, rbx
call gtk_container_add
; Afficher la fenêtre
mov rdi, rbx
call gtk_widget_show_all
; Exécuter la boucle principale de GTK
call gtk_main
; Nettoyer la pile
leave
ret
section .note.GNU-stack noalloc noexec nowrite progbits- Assembler
nasm -f elf64 hellogtk.asm -o hellogtk.o
- Linker
gcc -o hellogtk hellogtk.o `pkg-config --cflags --libs gtk+-3.0`
- Lancer le programme
./hellogtk
votre commentaire -
Par majekla le 28 Avril 2024 à 23:50
Nous allons créer des mini-programmes permettant d'effectuer des opérations de calcul simples
(addition/soustraction/multiplication/division), sans la possibilité pour l'utilisateur d'entrer des nombres.
Le programme doit présenter le résultat de l'opération sur le terminal.
C'est relativement complexe dans le cas de la multiplication et de la divisionProgramme 1 : addition.asm
Le but est d'afficher le résultat de l'addition 4 + 5.
section .data
result_message db '4 + 5 = ', 0 ; Message à afficher avant le résultat
result db '0' ; Réserver 1 octet pour le résultat (puisque 4+5 = 9, un seul chiffre est nécessaire)
newline db 10, 0 ; Caractère de nouvelle ligne suivi d'un terminateur nul
section .text
global _start
_start:
; Calculer 4 + 5 et stocker le résultat dans la variable result
mov eax, 4
add eax, 5
; Convertir le résultat en un caractère ASCII
add al, '0'
mov [result], al ; Stocker le caractère dans le résultat
; Écrire le message '4 + 5 = ' sur STDOUT
mov eax, 4 ; Numéro d'appel système pour sys_write dans FreeBSD
mov edi, 1 ; STDOUT
mov rsi, result_message ; Pointeur vers le message à afficher
mov rdx, 9 ; Longueur du message à afficher (y compris le résultat et le signe égal)
syscall ; Effectuer l'appel système pour écrire
; Écrire le résultat et une nouvelle ligne sur STDOUT
mov eax, 4 ; Numéro d'appel système pour sys_write dans FreeBSD
mov edi, 1 ; STDOUT
mov rsi, result ; Pointeur vers le résultat à afficher
mov rdx, 2 ; Longueur du résultat et de la nouvelle ligne
syscall ; Effectuer l'appel système pour écrire
; Terminer le programme correctement
mov eax, 1 ; Numéro d'appel système pour sys_exit dans FreeBSD
xor edi, edi ; Code de sortie 0
syscall ; Effectuer l'appel système pour quitter- Assembler
nasm -f elf64 addition.asm -o addition.o
- Linker
ld addition.o -o addition
- Lancer le programme
./addition
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Programme 2 : soustraction.asmLe but est d'afficher le résultat de la soustraction de 10 - 6
section .data
result_message db '10 - 6 = ', 0 ; Message à afficher avant le résultat
result db '0' ; Réserver 1 octet pour le résultat (puisque 10-6 = 4, un seul chiffre est nécessaire)
newline db 10, 0 ; Caractère de nouvelle ligne suivi d'un terminateur nul
section .text
global _start
_start:
; Calculer 10 - 6 et stocker le résultat dans la variable result
mov eax, 10
sub eax, 6
; Convertir le résultat en un caractère ASCII
add al, '0'
mov [result], al ; Stocker le caractère dans le résultat
; Écrire le message '10 - 6 = ' sur STDOUT
mov eax, 4 ; Numéro d'appel système pour sys_write dans FreeBSD
mov edi, 1 ; STDOUT
mov rsi, result_message ; Pointeur vers le message à afficher
mov rdx, 10 ; Longueur du message à afficher (y compris le résultat et le signe égal)
syscall ; Effectuer l'appel système pour écrire
; Écrire le résultat et une nouvelle ligne sur STDOUT
mov eax, 4 ; Numéro d'appel système pour sys_write dans FreeBSD
mov edi, 1 ; STDOUT
mov rsi, result ; Pointeur vers le résultat à afficher
mov rdx, 2 ; Longueur du résultat et de la nouvelle ligne
syscall ; Effectuer l'appel système pour écrire
; Terminer le programme correctement
mov eax, 1 ; Numéro d'appel système pour sys_exit dans FreeBSD
xor edi, edi ; Code de sortie 0
syscall ; Effectuer l'appel système pour quitter- Assembler
nasm -f elf64 soustraction.asm -o soustraction.o
- Linker
ld soustraction.o -o soustraction
- Lancer le programme
./soustraction
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Programme 3 : multiplication.asmLe but est d'afficher le résultat de la multiplication de 3*4
Là, c'est beaucoup, beaucoup plus compliqué !!section .data
message db "Le résultat est : ", 0
messageLen equ $-message
newline db 10, 0 ; Caractère de saut de ligne
section .bss
resultSpace resb 12 ; Réserve 12 octets pour le résultat en ASCII
section .text
global _start
_start:
; Calcul de 3 * 4
mov eax, 3
mov ebx, 4
mul ebx ; Après cette opération, eax = 3 * 4 = 12
; Convertir le nombre en chaîne de caractères
mov rdi, resultSpace + 11 ; Pointeur vers la fin de resultSpace
mov byte [rdi], 0 ; Terminer la chaîne avec un caractère nul
mov rbx, 10 ; Diviseur pour la conversion en décimal
mov rcx, 0 ; Initialiser le compteur de chiffres
convert_loop:
mov rdx, 0
div rbx ; Divise eax par 10
add dl, '0' ; Convertit le reste en caractère ASCII
dec rdi ; Décrémente le pointeur pour écrire le caractère
mov [rdi], dl ; Écrit le caractère dans resultSpace
inc rcx ; Incrémente le compteur de chiffres
test eax, eax
jnz convert_loop ; Continuer tant que eax n'est pas nul
; Afficher le message
mov rax, 4 ; syscall pour sys_write
mov rdi, 1 ; File descriptor 1 pour stdout
mov rsi, message ; Pointeur vers le message à afficher
mov rdx, messageLen ; Longueur du message
syscall ; Appel système pour écrire le message
; Afficher le résultat
mov rax, 4 ; syscall pour sys_write
mov rdi, 1 ; File descriptor 1 pour stdout
mov rsi, resultSpace ; Pointeur vers le résultat
mov rdx, rcx ; Longueur du résultat (nombre de chiffres)
syscall ; Appel système pour écrire le résultat
; Afficher le saut de ligne
mov rax, 4 ; syscall pour sys_write
mov rdi, 1 ; File descriptor 1 pour stdout
mov rsi, newline ; Pointeur vers le saut de ligne
mov rdx, 1 ; Longueur du saut de ligne
syscall ; Appel système pour écrire le saut de ligne
; Terminer le programme
mov rax, 1 ; syscall pour sys_exit
xor rdi, rdi ; Status 0
syscall ; Appel système pour terminer le programme- Assembler
nasm -f elf64 multiplication.asm -o multiplication.o
- Linker
ld multiplication.o -o multiplication
- Lancer le programme
./multiplication
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Programme 4 : division.asmLe but est d'afficher le résultat de la division 12/3
section .data
message db "Le résultat de la division est : ", 0
messageLen equ $-message
newline db 10, 0 ; Caractère de saut de ligne
section .bss
resultSpace resb 12 ; Réserve 12 octets pour le résultat en ASCII
section .text
global _start
_start:
; Calcul de 12 / 3
mov eax, 12
mov ebx, 3
div ebx ; Après cette opération, eax = 12 / 3 = 4
; Convertir le nombre en chaîne de caractères
mov rdi, resultSpace + 11 ; Pointeur vers la fin de resultSpace
mov byte [rdi], 0 ; Terminer la chaîne avec un caractère nul
mov rbx, 10 ; Diviseur pour la conversion en décimal
mov rcx, 0 ; Initialiser le compteur de chiffres
convert_loop:
mov rdx, 0
div rbx ; Divise eax par 10
add dl, '0' ; Convertit le reste en caractère ASCII
dec rdi ; Décrémente le pointeur pour écrire le caractère
mov [rdi], dl ; Écrit le caractère dans resultSpace
inc rcx ; Incrémente le compteur de chiffres
test eax, eax
jnz convert_loop ; Continuer tant que eax n'est pas nul
; Afficher le message
mov rax, 4 ; syscall pour sys_write
mov rdi, 1 ; File descriptor 1 pour stdout
mov rsi, message ; Pointeur vers le message à afficher
mov rdx, messageLen ; Longueur du message
syscall ; Appel système pour écrire le message
; Afficher le résultat
mov rax, 4 ; syscall pour sys_write
mov rdi, 1 ; File descriptor 1 pour stdout
mov rsi, resultSpace ; Pointeur vers le résultat
mov rdx, rcx ; Longueur du résultat (nombre de chiffres)
syscall ; Appel système pour écrire le résultat
; Afficher le saut de ligne
mov rax, 4 ; syscall pour sys_write
mov rdi, 1 ; File descriptor 1 pour stdout
mov rsi, newline ; Pointeur vers le saut de ligne
mov rdx, 1 ; Longueur du saut de ligne
syscall ; Appel système pour écrire le saut de ligne
; Terminer le programme
mov rax, 1 ; syscall pour sys_exit
xor rdi, rdi ; Status 0
syscall ; Appel système pour terminer le programme- Assembler
nasm -f elf64 division.asm -o division.o
- Linker
ld division.o -o division
- Lancer le programme
./division
votre commentaire -
Par majekla le 28 Avril 2024 à 22:58
Le but est simple :
le programme demande d'entrer un mot (ou une phrase), l'utilisateur écrit alors un mot ou une chaîne de caractères puis le programme la lui répète (affiche) comme un perroquet.
Aussi "simple" qu'un 'read PHRASE' puis un 'echo $PHRASE' en shell ou BASH...
Sauf que ça ne l'est pas du tout en assembleur !
Il faut gérer la longueur réelle de l'entrée pour pouvoir la renvoyer en entier.section .data
prompt_message db 'Entrez un mot: ', 0
prompt_len equ $-prompt_message
newline db 10 ; Caractère de saut de ligne
section .bss
input_buffer resb 100 ; Taille de l'espace réservé
input_length resq 1 ; Variable pour stocker la longueur réelle de l'entrée
section .text
global _start
_start:
; Affichage du message d'invite
mov rax, 4
mov rdi, 1
mov rsi, prompt_message
mov rdx, prompt_len
syscall
; Lecture de l'entrée utilisateur
mov rax, 3
mov rdi, 0
mov rsi, input_buffer
mov rdx, 100 ; Augmentation de la taille lue
syscall
; Stocker la longueur réelle lue dans rax, et soustraire 1 pour enlever le newline
sub rax, 1
mov qword [input_length], rax ; Stocker la longueur réelle dans input_length
; Affichage de l'entrée utilisateur
mov rax, 4
mov rdi, 1
mov rsi, input_buffer
mov rdx, qword [input_length] ; Utiliser la longueur réelle
syscall
; Affichage d'un saut de ligne
mov rax, 4
mov rdi, 1
mov rsi, newline
mov rdx, 1
syscall
; Sortie du programme
mov rax, 1 ; exit syscall number
xor rdi, rdi
syscall- Assembler
nasm -f elf64 perroquet.asm -o perroquet.o
- Linker
ld perroquet.o -o perroquet
- Lancer le programme
./perroquet
votre commentaire -
Par majekla le 28 Avril 2024 à 21:01
Nous reprenons le principe du programme du mot magique en le combinant à l'exécution d'une commande système simple.
Le programme demande à ce que l'utilisateur rentre un mot.
Si le mot 'magique' est entré, alors le programme répond 'BRAVO' et exécute la commande 'ls' pour afficher le contenu du répertoire courant puis quitte !section .data
prompt_message db 'Entrez un mot: ', 0
prompt_len equ $-prompt_message
magic_word db 'magique', 0
magic_len equ $-magic_word
bravo_message db 'BRAVO', 10
bravo_len equ $-bravo_message
error_message db 'ERREUR', 10
error_len equ $-error_message
command db '/bin/ls', 0
argv dq command, 0
envp dq 0
section .bss
input_buffer resb 50
section .text
global _start
_start:
; Affichage du message d'invite
mov rax, 4
mov rdi, 1
mov rsi, prompt_message
mov rdx, prompt_len
syscall
; Lecture de l'entrée utilisateur
mov rax, 3
mov rdi, 0
mov rsi, input_buffer
mov rdx, 50
syscall
; Stocker la longueur réelle lue dans rax, et soustraire 1 pour enlever le newline
sub rax, 1
; Comparer l'entrée avec 'magique'
mov rdi, input_buffer
mov rsi, magic_word
mov rcx, rax ; Utiliser la longueur ajustée
call compare_strings
; Décider sur la base du résultat de la comparaison
test rax, rax
jz magic_matched
jmp error_occurred
magic_matched:
; Affichage de 'BRAVO'
mov rax, 4
mov rdi, 1
mov rsi, bravo_message
mov rdx, bravo_len
syscall
; Exécuter 'ls'
mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
syscall ; Appeler le système
error_occurred:
; Affichage de 'ERREUR'
mov rax, 4
mov rdi, 1
mov rsi, error_message
mov rdx, error_len
syscall
exit:
; Sortie du programme
mov rax, 1
xor rdi, rdi
syscall
compare_strings:
; Comparaison caractère par caractère
repe cmpsb
jecxz equal ; Sauter si tous les caractères ont été comparés et sont égaux
mov rax, 1
ret
equal:
xor rax, rax ; Résultat zéro indique une égalité
ret- Assembler
nasm -f elf64 magiquels.asm -o magiquels.o
- Linker
ld magiquels.o -o magiquels
- Lancer le programme
./magiquels
votre commentaire -
Par majekla le 28 Avril 2024 à 20:42
Le but ici est d'afficher le résultat de la commande système 'ls', SANS ARGUMENT
Le contenu du répertoire courant doit s'affichersection .data
command db '/bin/ls', 0 ; Commande à exécuter avec un caractère nul à la fin
argv dq command, 0 ; Tableau d'arguments pour ls (seulement le nom du programme)
envp dq 0 ; Tableau d'environnement vide
section .text
global _start
_start:
; Exécuter '/usr/bin/ls' pour lister le contenu du répertoire courant
mov rax, 59 ; Le numéro de système pour sys_execve sur FreeBSD
lea rdi, [command] ; Le premier argument de sys_execve, le chemin du programme
lea rsi, [argv] ; Le deuxième argument, le tableau d'arguments
lea rdx, [envp] ; Le troisième argument, le tableau d'environnement
syscall ; Appeler le système
; Terminer le programme proprement si jamais sys_execve échoue
mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système- Assembler
nasm -f elf64 ls.asm -o ls.o
- Linker
ld ls.o -o ls
- Lancer le programme
./ls
-------------------------------------------------------------------------------------------------------------------------------
A présent, nous allons exécuter une autre commande, AVEC ARGUMENTS cette fois.
Le but ici est d'exécuter une commande avec redirection : echo "coucou" > /tmp/test.txtsection .data
command db '/bin/sh', 0 ; Utiliser le shell pour exécuter la commande
arg1 db '-c', 0 ; Argument pour exécuter une commande
arg2 db 'echo "coucou" > /tmp/test', 0 ; Commande à exécuter
argv dq command, arg1, arg2, 0 ; Tableau d'arguments pour execve
envp dq 0 ; Tableau d'environnement vide
section .text
global _start
_start:
; Exécuter 'echo "coucou" > /tmp/test' via /bin/sh
mov rax, 59 ; Numéro de l'appel système pour sys_execve sous FreeBSD
lea rdi, [command] ; Premier argument pour sys_execve, le chemin du programme
lea rsi, [argv] ; Deuxième argument, le tableau d'arguments
lea rdx, [envp] ; Troisième argument, le tableau d'environnement
syscall ; Appeler le système
; Terminer le programme avec grâce si sys_execve échoue
mov rax, 1 ; Numéro de l'appel système pour sys_exit sous FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système- Assembler
nasm -f elf64 echo.asm -o echo.o
- Linker
ld echo.o -o echo
- Lancer le programme
./echo
-------------------------------------------------------------------------------------------------------------------------------
A présent, nous allons exécuter une autre commande, AVEC ARGUMENTS cette fois.
Le but est de tester la connexion internet en utilisant la commande système fetch.
Le programme doit exécuter la commande 'fetch -q https://www.freebsd.org'section .data
command db '/usr/bin/fetch', 0 ; Command to be executed
arg1 db '-q', 0 ; First argument
arg2 db 'https://www.freebsd.org', 0 ; Second argument
argv dq command, arg1, arg2, 0 ; Argument array for fetch
envp dq 0 ; Empty environment array
section .text
global _start
_start:
; Execute 'fetch -q https://www.freebsd.org'
mov rax, 59 ; System call number for sys_execve on FreeBSD
lea rdi, [command] ; First argument for sys_execve, the program path
lea rsi, [argv] ; Second argument, the argument array
lea rdx, [envp] ; Third argument, the environment array
syscall ; Call the system
; Terminate the program gracefully if sys_execve fails
mov rax, 1 ; System call number for sys_exit on FreeBSD
xor rdi, rdi ; Exit code 0
syscall ; Call the system- Assembler
nasm -f elf64 fetch.asm -o fetch.o
- Linker
ld fetch.o -o fetch
- Lancer le programme
./fetch
-------------------------------------------------------------------------------------------------------------------------------
A présent, nous allons changer le mot de passe de l'utilisateur marcel3.
Ce n'est évidemment pas une bonne pratique !! C'est juste pour l'exemple de l'utilisation de commandes système.section .data
command db '/bin/sh', 0
arg1 db '-c', 0
; Construire la commande complète ici
arg2 db 'echo "motdepasse" | pw usermod marcel3 -h 0', 0
argv dq command, arg1, arg2, 0
envp dq 0
section .text
global _start
_start:
; Exécuter la commande via /bin/sh
mov rax, 59 ; Numéro de l'appel système pour sys_execve sous FreeBSD
lea rdi, [command] ; Premier argument pour sys_execve, le chemin du programme
lea rsi, [argv] ; Deuxième argument, le tableau d'arguments
lea rdx, [envp] ; Troisième argument, le tableau d'environnement
syscall ; Appeler le système
; Terminer le programme avec grâce si sys_execve échoue
mov rax, 1 ; Numéro de l'appel système pour sys_exit sous FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système- Assembler
nasm -f elf64 pass.asm -o pass.o
- Linker
ld pass.o -o pass
- Lancer le programme
./pass
votre commentaire -
Par majekla le 28 Avril 2024 à 20:18
Scénario 1 :
2 chaînes de caractères sont entrées dans le code du programme.
La première est le mot "hello", la seconde est une chaîne aléatoire contenant le mot "hello"
Le programme doit dire si la chaîne de caractères 1 (hello) est présente dans la 2.
Si oui, le programme répond "FOUND"
Si non (si vous remplacez le mot hello par autre chose), le programme répond "NOT FOUND"
Je tiens tout spécialement à remercier "omais" pour avoir trouvé la solution à ce premier scénario.
- Voici le programme search.asm%define SYS_WRITE 4
%define SYS_EXIT 1
;;; file ids
%define STDOUT 1
; cat search.asm
section .data
str1 db 'hello', 0
str2 db 'z vmermbzmev,emfb mzinv zinvlienblginbilnb zaeb enb leinrqfv hello zv elibn lienrli n', 0
found db "FOUND",10, 0
found_len equ $ - found
notfound db "NOT FOUND",10, 0
notfound_len equ $ - notfound
section .text
global _start
_start:
mov rsi, str1
mov rdi, str2
mov rax, 0
mov rcx, 0
search:
mov rbx, 0
compare:
mov al, [rsi + rbx]
mov ah, [rdi + rcx]
cmp al, ah
je check_find
cmp ah, 0
je notfound_msg
inc rcx
jmp compare
check_find:
inc rbx
inc rcx
mov al, [rsi + rbx]
mov ah, [rdi + rcx]
cmp al, 0
je found_msg
cmp al, ah
jne search
jmp check_find
found_msg:
mov rax, SYS_WRITE
mov rdi, STDOUT
mov rsi, found
mov rdx, found_len
syscall
jmp exit
notfound_msg:
mov rax, SYS_WRITE
mov rdi, STDOUT
mov rsi, notfound
mov rdx, notfound_len
syscall
exit:
mov rax, SYS_EXIT ; exit syscall
mov rdi, 0 ; exit code 0 (= "ok")
syscall ; kernel interrupt: system cal- Assembler
nasm -f elf64 search.asm -o search.o
- Linker
ld search.o -o search
- Lancer le programme
./search
Scénario 2 :
Le but est de demander à l'utilisateur d'entrer un mot magique.
- Si le mot entré correspond à ce qui est attendu, le programme répond "BRAVO" et quitte
- Si le mot entré ne correspond pas, le programme répond "ERREUR" et quitte
- Voici le programme motmagique.asmsection .data
prompt_message db 'Entrez un mot: ', 0
prompt_len equ $-prompt_message
magic_word db 'magique', 0
magic_len equ $-magic_word
bravo_message db 'BRAVO', 10
bravo_len equ $-bravo_message
error_message db 'ERREUR', 10
error_len equ $-error_message
section .bss
input_buffer resb 50
section .text
global _start
_start:
; Affichage du message d'invite
mov rax, 4
mov rdi, 1
mov rsi, prompt_message
mov rdx, prompt_len
syscall
; Lecture de l'entrée utilisateur
mov rax, 3
mov rdi, 0
mov rsi, input_buffer
mov rdx, 50
syscall
; Stocker la longueur réelle lue dans rax, et soustraire 1 pour enlever le newline
sub rax, 1
; Comparer l'entrée avec 'magique'
mov rdi, input_buffer
mov rsi, magic_word
mov rcx, rax ; Utiliser la longueur ajustée
call compare_strings
; Décider sur la base du résultat de la comparaison
test rax, rax
jz magic_matched
jmp error_occurred
magic_matched:
; Affichage de 'BRAVO'
mov rax, 4
mov rdi, 1
mov rsi, bravo_message
mov rdx, bravo_len
syscall
jmp exit
error_occurred:
; Affichage de 'ERREUR'
mov rax, 4
mov rdi, 1
mov rsi, error_message
mov rdx, error_len
syscall
exit:
; Sortie du programme
mov rax, 1
xor rdi, rdi
syscall
compare_strings:
; Comparaison caractère par caractère
repe cmpsb
jecxz equal ; Sauter si tous les caractères ont été comparés et sont égaux
mov rax, 1
ret
equal:
xor rax, rax ; Résultat zéro indique une égalité
ret- Assembler
nasm -f elf64 motmagique.asm -o motmagique.o
- Linker
ld motmagique.o -o motmagique
- Lancer le programme
./motmagique
votre commentaire -
Par majekla le 28 Avril 2024 à 11:39
- Passer en root
su -
- Installer le compilateur nasm
pkg ins -y nasm
- Ecrivez le programme 'hello.asm' dans votre éditeur de code préféré
section .data
hello_message db 'hello world', 10 ; Le message à afficher avec un saut de ligne
section .text
global _start
_start:
; Écrire 'hello world' sur STDOUT
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; STDOUT
mov rsi, hello_message ; Pointer vers le message à afficher
mov rdx, 12 ; La longueur du message à afficher (incluant le saut de ligne)
syscall ; Appeler le système
; Terminer le programme proprement
mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système
- Assemblernasm -f elf64 hello.asm -o hello.o
- Linker
ld hello.o -o hello
- Lancer le programme
./hello
Créons désormais une seconde version de notre programme :
- Ajoutons à présent une seconde ligne à notre sortie :hello world
I'm great!Voici le code :
- vous remarquerez qu'il faut faire 2 retours à la ligne après "I'm great", autrement le prompt du shell sera collé ! Pas évident à comprendre au début.
- vous remarquerez aussi que la longueur du message à afficher est également différente (logique !)section .data
hello_message db 'hello world', 10, "I'm great!", 10, 10 ; Les messages à afficher avec un saut de ligne après chaque ligne et un saut de ligne à la fin
section .text
global _start
_start:
; Écrire 'hello world' et "I'm great!" sur STDOUT
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; STDOUT
mov rsi, hello_message ; Pointer vers le message à afficher
mov rdx, 23 ; La longueur des messages à afficher (incluant les sauts de ligne)
syscall ; Appeler le système
; Terminer le programme proprement
mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le systèmeLe programme peut également être écrit ainsi :
section .data
hello_message db 'hello world', 10 ; Le message à afficher avec un saut de ligne
great_message db "I'm great!", 10 ; Le second message à afficher avec un saut de ligne
section .text
global _start
_start:
; Écrire 'hello world' sur STDOUT
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; STDOUT
mov rsi, hello_message ; Pointer vers le message à afficher
mov rdx, 12 ; La longueur du message à afficher (incluant le saut de ligne)
syscall ; Appeler le système
; Écrire 'I'm great!' sur STDOUT
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; STDOUT
mov rsi, great_message ; Pointer vers le second message à afficher
mov rdx, 11 ; La longueur du second message à afficher (incluant le saut de ligne)
syscall ; Appeler le système
; Terminer le programme proprement
mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le systèmeVous savez désormais comment afficher du texte sur le shell en assembleur !
ça paraît peu, mais c'est déjà beaucoup !
Créons désormais une boucle pour répéter l'apparition de nos 2 lignes 10 fois :section .data
hello_message db 'hello world', 10, "I'm great!", 10, 10 ; Les messages à afficher avec un saut de ligne après chaque ligne
hello_message_len equ $ - hello_message ; Longueur du message
section .text
global _start
_start:
; Initialiser le compteur de boucle
mov ecx, 10 ; Répéter 10 fois
repeat_loop:
; Écrire 'hello world' et "I'm great!" sur STDOUT
mov rax, 4 ; Le numéro de système pour sys_write sur FreeBSD
mov rdi, 1 ; STDOUT
mov rsi, hello_message ; Pointer vers le message à afficher
mov rdx, hello_message_len ; La longueur des messages à afficher
syscall ; Appeler le système
; Décrémenter le compteur de boucle
dec ecx
jnz repeat_loop ; Répéter jusqu'à ce que ecx soit égal à zéro
; Terminer le programme proprement
mov rax, 1 ; Le numéro de système pour sys_exit sur FreeBSD
xor rdi, rdi ; Code de sortie 0
syscall ; Appeler le système
votre commentaire
Suivre le flux RSS des articles de cette rubrique
Suivre le flux RSS des commentaires de cette rubrique