Skip to main content
1 of 3
Titus
  • 14.8k
  • 1
  • 24
  • 41

#C64 machine code, 29 bytes

sub routine; assumes input in A and X registers; returns result in $FB/$FC

machine code:

85 02 a9 00 85 FB 85 FC
E8 CA E4 02 30 0E 8A F0
F8 4A 90 FB E6 FB 90 F7
E6 FC D0 F3 60

assembler source code:

        STA $02     store lower bound in $02
        LDA #0      init result to 0
        STA $FB
        STA $FC
        INX         increment upper bound
LOOP1:  DEX         decrement upper bound
        CPX $02     compare to lower bound
        BMI :ENDE   if smaller, return
        TXA         copy X to A
LOOP2:  BEQ :LOOP1  if 0, next outer loop
        LSR         shift right
        BCC :LOOP2  if carry is clear, next inner loop
        INC $FB     else increment result
        BCC :LOOP2
        INC $FC
        BNE :LOOP2  next inner loop
ENDE:   RTS

notes

  • The maximum possible number of set bits is 1024; so incrementing the MSB (INC $FC) always has a non-zero result; hence BNE :LOOP always branches.
  • BEQ following that BNE never branches, even not if the accumulator is zero; but that doesn´t matter: LSR will clear the carry and set the zero flag, BCC will hop to LOOP2 and the BEQ to LOOP1.
  • I´m not completely sure (it´s been so long I actually coded on the C64), but it may fail if the range is larger than 127: CPX $02 is actually a substraction; if the result is >127, the negative flag may be set, so BMI would end the routine.
  • I hope I got the branching parameters correct - I assembled the machine code manually.
Titus
  • 14.8k
  • 1
  • 24
  • 41