0

I'm a total newbie and I'm triyng to write the code to count the number of set bits in a 32-bit integer.

I wrote this but I get a lot of errors:

.586
.model flat,stdcall
.stack 4096

; Windows libraries

includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib

.DATA

data:   .LONG 0x0F0F0101
count:  .BYTE 0x00

.TEXT

_main:  NOP
        MOVB $0x00, %CL
        MOVL data, %EAX
comp:   CMPL $0x00, %EAX
        JE end
        SHRL %EAX
        ADCB $0x0, %CL
        JMP comp
end:    MOVB %CL, count
        RET

I have the following error:

C:\Users\RaiN\Desktop\Test\test1.asm(20) : error A2034: must be in segment block
C:\Users\RaiN\Desktop\Test\test1.asm(25) : error A2108: use of register assumed to ERROR
C:\Users\RaiN\Desktop\Test\test1.asm(25) : error A2008: syntax error : .
C:\Users\RaiN\Desktop\Test\test1.asm(26) : error A2108: use of register assumed to ERROR
C:\Users\RaiN\Desktop\Test\test1.asm(26) : error A2008: syntax error : .
C:\Users\RaiN\Desktop\Test\test1.asm(28) : error A2008: syntax error : .
C:\Users\RaiN\Desktop\Test\test1.asm(29) : error A2108: use of register assumed to ERROR
C:\Users\RaiN\Desktop\Test\test1.asm(30) : error A2008: syntax error : $0x00
C:\Users\RaiN\Desktop\Test\test1.asm(31) : error A2008: syntax error : dato
C:\Users\RaiN\Desktop\Test\test1.asm(32) : error A2108: use of register assumed to ERROR
C:\Users\RaiN\Desktop\Test\test1.asm(32) : error A2008: syntax error : CMPL
C:\Users\RaiN\Desktop\Test\test1.asm(34) : error A2008: syntax error : !%
C:\Users\RaiN\Desktop\Test\test1.asm(35) : error A2008: syntax error : $0x0
C:\Users\RaiN\Desktop\Test\test1.asm(37) : error A2108: use of register assumed to ERROR
C:\Users\RaiN\Desktop\Test\test1.asm(37) : error A2008: syntax error : MOVB
C:\Users\RaiN\Desktop\Test\test1.asm(38) : error A2088: END directive required at end of file
C:\Users\RaiN\Desktop\Test\test1.asm(33) : error A2107: cannot have implicit far jump or call to near label
C:\Users\RaiN\Desktop\Test\test1.asm(36) : error A2107: cannot have implicit far jump or call to near label

How can I solve this?

Thank you very much!!!

rkhb
  • 14,159
  • 7
  • 32
  • 60
