Машинный код x86-64, 26 байт
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
Приведенный выше код определяет функцию, которая принимает один параметр (входное значение, положительное целое число) EDI
(в соответствии с соглашением о вызовах System64 AMD64, используемым в Gnu / Unix) и возвращает один результат (произведение делителей) в EAX
.
Внутренне он вычисляет произведение делителей, используя (крайне неэффективный) итерационный алгоритм, аналогичный представлению C в pizzapants184 . В основном, он использует счетчик для циклического перебора всех значений между 1 и входным значением, проверяя, является ли текущее значение счетчика делителем входного значения. Если это так, он умножает это на текущий итоговый продукт.
Неуправляемый язык ассемблера
; 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
Тот факт, что IDIV
инструкция использует жестко запрограммированные операнды для дивидендов, немного ограничивает мой стиль, но я думаю, что это довольно хорошо для языка, который не имеет встроенных модулей, но имеет базовые арифметические и условные ветви!