main.cpp
#include <stdio.h>
#include "../../commonfiles/miscdefs.h"

extern "C" void AvxGprCountZeroBits(Uint32 x, Uint32* lzcnt, Uint32* tzcnt);
extern "C" Uint32 AvxGprBextr(Uint32 x, Uint8 start, Uint8 length);
extern "C" Uint32 AvxGprAndNot(Uint32 x, Uint32 y);

void AvxGprCountZeroBitsCpp(void)
{
    const int n = 5;
    Uint32 x[n] = { 0x001000008, 0x00008000, 0x8000000, 0x00000001, 0 };

    printf("\nResults for AvxGprCountZeroBits()\n");
    for (int i = 0; i < n; i++)
    {
        Uint32 lzcnt, tzcnt;

        AvxGprCountZeroBits(x[i], &lzcnt, &tzcnt);
        printf("x: 0x%08X  ", x[i]);
        printf("lzcnt: %2u  ", lzcnt);
        printf("tzcnt: %2u\n", tzcnt);
    }
}

void AvxGprExtractBitFieldCpp(void)
{
    const int n = 3;
    Uint32 x[n] = { 0x12345678, 0x80808080, 0xfedcba98 };
    Uint8 start[n] = { 4, 7, 24 };
    Uint8 len[n] = { 16, 9, 8 };

    printf("\nResults for AvxGprExtractBitField()\n");
    for (int i = 0; i < n; i++)
    {
        Uint32 bextr = AvxGprBextr(x[i], start[i], len[i]);

        printf("x: 0x%08X  ", x[i]);
        printf("start: %2u  ", start[i]);
        printf("len:  %2u  ", len[i]);
        printf("bextr: 0x%08X\n", bextr);
    }
}

void AvxGprAndNotCpp(void)
{
    const int n = 3;
    Uint32 x[n] = { 0xf000000f, 0xff00ff00, 0xaaaaaaaa };
    Uint32 y[n] = { 0x12345678, 0x12345678, 0xffaa5500 };

    printf("\nResults for AvxGprAndNot()\n");
    for (int i = 0; i < n; i++)
    {
        Uint32 andn = AvxGprAndNot(x[i], y[i]);
        printf("x: 0x%08X  y: 0x%08X  z: 0x%08X\n", x[i], y[i], andn);
    }
}

int main(int argc, char* argv[])
{
    AvxGprCountZeroBitsCpp();
    AvxGprExtractBitFieldCpp();
    AvxGprAndNotCpp();
    return 0;
}
avxbgprbitmanip.asm
; Name:     avxbgprbitmanip.asm
;
; Build:    g++ -c -m32 main.cpp -o main.o
;           nasm -f elf32 -o avxbgprbitmanip.o avxbgprbitmanip.asm
;           g++ -m32 -o avxbgprbitmanip avxbgprbitmanip.o main.o
;
; Source:   Modern x86 Assembly Language Programming p. 486

global AvxGprCountZeroBits
global AvxGprBextr
global AvxGprAndNot

section .text

; extern "C" void AvxGprCountZeroBits(Uint32 x, Uint32* lzcnt, Uint32* tzcnt);
;
; Description:  The following function demonstrates use of the lzcnt and
;               tzcnt instructions.
;
; Requires:     BMI1, LZCNT

AvxGprCountZeroBits:
    mov     eax,[esp+4]                   ;eax = x

    lzcnt   ecx,eax                       ;count leading zeros
    mov     edx,[esp+8]
    mov     [edx],ecx                     ;save result

    tzcnt   ecx,eax                       ;count trailing zeros
    mov     edx,[esp+12]
    mov     [edx],ecx                     ;save result
    ret

; extern "C" Uint32 AvxGprBextr(Uint32 x, Uint8 start, Uint8 length);
;
; Description:  The following function demonstrates use of the
;               bextr instruction.
;
; Requires:     BMI1

AvxGprBextr:
    mov     cl,[esp+8]                    ;cl = start index
    mov     ch,[esp+12]                   ;ch = length of bit field
    bextr   eax,[esp+4],ecx               ;eax = extracted bit field
    ret

; extern "C" Uint32 AvxGprAndNot_(Uint32 x, Uint32 y);
;
; Description:  The following function demonstrates use of the
;               andn instruction.
;
; Requires:     BMI1

AvxGprAndNot:
    mov     ecx,[esp+4]
    andn    eax,ecx,[esp+8]               ;eax = ~ecx & [esp+8]
    ret
build
g++ -c -m32 main.cpp -o main.o
nasm -f elf32 -o avxgprbitmanip.o avxgprbitmanip.asm
g++ -m32 -o avxgprbitmanip avxgprbitmanip.o main.o