0

So I'm trying things out with assembly and I have a problem that involves counting set bits in a register. I have the code below but I can't seem to figure out how I'll stop this loop cause it goes on and on shifting the bits and ends up with an invalid count.

addi x9, x0, 0xff00
addi x10, x0, 1 # adding counter for AND function
addi x11, x0, 0 # bit counter count
addi x12, x0, 0 # to compare 0

and x13, x9, x10
#bge x10, x9, func_c             # this somehow works with positive numbers only
bne x13, x12,func_a  # go to func_a if not equal to 0
beq x13, x12, func_b # else go to funcb_b

func_a:
addi x11, x11, 1     # add one to bit count
slli x10, x10, 1     # shift left
and x13, x9, x10     # new x13
bne x13, x12, func_a # not equal to 0
beq x13, x12, func_b

func_b:
slli x10, x10, 1 # shift left
and x13, x9, x10
#jal x0, -40 # go to line 7      # this jumped to the commented `bge` instruction above
jal x0, -36 # go to line 8

func_c:
add x20, x0, x11 # store final count
Dev Yego
  • 539
  • 2
  • 12
  • `beq x13, x12, func_b` is useless after the `func_a` loop; execution goes to `func_b` whether it's taken or falls through. `b next_instruction` is always a no-op. Also, you don't need to copy the zero-register to `x12` to compare against zero later, just compare against `x0` any time you want to check on something being non-zero. Or if RISC-V has a `beqz` pseudo-instruction for comparing to zero, use that. – Peter Cordes Dec 07 '22 at 04:32
  • I don't understand why you have multiple labels instead of one loop. An answer on [Count the number of set bits in a 32-bit integer](https://stackoverflow.com/a/67619076) shows the two standard simple algorithms. Since you're incrementing the count by one every iteration, your loop body should be clearing one set bit every iteration. But it's not, it's just left-shifting by 1 (and looping while there are any set bits in the high 16, which seems like a weird subset of the register to check.) – Peter Cordes Dec 07 '22 at 04:39
  • 1
    Loop termination is not really specific to some assembly language, unless there's some instruction(s) you don't understand. Write your algorithm, including loop termination, in a high-level language like C (test it) and then do the same in assembly. – Erik Eidt Dec 07 '22 at 05:02
  • Would strongly suggest you use labels for the jump destinations as that's more flexible and easier to maintain and also easier for anyone trying to answer your question! – adrianmcmenamin Dec 08 '22 at 11:11
  • `bge` is intended to work with signed numbers, use `bgeu` if you want to ignore signs. As far as your actual question, you can set a register to -1 and shift it left by 1 each time you loop, when that register equals zero you will have shifted 32 times (since -1 in binary is all ones.) – puppydrum64 Dec 08 '22 at 16:16

0 Answers0