x87 Код машини, 11 байт
D9 EB
DA 31
D9 F2
DD D8
DA 09
C3
Вищеописані байти коду визначають функцію, яка обчислює площу регулярного n-gon з апотемою 1. Для цього використовується обчислення x87 FPU (класичний блок з плаваючою комою на процесорах x86).
Після стандартної конвенції викликів на основі реєстру x86 (в даному випадку __fastcall
) аргумент функції є вказівником на ціле число, передане в ECX
регістр. Результатом функції є значення з плаваючою комою, повернене у верхній частині стека x87 з плаваючою комою (регістр ST0
).
Спробуйте в Інтернеті!
Невикольована збірна мнемоніка:
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
Як бачимо, це в основному просто пряме обчислення даної формули,
результат = n * tan (π / n)
Вказує лише кілька цікавих речей:
- X87 FPU має спеціалізовану інструкцію для завантаження постійного значення PI (
FLDPI
). Це використовувалося рідко, навіть у той час (і, очевидно, набагато менше, ніж зараз), але він коротший за розміром, ніж вбудовувати константу у свій двійковий і завантажувати це.
- Інструкція x87 FPU для обчислення дотичної,
FPTAN
замінює значення вхідного регістру (вершина стека FPU) результатом, але також висуває постійну 1,0 на вершину стека FPU. Це робиться для зворотної сумісності з 8087 (я поняття не маю, чому це було зроблено на 8087; можливо, помилка). Це означає, що нам потрібно вивести це зайве значення зі стека. Найшвидший і найкоротший спосіб зробити це простий FSTP st0
, як ми тут використовуємо. Ми могли б також зробити множину та попс , оскільки множення на 1.0 не змінить результат, але це також 2 байти (тому виграш не в розмірі коду), ймовірно, буде виконуватися повільніше і може внести зайву невизначеність у результат.
Хоча сучасний програміст або компілятор використовує набір інструкцій SSE (і пізнішої версії), а не старіння x87, для цього потрібно буде більше коду для реалізації, оскільки немає жодної інструкції для обчислення дотичної в цих нових ISA.
Area@RegularPolygon
повинно бутиArea@*RegularPolygon
; як зараз, він не може бути захоплений змінною. Тобтоf = Area@RegularPolygon; f[3]
не працює. Відповідна мета дискусія