Announcement

Collapse
No announcement yet.

Bit counts. Quad integer

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Bit counts. Quad integer

    Does someone have a 64-bit version of the asm code to share found at https://forum.powerbasic.com/forum/u...088#post502088

    Thanks in advance!
    --
    Olav Bergesen

  • #2
    What if you modify Paul's code to do first and second half of a quad.

    Code:
    #COMPILE EXE '#Win9.07#
    #DIM ALL
    #REGISTER NONE
    #INCLUDE "Win32Api.inc"
    
    MACRO ShowCount = MessageBox(%HWND_DESKTOP, BIN$(q / &H100000000, 32) & " " & BIN$(q, 32) & $CRLF & FORMAT$((QuadPopulationCount(VARPTR(Q)))), "QuadPopulationCount", %MB_OK OR %MB_TOPMOST)
    '______________________________________________________________________________
    
    FUNCTION QuadPopulationCount(BYVAL pQuad AS QUAD POINTER) AS LONG
     'Based on the ASM master, Paul. See https://forum.powerbasic.com/forum/user-to-user-discussions/programming/42811-bits-count?p=502090#post502090
    
     !MOV EAX, pQuad
     !MOV EAX, [EAX]
     !MOV EDX, EAX
     !SHR EAX, 1
     !AND EAX, &h055555555
     !SUB EDX, EAX
     !MOV EAX, EDX
     !SHR EDX, 2
     !AND EAX, &h033333333
     !AND EDX, &h033333333
     !ADD EAX, EDX
     !MOV EDX, EAX
     !SHR EAX, 4
     !ADD EAX, EDX
     !AND EAX, &h00F0F0F0F
     !IMUL EAX, &h01010101
     !SHR EAX,24
    
     !MOV FUNCTION, EAX
     !MOV EAX, pQuad
     !ADD EAX, 4
     !MOV EAX, [EAX]
     !MOV EDX, EAX
     !SHR EAX, 1
     !AND EAX, &h055555555
     !SUB EDX, EAX
     !MOV EAX, EDX
     !SHR EDX, 2
     !AND EAX, &h033333333
     !AND EDX, &h033333333
     !ADD EAX, EDX
     !MOV EDX, EAX
     !SHR EAX, 4
     !ADD EAX, EDX
     !AND EAX, &h00F0F0F0F
     !IMUL EAX, &h01010101
     !SHR EAX,24
     !ADD FUNCTION, EAX
    
    END FUNCTION
    '______________________________________________________________________________
    
    FUNCTION PBMAIN AS LONG
     LOCAL q AS QUAD
    
     q = &H0000000000000000 : ShowCount
     q = &H0000000000000001 : ShowCount
     q = &H0000000100000001 : ShowCount
     q = &H000000FF000000FF : ShowCount
    
    END FUNCTION
    '______________________________________________________________________________
    '

    Comment


    • #3
      I think slower in assembly, but here is my try at the job.

      Pierre, I have got to try to remember using the word "FUNCTION" in assembly code (instead of separate variable like I used.

      Code:
      #compile exe
      #dim all
      function CountBitsInQuad(byval TargQ as quad) as long
        #register none
        local LDWord, UDWord as dword
        local TheCount as long
        'ebx source  (has single bit set, shifted)
        'ecx bit counter
        LDWord = lo(dword, TargQ)
        UDWord = hi(dword, TargQ)
        ! push ecx
        ! xor ecx, ecx    'set bit counter to 0
        ! xor ebx, ebx    'set bit offset to 0
        ChkLower:
          ! bt LDWord, ebx  'test for set bit
          ! jnc ChkUpper    'skip to upper if bit not set
          ! call bCount     'increment count if bit is set
        ChkUpper:
          ! bt UDWord, ebx  'bit test to CF
          ! jnc NextBit      '
          ! call bCount     '
        NextBit:
          ! inc ebx         'next offset
          ! cmp ebx, 32     'done if 32 because MSb is 31
          ! jz CountDone
          ! jmp ChkLower
        bCount:
          ! inc ecx
        ! ret
        CountDone:
        ! mov TheCount, ecx
        ! pop ecx
        function = TheCount
      end function
      function pbmain () as long
        local OneBits as long
        OneBits = CountBitsInQuad(&b100110010010000000000110001110000111101&&)    '15
        ? str$(OneBits)
      end function
      See ya!
      Dale

      Comment


      • #4
        Try this...not optimized, but does count the bits
        code:

        #COMPILE EXE
        #DIM ALL

        FUNCTION PBMAIN () AS LONG
        LOCAL q AS QUAD
        LOCAL x, y AS LONG
        x = &H10101010
        y = CntBitsSetDword(BYVAL VARPTR(x))
        MSGBOX STR$(y)
        q= &h1010101010101010
        x = CntBitsSetQuad(BYVAL VARPTR(q))
        MSGBOX STR$(x)
        END FUNCTION

        FASTPROC CntBitsSetDword(BYVAL x AS LONG) AS LONG
        !mov eax, x
        !popcnt eax, [eax] 'counts set bits
        !mov x, eax
        END FASTPROC = x

        FASTPROC CntBitsSetQuad(BYVAL x AS LONG) AS LONG
        !mov eax, x
        !popcnt ebx, [eax]
        !popcnt eax, [eax+4]
        !add eax, ebx
        !mov x, eax
        END FASTPROC = x


        Hope it helps
        Frank C

        Comment


        • #5
          A little clearer

          #COMPILE EXE
          #DIM ALL

          FUNCTION PBMAIN () AS LONG
          LOCAL q AS QUAD
          LOCAL x, y AS LONG
          LOCAL d1, d2, d AS DWORD
          LOCAL i AS INTEGER
          LOCAL b AS BYTE

          'Integer or Word
          i = &h0101
          x = CntBitsSet(BYVAL VARPTR(i))
          MSGBOX "Int, " + STR$(x)

          'Byte
          b = &h33
          x = CntBitsSet(BYVAL VARPTR(b))
          MSGBOX " byte , " + STR$(x)

          'DWord
          d = &H10101010
          y = CntBitsSet(BYVAL VARPTR(d))
          MSGBOX "Dword, " + STR$(y)

          'Quad
          q = 0
          q = &h1010101050505050
          ' q = &hFFFFFFFFFFFFFFFF
          x = CntBitsSetQuad(BYVAL VARPTR(q))
          MSGBOX "Quad, " + STR$(x)

          ' Quad another way
          d1 = HI(DWORD, q)
          d2 = LO(DWORD, q)
          x = CntBitsSet(BYVAL VARPTR(d1)) + CntBitsSet(BYVAL VARPTR(d2))
          MSGBOX "Quad, " + STR$(x)
          END FUNCTION


          FASTPROC CntBitsSet(BYVAL x AS LONG) AS LONG 'x is address of variable to count
          !mov eax, x
          !popcnt ebx, [eax] 'counts set bits in x, puts count in ebx
          !mov x, ebx
          END FASTPROC = x

          Comment


          • #6
            The 2 volume Intel IA32 and 64 instruction documents I have are just old enough to not have POPCNT in them. Thanks Frank, no loop with POPCNT.( Now I need to find newer docs at Intel)

            Thick head tonight? (on me) I can not see how the code posted by Pierre works. (okay, modified and reposted) Thanks here too because I picked up something useful and cleaned up my code from before.
            Code:
            #compile exe
            #dim all
            function CountBitsInQuad(byval TargQ as quad) as long
              #register none
              local LDWord, UDWord as dword
              LDWord = lo(dword, TargQ)
              UDWord = hi(dword, TargQ)
              ! xor ebx, ebx    'set bit offset to 0
              ChkLower:
                ! bt LDWord, ebx  'test for set bit
                ! jnc ChkUpper    'skip to upper if bit not set
                ! inc function    'increment count if bit is set
              ChkUpper:
                ! bt UDWord, ebx  'bit test to CF
                ! jnc NextBit      '
                ! inc function     '
              NextBit:
                ! inc ebx         'next offset
                ! cmp ebx, 32     'done if 32 because MSb is 31
                ! jnz ChkLower
            end function
            function pbmain () as long
              local OneBits as long
              OneBits = CountBitsInQuad(&b100110010010000000000110001110000111101&&)    'is 15
              ? str$(OneBits)
            end function
            Dale

            Comment

            Working...
            X