Código de máquina x87, 11 bytes
D9 EB
DA 31
D9 F2
DD D8
DA 09
C3
Os bytes de código acima definem uma função que calcula a área de um n-gon regular com um apótema de 1. Ele usa instruções x87 FPU (a unidade clássica de ponto flutuante nos processadores x86) para fazer esse cálculo.
Após uma convenção de chamada padrão baseada em registro x86 (neste caso __fastcall
), o argumento da função é um ponteiro para o número inteiro passado no ECX
registro. O resultado da função é um valor de ponto flutuante, retornado na parte superior da pilha de ponto flutuante x87 (registrador ST0
).
Experimente online!
Mnemônicos de montagem não destruídos:
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 você pode ver, isso é basicamente apenas um cálculo direto da fórmula fornecida,
result = n * tan (π / n)
Apenas algumas coisas interessantes merecem destaque:
- A xU FPU possui uma instrução dedicada para carregar o valor constante PI (
FLDPI
). Isso raramente era usado, mesmo no passado (e obviamente muito menos agora), mas é menor em tamanho do que incorporar uma constante ao seu binário e carregá-lo.
- A instrução x87 da FPU para calcular a tangente
FPTAN
substitui o valor do registro de entrada (a parte superior da pilha da FPU) pelo resultado, mas também coloca uma constante 1,0 na parte superior da pilha da FPU. Isso é feito para compatibilidade retroativa com o 8087 (não tenho idéia do por que isso foi feito no 8087; provavelmente um bug). Isso significa que precisamos extrair esse valor desnecessário da pilha. A maneira mais rápida e curta de fazer isso é simples FSTP st0
, como usamos aqui. Também poderíamos ter feito um multiplique e pop , pois multiplicar por 1.0 não mudará o resultado, mas isso também é de 2 bytes (portanto, não há ganho no tamanho do código), provavelmente será executado mais lentamente e poderá introduzir indeterminação desnecessária. o resultado.
Embora um programador ou compilador moderno usasse o conjunto de instruções SSE (e posterior), em vez do x87 antigo, isso exigiria mais código para implementar, pois não há uma instrução única para calcular uma tangente nesses novos ISAs.
Area@RegularPolygon
deveria serArea@*RegularPolygon
; como está agora, não pode ser capturado em uma variável. Ou seja,f = Area@RegularPolygon; f[3]
não funciona. Meta-discussão relevante