Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NASM: Count how many bits in a 32 Bit number are set to 1

I have a 32 Bit number and want to count know how many bits are 1.

I'm thinking of this pseudocode:

mov eax, [number]
while(eax != 0)
{
  div eax, 2
  if(edx == 1)
  {
   ecx++;
  } 
  shr eax, 1
}

Is there a more efficient way?

I'm using NASM on a x86 processor.

(I'm just beginning with assembler, so please do not tell me to use code from extern libraries, because I do not even know how to include them ;) )

(I just found How to count the number of set bits in a 32-bit integer? which also contains my solution. There are other solutions posted, but unfortunatly I can't seem to figure out, how I would write them in assembler)

like image 810
citronas Avatar asked May 28 '10 18:05

citronas


2 Answers

The most efficient way (in terms of execution time, anyway) is to have a lookup table. Obviously you're not going to have a 4-billion entry table, but you could break the 32 bits down into 8-bit chunks and only need a 256-entry table, or further down into 4-bit chunks and only need 16 entries. Good luck!

like image 169
Carl Norum Avatar answered Oct 11 '22 18:10

Carl Norum


In processors that have SSE4 support, you have the POPCNT instruction that does this for you.

The most naive algorithm is actually faster than what you thought up (DIV instructions are really slow).

mov eax, [number]
xor ecx,ecx
loop_start:
  test eax,1
  jnz next
  inc ecx
next:
  shr eax, 1
  mov eax,ecx

Regarding your comment about previous SO answers, I'm going to take an example answer from there and walk you through how I'll convert it.

long count_bits(long n) {     
  unsigned int c; // c accumulates the total bits set in v
  for (c = 0; n; c++) 
    n &= n - 1; // clear the least significant bit set
  return c;
}

(I'm going to assume you know how to define a function and fun stuff like that). What is needed is a very simple loop, a counter variable (traditionally, ecx is both the index and a counter), and bit testing instructions.

    mov edx,n
    xor ecx,ecx
loop_start:
    test edx,edx
    jz end
    mov ebx,edx
    dec ebx
    and edx,ebx
    inc ecx
    jmp loop_start
end:
    mov eax,ecx
    ret

Implementing something like the Hamming Weight algorithm in assembly isn't complicated, but is just complicated enough that you'd rather not do it as an initial homework problem.

like image 23
Daniel Goldberg Avatar answered Oct 11 '22 20:10

Daniel Goldberg