Table des matières
Cet exercice sera le dernier de la saga assembleur 8086+. Nous allons donc finir par un jeu rudimentaire 😎 .
Comme d'habitude, je ne détaillerai rien concernant la compilation/l'édition des liens encore cette fois-ci. Reportez-vous au premier billet pour plus d'informations.
Exercice 6 : énoncé
Nous allons faire un mini jeu de motus en assembleur. Le but est de deviner le mot qui sera défini dans la zone data en un minimum d'essais. Si le mot n'est pas découvert en 7 essais, la partie est perdue. La première lettre du mot sera montrée au joueur dès le début d'une partie. Lors de chaque essai, il faudra afficher le numéro de l'essai, un rappel des lettres trouvés lors des essais précédents ainsi qu'une invitation à saisir une nouvelle proposition. Des messages "perdu"/"gagné" devront également être prévus.
Note : Comme d'habitude, cet énoncé n’est pas de moi : je l’ai repris à T.M. / E.R. et je l’ai modifié.
Exercice 6 : aides
Pas d'aide pour cet exercice car il n'y a aucune nouvelle notion ni aucune difficulté.
Exercice 6 : sous Windows, avec TASM et TLINK
TITLE MOTUS DOSSEG .MODEL SMALL .STACK 100H .DATA mot db "bonjour$" ; le mot à trouver longueur db 7 ; longueur du mot à trouver mot2 db "b------$" ; les lettres connues trouve db 1 ; nb lettres trouvées essai db 1 ; combien d'essai nécessaires ? saisie db 8,9 dup(?) ; stockera la saisie utilisateur ; messages écran msgEssai db 13,10,"Essai $" demandeSaisie db ", saisissez un mot : ",13,10,10,"$" msgGagne db "Bravo, vous avez trouve le mot !",13,10,"$" msgPerdu db "Perdu, vous n'avez pas trouve en 7 essais !",13,10,"$" ligne db 13,10,"$" .CODE mov ax, @DATA mov ds, ax mov cx, 7 bcl: push cx ;AFFICHAGE NUM ESSAI ; "Essai numero" mov ah, 09h mov dx, offset msgEssai int 21h ; affichage numero de l'essai mov ah, 02h mov dl, [essai] add dl, 30h int 21h ; affichage "saisissez un mot" mov ah, 09h mov dx, offset demandeSaisie int 21h ;SAISIE DE LA PROPOSITION ; affiche lettres déjà connues mov ah, 09h mov dx, offset mot2 int 21h ; retour ligne mov ah, 09h mov dx, offset ligne int 21h ; saisie mov ah, 0Ch mov al, 0ah mov dx, offset saisie int 21h ; retour ligne mov ah, 09h mov dx, offset ligne int 21h ;EVALUATION DE LA SAISIE mov [trouve], 0 ; à chaque essai, on considére qu'aucune lettre n'a été trouvée mov bx, 0 mov dl, longueur ; On va comparer lettre par lettre la saisie au mot à trouver bcl2: cmp bx, dx ja finbcl2 mov al, [mot+bx] cmp [saisie+bx+2], al ; Attention il y a une différence de 2 entre la saisie et le mot JNE remonte ; revoir le format d'une saisie : les 2 octets initiaux servent à ; stocker taille maximale de la chaîne et taille réelle mov [mot2+bx], al ; Si l'on a la même lettre, on l'ajoute aux lettres connues inc [trouve] ; et on incrémente le compteur de lettres trouvées remonte: inc bx jmp bcl2 finbcl2: ;EVALUATION GAGNE/PERDU mov al, longueur cmp trouve, al ; Si toutes les lettres ont été trouvé, c'est gagné je gagne inc essai ; Sinon on incrémente le nombre d'essais, pop cx ; on restaure cx et on repart pour un essai loop bcl ; Si l'on arrive là, alors la boucle s'est finie donc les essais sont écoulés ; donc c'est perdu : affichage du message mov ah, 09h mov dx, offset msgPerdu int 21h jmp fin gagne: ; affiche message "gagné" mov ah, 09h mov dx, offset msgGagne int 21h fin: mov ax, 4c00h int 21h END |
Exercice 6 : sous Windows, avec Nasm et le linker Val
segment .data mot db "bonjour$" ; le mot à trouver longueur db 7 ; longueur du mot à trouver mot2 db "b------$" ; les lettres connues trouve db 1 ; nb lettres trouvées essai db 1 ; combien d'essai necessaires ? saisie times 10 db 8 ; messages écran msgEssai db 13,10,"Essai $" demandeSaisie db ", saisissez un mot : ",13,10,10,"$" msgGagne db "Bravo, vous avez trouve le mot !",13,10,"$" msgPerdu db "Perdu, vous n'avez pas trouve en 7 essais !",13,10,"$" ligne db 13,10,"$" segment stack stack resb 64 stackstop: segment .code ..start: mov ax, data mov ds, ax mov cx, 7 bcl: push cx ;AFFICHAGE NUM ESSAI ; "Essai numero" mov ah, 09h mov dx, msgEssai int 21h ; affichage numero de l'essai mov ah, 02h mov dl, [essai] add dl, 30h int 21h ; affichage "saisissez un mot" mov ah, 09h mov dx, demandeSaisie int 21h ;SAISIE DE LA PROPOSITION ; affiche lettres déjà connues mov ah, 09h mov dx, mot2 int 21h ; retour ligne mov ah, 09h mov dx, ligne int 21h ; saisie mov ah, 0Ch mov al, 0ah mov dx, saisie int 21h ; retour ligne mov ah, 09h mov dx, ligne int 21h ;EVALUATION DE LA SAISIE mov byte [trouve], 0 ; à chaque essai, on considére qu'aucune lettre n'a été trouvée mov bx, 0 mov dl, [longueur] ; On va comparer lettre par lettre la saisie au mot à trouver bcl2: cmp bx, dx ja finbcl2 mov al, [mot+bx] cmp [saisie+bx+2], al ; Attention il y a une différence de 2 entre la saisie et le mot JNE remonte ; revoir le format d'une saisie : les 2 octets initiaux servent à ; stocker taille maximale de la chaîne et taille réelle mov [mot2+bx], al ; Si l'on a la même lettre, on l'ajoute aux lettres connues inc byte [trouve] ; et on incrémente le compteur de lettres trouvées remonte: inc bx jmp bcl2 finbcl2: ;EVALUATION GAGNE/PERDU mov al, [longueur] cmp [trouve], al ; Si toutes les lettres ont été trouvé, c'est gagné je gagne inc byte [essai] ; Sinon on incrémente le nombre d'essais, pop cx ; on restaure cx et on repart pour un essai loop bcl ; Si l'on arrive là, alors la boucle s'est finie donc les essais sont écoulés ; donc c'est perdu : affichage du message mov ah, 09h mov dx, msgPerdu int 21h jmp fin gagne: ; affiche message "gagné" mov ah, 09h mov dx, msgGagne int 21h fin: mov ax, 4c00h int 21h |
Exercice 6 : sous GNU/Linux, avec Nasm et ld
section .data mot db "bonjour" ; le mot à trouver lenmot: equ $-mot ; longueur du mot à trouver mot2 db "b------" ; les lettres connues lenmot2: equ $-mot2 trouve db 1 ; nb lettres trouvées essai db 1 ; combien d'essai necessaires ? msgEssai db 13,10,"Essai " lenMsgEssai: equ $-msgEssai demandeSaisie db ", saisissez un mot : ",13,10,10 lenDemandeSaisie: equ $-demandeSaisie msgGagne db "Bravo, vous avez trouvé le mot !",10 lenMsgGagne: equ $-msgGagne msgPerdu db "Perdu, vous n'avez pas trouvé le mot en 7 essais !",10 lenMsgPerdu: equ $-msgPerdu ligne db 13,10 lenligne: equ $-ligne section .bss saisie resb 8 ; Stocker la saisie. Prévoir une case de plus pour le retour-chariot section .text global _start _start: bcl: ; loop ainsi que les sauts conditionnels ne sont pas utilisables cmp byte [essai], 7 ; car l'adresse destination est trop éloignée. On procède donc jle suite ; à une indirection : un saut conditionnel pointe sur un ; saut inconditionnel (qui ne fait pas partie des sauts courts). jmp finbcl suite: ; AFFICHAGE NUM ESSAI ; "Essai numero" mov eax, 4 mov ebx, 1 mov ecx, msgEssai mov edx, lenMsgEssai int 80h ; affichage numero de l'essai mov eax, 4 mov ebx, 1 mov ecx, essai add byte [ecx], 30h ; Rappel : 30h c'est la différence entre un chiffre mov edx, 1 ; et son équivalent caractère imprimable dans la table ASCII int 80h sub byte [ecx], 30h ; affichage "saisissez un mot" mov eax, 4 mov ebx, 1 mov ecx, demandeSaisie mov edx, lenDemandeSaisie int 80h ;SAISIE DE LA PROPOSITION ; affiche lettres déjà connues mov eax, 4 mov ebx, 1 mov ecx, mot2 mov edx, lenmot2 int 80h ; retour ligne mov eax, 4 mov ebx, 1 mov ecx, ligne mov edx, lenligne int 80h ; saisie mov eax, 3 mov ebx, 0 mov ecx, saisie mov edx, lenmot inc edx int 80h ; retour ligne mov eax, 4 mov ebx, 1 mov ecx, ligne mov edx, lenligne int 80h ;EVALUATION DE LA SAISIE mov byte [trouve], 0 ; à chaque essai, on considére qu'aucune lettre n'a été trouvée mov ebx, 0 mov dl, lenmot sub dx, 1 ; On va comparer lettre par lettre la saisie au mot à trouver bcl2: cmp bx, dx ja finbcl2 mov al, [mot+ebx] cmp [saisie+ebx], al JNE remonte mov [mot2+ebx], al ; Si l'on a la même lettre, on l'ajoute aux lettres connues inc byte [trouve] ; et on incrémente le compteur de lettres trouvées remonte: inc ebx jmp bcl2 finbcl2: ;EVALUATION GAGNE/PERDU mov al, lenmot cmp [trouve], al ; Si toutes les lettres ont été trouvé, c'est gagné je gagne inc byte [essai] ; Sinon on incrémente le nombre d'essais et on repart pour un essai jmp bcl finbcl: ; Si l'on arrive là, alors la boucle s'est finie donc les essais sont écoulés ; donc c'est perdu : affichage du message mov eax, 4 mov ebx, 1 mov ecx, msgPerdu mov edx, lenMsgPerdu int 80h jmp fin gagne: ; affiche message "gagné" mov eax, 4 mov ebx, 1 mov ecx, msgGagne mov edx, lenMsgGagne int 80h fin: mov eax, 1 mov ebx, 0 int 80h |