code machine x86, 70 octets
60 89 d7 31 db 43 88 ce b2 fe 49 d1 e1 87 da 0f
c7 f0 24 7f 3c 22 72 f7 48 3c 79 74 f2 3c 59 74
ee aa 49 7c 1c 00 df 79 06 86 f7 42 43 eb f6 f6
c3 01 74 03 b0 0a aa 51 88 f9 b0 20 f3 aa 59 eb
cc c6 07 00 61 c3
Mon code exécutable, désassemblé:
0000003d <myheh>:
3d: 60 pusha
3e: 89 d7 mov %edx,%edi
40: 31 db xor %ebx,%ebx
42: 43 inc %ebx
43: 88 ce mov %cl,%dh
45: b2 fe mov $0xfe,%dl
47: 49 dec %ecx
48: d1 e1 shl %ecx
0000004a <myloop>:
4a: 87 da xchg %ebx,%edx
0000004c <myrand>:
4c: 0f c7 f0 rdrand %eax
4f: 24 7f and $0x7f,%al
51: 3c 22 cmp $0x22,%al
53: 72 f7 jb 4c <myrand>
55: 48 dec %eax
56: 3c 79 cmp $0x79,%al
58: 74 f2 je 4c <myrand>
5a: 3c 59 cmp $0x59,%al
5c: 74 ee je 4c <myrand>
5e: aa stos %al,%es:(%edi)
5f: 49 dec %ecx
60: 7c 1c jl 7e <mydone>
00000062 <mylab>:
62: 00 df add %bl,%bh
64: 79 06 jns 6c <myprint>
66: 86 f7 xchg %dh,%bh
68: 42 inc %edx
69: 43 inc %ebx
6a: eb f6 jmp 62 <mylab>
0000006c <myprint>:
6c: f6 c3 01 test $0x1,%bl
6f: 74 03 je 74 <myprint1>
71: b0 0a mov $0xa,%al
73: aa stos %al,%es:(%edi)
00000074 <myprint1>:
74: 51 push %ecx
75: 88 f9 mov %bh,%cl
77: b0 20 mov $0x20,%al
79: f3 aa rep stos %al,%es:(%edi)
7b: 59 pop %ecx
7c: eb cc jmp 4a <myloop>
0000007e <mydone>:
7e: c6 07 00 movb $0x0,(%edi)
81: 61 popa
82: c3 ret
C'est une fonction qui reçoit la taille du X dans ecx et un pointeur sur le tampon de sortie dans edx.
Il remplit la mémoire tampon de sortie séquentiellement d'octets. Il y a des 2 * n - 1
itérations (égales au nombre de caractères sans espace à afficher). À chaque itération, il effectue les opérations suivantes:
- Générer un nombre aléatoire
- Violon avec le numéro pour l'adapter à la gamme; si c'est mauvais, retourne et génère de nouveau
- Imprimer le caractère aléatoire
- Imprimer une nouvelle ligne (chaque itération)
- Imprimer le nombre approprié d'espaces
La conversion d'un nombre aléatoire en un caractère aléatoire n'est pas remarquable:
myrand:
rdrand eax;
and al, 7fh;
cmp al, 22h;
jb myrand;
dec eax;
cmp al, 'y';
je myrand;
cmp al, 'Y';
je myrand;
La partie intéressante est le calcul du nombre d'espaces. Il doit générer les nombres suivants (exemple pour N = 9):
7 1
5 2
3 3
1 4
3
1 2
3 1
5 0
7
Les nombres sont pris alternativement de deux progressions arithmétiques. Le premier descend à l’étape -2 et le second à l’étape 1. Lorsque la première progression arrive à -1 (au milieu du X), il y a un problème (-1 est supprimé), puis les progressions changent de direction.
Les progressions sont stockées dans des registres ebx
et edx
- les parties hautes bh
et dh
stockent le numéro actuel, et les parties basses bl
et dl
stockent le pas. Pour alterner les progressions, le code échange les registres avec xchg
.
Lorsque la progression arrive à -1 (autour de l' mylab
étiquette), les deux registres sont augmentés, les étapes passant de -2, 1
à -1, 2
. Cela modifie également les rôles des registres, de sorte qu'il permute les parties hautes des registres.
À la fin de la fonction, il stocke un octet nul pour indiquer une fin de chaîne.