Kod maszynowy x86-64, 26 bajtów
31 C9 8D 71 01 89 F8 FF C1 99 F7 F9 85 D2 75 03 0F AF F1 39 F9 7C EE 89 F0 C3
Powyższy kod definiuje funkcję, która przyjmuje pojedynczy parametr (wartość wejściowa, dodatnia liczba całkowita) w EDI
(zgodnie z konwencją wywoływania AMD V System64 używaną w Gnu / Unix) i zwraca pojedynczy wynik (iloczyn dzielników) EAX
.
Wewnętrznie oblicza iloczyn dzielników za pomocą (wyjątkowo nieefektywnego) algorytmu iteracyjnego, podobnego do złożenia C przez pizzapants184 . Zasadniczo używa licznika do przechodzenia przez wszystkie wartości między 1 a wartością wejściową, sprawdzając, czy bieżąca wartość licznika jest dzielnikiem wejścia. Jeśli tak, mnoży to przez działający produkt ogółem.
Mnemoniki języka asemblera:
; Parameter is passed in EDI (a positive integer)
ComputeProductOfDivisors:
xor ecx, ecx ; ECX <= 0 (our counter)
lea esi, [rcx + 1] ; ESI <= 1 (our running total)
.CheckCounter:
mov eax, edi ; put input value (parameter) in EAX
inc ecx ; increment counter
cdq ; sign-extend EAX to EDX:EAX
idiv ecx ; divide EDX:EAX by ECX
test edx, edx ; check the remainder to see if divided evenly
jnz .SkipThisOne ; if remainder!=0, skip the next instruction
imul esi, ecx ; if remainder==0, multiply running total by counter
.SkipThisOne:
cmp ecx, edi ; are we done yet? compare counter to input value
jl .CheckCounter ; if counter hasn't yet reached input value, keep looping
mov eax, esi ; put our running total in EAX so it gets returned
ret
Fakt, że IDIV
instrukcja używa zakodowanych operandów do dywidendy, trochę obciąża mój styl, ale myślę, że jest to całkiem dobre dla języka, który nie ma wbudowanych, ale podstawowe gałęzie arytmetyczne i warunkowe!