kod maszynowy x86, 70 bajtów
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
Mój kod wykonywalny, zdemontowany:
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
Jest to funkcja, która odbiera rozmiar X w ekxie i wskaźnik do bufora wyjściowego w edx.
Wypełnia bufor wyjściowy sekwencyjnie bajtami. Istnieją 2 * n - 1
iteracje (równe liczbie znaków spacji do wydrukowania). Przy każdej iteracji wykonuje następujące czynności:
- Wygeneruj liczbę losową
- Baw się z liczbą, aby dopasować ją do zasięgu; jeśli jest źle, wróć i wygeneruj od nowa
- Wydrukuj losowy znak
- Wydrukuj nowy wiersz (co drugą iterację)
- Wydrukuj odpowiednią liczbę spacji
Konwersja liczby losowej na postać losową nie jest niezwykła:
myrand:
rdrand eax;
and al, 7fh;
cmp al, 22h;
jb myrand;
dec eax;
cmp al, 'y';
je myrand;
cmp al, 'Y';
je myrand;
Interesującą częścią jest obliczenie liczby spacji. Musi wygenerować następujące liczby (przykład dla N = 9):
7 1
5 2
3 3
1 4
3
1 2
3 1
5 0
7
Liczby są pobierane naprzemiennie z dwóch postępów arytmetycznych. Pierwszy idzie w dół z krokiem -2, a drugi idzie w górę z krokiem 1. Gdy pierwszy postęp osiąga -1 (w środku X), pojawia się usterka (-1 jest usuwany), a następnie postępy zmieniają kierunek.
Postępy są przechowywane w rejestrach ebx
i edx
- wysokie części bh
i dh
przechowują bieżący numer, a niskie części bl
i dl
przechowują krok. Aby przełączać się między progresjami, kod zamienia rejestry na xchg
.
Gdy progresja osiąga wartość -1 (wokół mylab
etykiety), zwiększa oba rejestry, przełączając kroki z -2, 1
na -1, 2
. Zmienia to także role rejestrów, a zatem zamienia wysokie części rejestrów.
Na końcu funkcji przechowuje bajt zerowy wskazujący koniec łańcucha.