código de máquina x86, 70 bytes
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
Mi código ejecutable, desmontado:
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
Es una función que recibe el tamaño de la X en ecx, y un puntero al búfer de salida en edx.
Llena el búfer de salida secuencialmente con bytes. Hay 2 * n - 1
iteraciones (igual al número de caracteres que no son espaciales para generar). En cada iteración, hace lo siguiente:
- Generar un número aleatorio
- Juega con el número para ajustarlo al rango; si es malo, regrese y genere nuevamente
- Imprime el caracter aleatorio
- Imprima una nueva línea (cada dos iteraciones)
- Imprima la cantidad adecuada de espacios
La conversión de un número aleatorio a un carácter aleatorio no es notable:
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 interesante es el cálculo del número de espacios. Debe generar los siguientes números (ejemplo para N = 9):
7 1
5 2
3 3
1 4
3
1 2
3 1
5 0
7
Los números se toman alternativamente de dos progresiones aritméticas. El primero baja con el paso -2, y el segundo sube con el paso 1. Cuando la primera progresión llega a -1 (en el medio de la X), hay una falla (se elimina -1), y luego Las progresiones cambian de dirección.
Las progresiones se almacenan en registros ebx
y edx
- las partes altas bh
y dh
almacenan el número actual, y las partes bajas bl
y dl
almacenan el paso. Para alternar entre las progresiones, el código intercambia los registros con xchg
.
Cuando la progresión llega a -1 (alrededor de la mylab
etiqueta), aumenta ambos registros, cambiando los pasos de -2, 1
a -1, 2
. Esto también cambia las funciones de los registros, por lo que intercambia las partes altas de los registros.
Al final de la función, almacena un byte cero para indicar el final de la cadena.