将 x86 汇编中的所有 1 位相加

add up all 1 bits in x86 assembly

我真的不知道我在做什么... 目标是将所有的 1 相加,如果是偶数则表示是,如果是奇数则表示是 C/C++ 部分给出了传递给 asm

的变量
#include <stdint.h>
#include <stdio.h>
#include <iostream>
using namespace std;

extern "C" {
    bool    isBitCountEven(int32_t);
}

static int32_t testData[] = {
    0x0,
    0x1,
    0x2,
    0x4,
    0x8,
    0x40000000,
    0x80000000,
    0x00000002,
    0xe,
    0xff770001,
    0xffeeeeff,
    0xdeadbeef,
    0xbaddf00d,
    0xd00fefac,
    0xfaceecaf,
    0xffffffff,
    0xaaaa5555
};
#define NUM_TEST_CASES  (sizeof (testData) / sizeof (*testData))


int main()
{
    printf(" ICE#10 \n\n");

    for (int i = 0; i < NUM_TEST_CASES; i++) {
        printf("isBitCountEven(0x%8x) yields: %s\n", testData[i], isBitCountEven(testData[i]) ? "true" : "false");
    }
    system("PAUSE");
    return 0;
}

这是我的汇编。它不输出任何东西。 序言和结语只是我从其他工作良好的作品中抄袭和粘贴的东西,所以请忽略那些,我知道它们可能是垃圾

这是我的 asm

        .386P           ; use 80386 instruction set
        .MODEL flat,C     ; use flat memory model

        printf PROTO C, :VARARG

        .DATA           ; declare initialzed data here

        .STACK          ; use default 1k stack space

        .CODE           ; contains our code


    ;-------------------PART 1------------------------------------------------------------
    ;if (the number of 1 bits in the binary representation of val is even)
    ;               return true;
    ;           else        
    ;               return false;
    ;       }
    ;
    ;--------------------------------------------------------------------------------------
    isBitCountEven PROC PUBLIC
        PUSH    ebp             ; save caller base pointer
        MOV     ebp, esp        ; set our base pointer
        SUB     esp, (1 * 4)    ; allocate uint32_t local vars
        PUSH    edi
        PUSH    esi
        ; end prologue

        MOV     al, [ebp + 8]
    ;now walk down the variable and count the number of 1

    SHIFT:
        SHL al, 1
        JNC SKIP
        INC ebx
    SKIP:
        loop SHIFT

    FINALE:             ;see if it adds up to ebx
    TEST al, al
    JP FALSE
    TEST ebx, 1 
    JZ TRUE



TRUE:
    MOV     eax,1
    POP     esi                 ; start epilogue
    POP     edi
    MOV     esp, ebp            ; deallocate locals
    POP     ebp                 ; restore caller base pointer
    RET
FALSE:
    MOV     eax, 0
    POP     esi                 ; start epilogue
    POP     edi
    MOV     esp, ebp            ; deallocate locals
    POP     ebp                 ; restore caller base pointer
    RET
isBitCountEven ENDP ; end the procedure
END isBitCountEven

我该怎么办我完全迷失了并且在 asm 方面很糟糕...

它可以简化很多,主要是通过摆脱所有堆栈框架业务(真的没有必要,没有动态堆栈分配)和使用 setcc 而不是分支。

你可以用popcnt来计算int32_t的位数,然后测试计数是否为偶数,

isBitCountEven PROC PUBLIC
    mov eax, dword ptr [esp + 4]
    popcnt eax, eax
    test al, 1
    setz al    ; if the lowest bit of the count is zero, its even
    ret
isBitCountEven ENDP

另一种简单的方法是使用奇偶校验标志,但它只检查低字节的奇偶校验,所以需要先减少一点,

isBitCountEven PROC PUBLIC
    mov eax, dword ptr [esp + 4]
    mov edx, eax
    shr eax, 16
    xor eax, edx
    xor al, ah ; all 4 bytes are now XORed together, parity flag reflects total parity
    setpe al   ; set al to 1 if parity is even, 0 if odd
    ret
isBitCountEven ENDP