• 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)

    - Liste des appels système sur FreeBSD

  • 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
  • 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
  • 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
  • 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
  • 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ème

     

     

     

    Scé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
  • 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
  • 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
  • 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
    syscall


     

    Maintenant, 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
    syscall

     

    Enfin, 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
  • 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
    syscall

     

    Nous 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
  • 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
  • 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
  • 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
  • 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
  • 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 division

     

    Programme 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.asm

    Le 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.asm

    Le 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.asm

    Le 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
  • 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
  • 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
  • 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'afficher

    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:
    ; 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.txt



    section .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
  • 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.asm

    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

    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
  • - 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


    - Assembler

    nasm -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ème

    Le 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ème

     

    Vous 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