Skip to main content
3 of 3
Commonmark migration

6510 machine code, 29 28 bytes

sub routine;
takes input from A (lower bound) and X (upper bound) registers;
returns result in A (MSB) and Y (LSB)

machine code:

85 02 A0 00 84 FC E8 CA
E4 02 30 OD 8A F0 F8 46
90 FB E8 90 F8 E6 FC D0
F4 A5 FC 60

source code:

        STA $02     store lower bound in $02
        LDY #0      init result to 0 (Y = LSB, $FC=MSB)
        STY $FC
        INX         increment upper bound
LOOP1:  DEX         decrement upper bound
        CPX $02     compare to lower bound
        BMI :FINISH 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
        INY         else increment result
        BCC :LOOP2
        INC $FC
        BNE :LOOP2  next inner loop
FINISH: LDA $FC
        RTS

notes

  • With only 8 bit input possible, the maximum 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 (so I could actually add two to the BEQ parameter and save one cycle); 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