codice macchina x86, 70 byte
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
Il mio codice eseguibile, smontato:
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
È una funzione che riceve la dimensione della X in ecx e un puntatore al buffer di output in edx.
Riempie il buffer di output in sequenza con byte. Esistono 2 * n - 1
iterazioni (pari al numero di caratteri non spaziali da emettere). Ad ogni iterazione, procede come segue:
- Genera un numero casuale
- Armeggia con il numero per adattarlo al range; se è male, torna indietro e genera di nuovo
- Stampa il personaggio casuale
- Stampa una nuova riga (ogni altra iterazione)
- Stampa il numero corretto di spazi
La conversione da un numero casuale a un personaggio casuale non è notevole:
myrand:
rdrand eax;
and al, 7fh;
cmp al, 22h;
jb myrand;
dec eax;
cmp al, 'y';
je myrand;
cmp al, 'Y';
je myrand;
La parte interessante è il calcolo del numero di spazi. Deve generare i seguenti numeri (esempio per N = 9):
7 1
5 2
3 3
1 4
3
1 2
3 1
5 0
7
I numeri sono presi alternativamente da due progressioni aritmetiche. Il primo scende con il passaggio -2 e il secondo sale con il passaggio 1. Quando la prima progressione arriva a -1 (al centro della X), c'è un problema tecnico (-1 viene rimosso), quindi le progressioni cambiano direzione.
Le progressioni sono memorizzate nei registri ebx
e edx
- le parti alte bh
e dh
memorizzano il numero corrente e le parti basse bl
e dl
memorizzano il passo. Per alternare tra le progressioni, il codice scambia i registri con xchg
.
Quando la progressione arriva a -1 (attorno mylab
all'etichetta), aumenta entrambi i registri, passando da -2, 1
a -1, 2
. Questo cambia anche i ruoli dei registri, quindi scambia le parti alte dei registri.
Alla fine della funzione, memorizza un byte zero per indicare una fine della stringa.