将 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
我真的不知道我在做什么... 目标是将所有的 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