Rosikolo
  • 11
  • 1
  • 4
    Cheat: write it in C, compile using -S switch, then review the generated assembler! – Yimin Rong Sep 20 '16 at 21:33
  • 5
    What assembler do you use? Your output awefully looks like you try to use GNU assembler syntax with the Microsoft assembler. This can't work. – fuz Sep 20 '16 at 22:25
  • I use WinAsm Studio.For a test I need to use a Microsoft Assembler – Rosikolo Sep 20 '16 at 23:00
  • @Yimin Rong Cheating would be using the POPCNT instruction. ;) – icecreamsword Sep 21 '16 at 00:43
  • @icecreamsword: yeah, at least give yourself a challenge and slice the integer up into nibbles for a PSHUFB 4-bit LUT :) – Peter Cordes Sep 21 '16 at 00:47
  • 2
    This isn't exactly a new question. [Last time](http://stackoverflow.com/a/27053187/2189500) I wrote this, the requirement was to use inline asm. But turning this to 'real' assembler shouldn't be too hard. That said, the 5's and 3's method from the [Bit Twiddling Hacks](https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel) has been known to be faster than the popcnt instruction (depending on the specific cpu's implementation), and doesn't require asm. – David Wohlferd Sep 21 '16 at 03:43
  • Thank you David but I'm sorry, I'm at the beginning and I can't understand your suggestion. What do you mean with inline asm and 5's and 3's method? Thank you. – Rosikolo Sep 21 '16 at 08:43
  • I have found another tool named SASM in which I can use also the AT&T syntax format and now the code works! The problem is another... Do exist in Assembly an istruction like "System Pause"? When I run the .exe files I have generated, I have not the ability to insert input and to watch the result. – Rosikolo Sep 21 '16 at 11:16
  • @Rosikolo: Run your code in a debugger if you want to single-step the instructions. There's no single asm instruction that makes your program wait for input. You'd have to do that with a system call to the OS. – Peter Cordes Sep 22 '16 at 02:13

2 Answers2

0

New code is:

.text
.global main
main:
    movq %rsp, %rbp #for correct debugging
    # write your code here
.DATA
stringa:    .ASCIZ "Questa è la stringa di caratteri ASCII che usiamo come esempio"

lettera:     .BYTE 'e'
conteggio:   .BYTE 0x00

.TEXT
_main:        NOP
              MOV $0x00, %CL
              LEA stringa, %ESI
              MOV lettera, %AL
comp:         CMPB $0x00, (%ESI)
              JE fine
              CMP (%ESI), %AL
              JNE poi
              INC %CL
poi:          INC %ESI
              JMP comp
fine:         MOV %Cl, conteggio

              INT $0x27              
              RET
Nathan Fellman
  • 122,701
  • 101
  • 260
  • 319
Rosikolo
  • 11
  • 1
0

What you're trying to calculate is called Hamming Weight You can achieve this by using Logical shifts and Bit Masking

Here is a simple program. Im assuming youre using x86 assembly.

.386
.model flat,stdcall
option casemap:none

include kernel32.inc
includelib kernel32.lib

.code
start:
    mov eax,1h             ;your number in eax 100 is sample here
    mov ecx,0h             ;is the counter register
    xor edx,edx            ;is done to make edx 0, you can also do mov edx,0
notDoneWithNumber:
    cmp eax,0
    je done
    mov edx,eax            ;edx is here a compare register, not nice, but it works
    shr eax,1              ;we push all the bits one place to the right, bits at position 1 will be "pushed out of the byteword"
    and edx,1h             ;make sure we only get, wether the last bit is set or not(thats called bitmaking) 
    cmp edx,0h
    jz notDoneWithNumber   ;if the found value is a zero we can skip the inc of the count register
    inc ecx
    jmp notDoneWithNumber
done:                      ;register ecx will now hold your hamming weight
end start
jAC
  • 5,195
  • 6
  • 40
  • 55
  • Thank you for the code but I have to improve the solution I have posted before... Code could be built but I can't execute them on DOS. I don't understand how can I insert the I/O Function and the System Pause. – Rosikolo Sep 21 '16 at 12:48
  • Oh I thought you would just need a working algorithm. When it comes to DOS im afraid I cant really help you, sorry. – Burgesstorm Sep 21 '16 at 13:24
  • `and edx, 1` already sets ZF based on the result. You don't need `cmp edx, 0`. You can simplify the branching, too, by using `shr eax / jnz notDone` as the jump at the bottom of the loop. i.e. repeat the loop if the shift left any non-zero bits. (This works best if you unconditionally `add ecx, edx` after masking it, instead of conditionally running an `inc`. It's a lot more efficient to just add zero than to use a hard-to-predict branch to skip an `inc`.) – Peter Cordes Sep 22 '16 at 02:19
  • Of course, this whole one-bit-at-a-time algorithm is very slow compared to https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel, or especially SSSE3 pshufb (slice the input into 4-bit nibbles, and use those as parallel LUT indices). Or of course the `popcnt` instruction is ideal for one integer at a time on CPUs that support it. – Peter Cordes Sep 22 '16 at 02:21
  • Yes you're right that algortihm is very slow. Im kind of new to assembly too, to be honest and i wanted to give an answer, thats easy to understand and clearly structured. – Burgesstorm Sep 22 '16 at 17:04