машинний код x86, 70 байт
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
Мій виконуваний код, розібраний:
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
Це функція, яка отримує розмір X в ecx, і вказівник на вихідний буфер в edx.
Він заповнює вихідний буфер послідовно байтами. Є 2 * n - 1
ітерації (дорівнює кількості непробільних символів для виводу). При кожній ітерації вона робить наступне:
- Утворіть випадкове число
- Скиньтеся з номером, щоб вписати його в діапазон; якщо це погано, поверніться і генеруйте заново
- Друк випадкового символу
- Друк нового рядка (будь-яка інша ітерація)
- Роздрукуйте належну кількість пробілів
Перетворення від випадкового числа до випадкового символу не примітно:
myrand:
rdrand eax;
and al, 7fh;
cmp al, 22h;
jb myrand;
dec eax;
cmp al, 'y';
je myrand;
cmp al, 'Y';
je myrand;
Цікава частина - обчислення кількості пробілів. Він повинен генерувати такі числа (приклад для N = 9):
7 1
5 2
3 3
1 4
3
1 2
3 1
5 0
7
Числа приймаються по черзі з двох арифметичних прогресій. Перший знижується з кроком -2, а другий йде з кроком 1. Коли перша прогресія доходить до -1 (в середині X), виникає збіг (-1 видаляється), а потім прогресії змінюють напрямок.
Прогресії зберігаються в регістрах ebx
і edx
- високих частинах bh
і dh
зберігають поточне число, а низькі частини bl
і dl
зберігають крок. Для чергування між прогресіями код заміняє регістри на xchg
.
Коли прогресія досягає -1 (навколо mylab
мітки), вона збільшує обидва регістри, перемикаючи кроки з -2, 1
на -1, 2
. Це також змінює ролі регістрів, тож воно замінює високі частини регістрів.
В кінці функції він зберігає нульовий байт для позначення кінця рядка.