x86-16 machine code, 18 bytes
00000000: 89c1 9988 0e09 0150 d40a 7502 02d4 58e2 .......P..u...X.
00000010: f2c3 ..
Listing:
89 C1 MOV CX, AX ; input number as loop counter
99 CWD ; zero DX as running sum
DIVLOOP:
88 0E 0109 MOV BYTE PTR[AAM1+1], CL ; move loop counter to divisor
50 PUSH AX ; save input number
AAM1:
D4 0A AAM ; ZF if (AL % CL == 0), AH = quotient
75 02 JNZ END_LOOP ; if not ZF, continue loop
02 D4 ADD DL, AH ; otherwise add to running sum
END_LOOP:
58 POP AX ; restore input number
E2 F2 LOOP DIVLOOP ; loop until CL == 0
C3 RET ; return to caller
Callable function, input N
in AX
, result in DX
.
Inspired by @CodyGray's excellent answer, and the comment "It sure seems like there should be a way to make this shorter"
I just had to try!
As Cody mentioned, Using DIV
/IDIV
is inconvenient because it clobbers two registers including the dividend. Another is that the ZF
flag is set when the quotient is 0
, however in this case we're only interested in when the remainder is 0
. Enter AAM
, a trusty and underrated byte-sized division/modulo instruction that can be golfy. Even though it does clobber the dividend just like DIV
, it will set ZF
when the remainder is 0
which is what we want here. It's downside is that the divisor is encoded in the instruction opcode, which can be modified at runtime at a cost of 4 bytes (in real mode at least).