Código da máquina x86-64, 26 bytes
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
O código acima define uma função que recebe um único parâmetro (o valor de entrada, um número inteiro positivo) em EDI
(seguindo a convenção de chamada do System V AMD64 usada no Gnu / Unix) e retorna um único resultado (o produto dos divisores) em EAX
.
Internamente, ele calcula o produto de divisores usando um algoritmo iterativo (extremamente ineficiente), semelhante à submissão C de pizzapants184 . Basicamente, ele usa um contador para percorrer todos os valores entre 1 e o valor de entrada, verificando se o valor atual do contador é um divisor da entrada. Nesse caso, ele multiplica isso no produto total em execução.
Mnemônicos de linguagem assembly não destruídos:
; 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
O fato de a IDIV
instrução usar operandos codificados para os dividendos diminui um pouco meu estilo, mas acho que isso é muito bom para uma linguagem que não tem built-ins, mas aritmética básica e ramificações condicionais!