You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改x86嵌入C汇编代码统计整数二进制中的0的个数?

统计二进制中0的个数的修改方案

原代码逻辑分析

原代码通过add eax, eax(等价于左移1位)将当前数的最高位移到进位标志位(CF):

  • jnc next:当CF为0(即移出的是0)时跳转到next,不执行计数
  • inc ebx:仅当CF为1(即移出的是1)时执行,最终ebx存储的是二进制中1的个数

修改方案1:反转计数条件

直接修改跳转指令,当移出的是0时计数,移出的是1时跳过:
将jnc next替换为jc next,这样有进位(移出1)时跳走不计数,无进位(移出0)时执行计数。

修改后的完整代码:

int main(){
  int x = 2023; // 二进制低11位为11111100111,含9个1,剩余21位为0,总0的个数为23
  int y;
  
  asm(
    "mov eax, %1 ;"
    "mov ecx, 32 ;"
    "mov ebx, 0 ;"
    "loop:"
      "add eax, eax ;"
      "jc next ;"  // 移出1(有进位)时跳过计数
      "inc ebx ;"   // 移出0(无进位)时统计
      "next :"
      "dec ecx ;"
      "jnz loop;"
    "mov %0, ebx ;"

    : "=r" (y)
    : "r"(x)
    : "eax", "ebx", "ecx"
  );
}

注:2023的32位二进制中实际包含23个0,你之前得到的23是正确结果,并非错误。


修改方案2:总位数减去1的个数

如果不想改动核心计数逻辑,可以先统计1的个数,再用32(int类型的总位数)减去该值得到0的个数:

修改后的完整代码:

int main(){
  int x = 2023; //nine 1 and two 0 as in bin it's - 11111100111
  int y;
  
  asm(
    "mov eax, %1 ;"
    "mov ecx, 32 ;"
    "mov ebx, 0 ;"
    "loop:"
      "add eax, eax ;"
      "jnc next ;"
      "inc ebx ;"
      "next :"
      "dec ecx ;"
      "jnz loop;"
    "mov eax, 32 ;"  // 加载int类型的总位数
    "sub eax, ebx ;" // 总位数减去1的个数,得到0的个数
    "mov %0, eax ;"

    : "=r" (y)
    : "r"(x)
    : "eax", "ebx", "ecx"
  );
}

额外注意

如果需要处理负数,由于有符号int的最高位是符号位(负数为1),统计时会包含该位。若要统计绝对值的二进制0的个数,需先对负数取绝对值后再处理。

内容的提问来源于stack exchange,提问作者pawel_duszynski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 19:23:11