x87 Kode Mesin, 11 byte
D9 EB
DA 31
D9 F2
DD D8
DA 09
C3
Byte kode di atas mendefinisikan fungsi yang menghitung luas n-gon reguler dengan apothem 1. Menggunakan instruksi FPU x87 (unit floating-point klasik pada prosesor x86) untuk melakukan perhitungan ini.
Mengikuti konvensi pemanggilan berbasis register x86 standar (dalam hal ini, __fastcall
), argumen fungsi adalah sebuah pointer ke integer, diteruskan dalam ECX
register. Hasil fungsi adalah nilai titik-mengambang, dikembalikan di bagian atas tumpukan titik-mengambang x87 (register ST0
).
Cobalah online!
Mnemonik perakitan tidak dikumpulkan:
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
Seperti yang Anda lihat, ini pada dasarnya hanya perhitungan langsung dari rumus yang diberikan,
hasil = n * tan (π / n)
Hanya beberapa hal menarik yang menunjukkan:
- FPU x87 memiliki instruksi khusus untuk memuat nilai konstan PI (
FLDPI
). Ini jarang digunakan, bahkan pada hari itu (dan jelas jauh lebih sedikit sekarang), tetapi ukurannya lebih pendek daripada memasukkan konstanta ke dalam biner Anda dan memuatnya.
- Instruksi FPU x87 untuk menghitung garis singgung,,
FPTAN
menggantikan nilai register input (bagian atas tumpukan FPU) dengan hasilnya, tetapi juga mendorong konstanta 1,0 ke atas tumpukan FPU. Ini dilakukan untuk kompatibilitas dengan 8087 (saya tidak tahu mengapa ini dilakukan pada 8087; mungkin bug). Itu berarti kita perlu membuang nilai yang tidak dibutuhkan ini dari tumpukan. Cara tercepat dan terpendek untuk melakukannya adalah sederhana FSTP st0
, seperti yang kami gunakan di sini. Kita juga bisa melakukan multiply-and-pop , karena mengalikan dengan 1,0 tidak akan mengubah hasilnya, tetapi ini juga 2 byte (jadi tidak ada kemenangan dalam ukuran kode), mungkin akan mengeksekusi lebih lambat, dan dapat memperkenalkan ketidakpastian yang tidak perlu ke dalam hasil.
Meskipun seorang programmer atau kompiler modern akan menggunakan set instruksi SSE (dan yang lebih baru), daripada x87 yang menua, ini akan membutuhkan lebih banyak kode untuk diimplementasikan, karena tidak ada instruksi tunggal untuk menghitung garis singgung dalam SPA yang lebih baru ini.
Area@RegularPolygon
seharusnyaArea@*RegularPolygon
; seperti sekarang, tidak bisa ditangkap dalam variabel. Artinya,f = Area@RegularPolygon; f[3]
tidak berfungsi. Diskusi meta yang relevan