Código de máquina x87, 11 bytes
D9 EB
DA 31
D9 F2
DD D8
DA 09
C3
Los bytes de código anteriores definen una función que calcula el área de un n-gon regular con una apotema de 1. Utiliza instrucciones de FPU x87 (la unidad clásica de punto flotante en los procesadores x86) para hacer este cálculo.
Siguiendo una convención estándar de llamadas basadas en registros x86 (en este caso __fastcall
), el argumento de la función es un puntero al número entero, pasado en el ECX
registro. El resultado de la función es un valor de coma flotante, devuelto en la parte superior de la pila de coma flotante x87 (registro ST0
).
Pruébalo en línea!
Mnemónicos de ensamblaje sin golf:
D9 EB fldpi ; load constant PI at top of FPU stack
DA 31 fidiv DWORD PTR [ecx] ; divide PI by integer input (loaded from pointer
; in ECX), leaving result at top of FPU stack
D9 F2 fptan ; compute tangent of value at top of FPU stack
DD D8 fstp st0 ; pop junk value (FPTAN pushes 1.0 onto stack)
DA 09 fimul DWORD PTR [ecx] ; multiply by integer input (again, loaded via ECX)
C3 ret ; return control to caller
Como puede ver, esto es básicamente un cálculo directo de la fórmula dada,
resultado = n * tan (π / n)
Solo un par de cosas interesantes se destacan:
- La FPU x87 tiene una instrucción dedicada para cargar el valor constante PI (
FLDPI
). Esto rara vez se usaba, incluso en el pasado (y obviamente mucho menos ahora), pero es más corto en tamaño que incrustar una constante en su binario y cargar eso.
- La instrucción x87 FPU para calcular la tangente,
FPTAN
reemplaza el valor del registro de entrada (la parte superior de la pila FPU) con el resultado, pero también empuja un constante 1.0 en la parte superior de la pila FPU. Esto se hace para la compatibilidad con el 8087 (no tengo idea de por qué esto se hizo en el 8087; probablemente sea un error). Eso significa que necesitamos extraer este valor innecesario de la pila. La forma más rápida y rápida de hacerlo es simple FSTP st0
, como la que usamos aquí. También podríamos haber hecho una multiplicación y pop , ya que multiplicar por 1.0 no cambiará el resultado, pero esto también es de 2 bytes (por lo que no hay ganancia en el tamaño del código), probablemente se ejecutará más lentamente y puede introducir indeterminaciones innecesarias en el resultado.
Aunque un programador o compilador moderno usaría el conjunto de instrucciones SSE (y posterior), en lugar del antiguo x87, esto requeriría más código para implementar, ya que no hay una sola instrucción para calcular una tangente en estas ISA más nuevas.
Area@RegularPolygon
debería serArea@*RegularPolygon
; tal como está ahora, no se puede capturar en una variable. Es decir,f = Area@RegularPolygon; f[3]
no funciona. Meta discusión relevante