c语言位运算 汇编代码分析

文章目录

  • [🧩 基础背景](#🧩 基础背景)
  • [⚙️ 分析逐步讲解](#⚙️ 分析逐步讲解)
    • [🧠 1️⃣ 定义变量 a、b](#🧠 1️⃣ 定义变量 a、b)
    • [🧩 2️⃣ 按位与(AND)](#🧩 2️⃣ 按位与(AND))
      • [➤ 执行过程:](#➤ 执行过程:)
      • [➤ 结果:](#➤ 结果:)
      • [➤ 汇编解释:](#➤ 汇编解释:)
    • [🧩 3️⃣ 按位或(OR)](#🧩 3️⃣ 按位或(OR))
      • [➤ 执行过程:](#➤ 执行过程:)
      • [➤ 结果:](#➤ 结果:)
      • [➤ 汇编解释:](#➤ 汇编解释:)
    • [🧩 4️⃣ 按位异或(XOR)](#🧩 4️⃣ 按位异或(XOR))
      • [➤ 执行过程:](#➤ 执行过程:)
      • [➤ 结果:](#➤ 结果:)
      • [➤ 汇编解释:](#➤ 汇编解释:)
    • [🧩 5️⃣ 按位取反(NOT)](#🧩 5️⃣ 按位取反(NOT))
      • [➤ 执行过程:](#➤ 执行过程:)
      • [➤ 结果:](#➤ 结果:)
      • [➤ 汇编解释:](#➤ 汇编解释:)
    • [🧩 6️⃣ 左移(SHL)](#🧩 6️⃣ 左移(SHL))
      • [➤ 执行过程:](#➤ 执行过程:)
      • [➤ 结果:](#➤ 结果:)
      • [➤ 汇编解释:](#➤ 汇编解释:)
    • [🧩 7️⃣ 右移(SHR)](#🧩 7️⃣ 右移(SHR))
      • [➤ 执行过程:](#➤ 执行过程:)
      • [➤ 结果:](#➤ 结果:)
      • [➤ 汇编解释:](#➤ 汇编解释:)
  • [🧾 汇总表](#🧾 汇总表)
  • [🧠 编译器生成逻辑分析](#🧠 编译器生成逻辑分析)
  • [✅ 总结要点](#✅ 总结要点)

位运算代码

c 复制代码
#include <iostream>
#include <bitset>

void basicBitOperations() {
	unsigned int a = 0b11001100; // 204
	unsigned int b = 0b10101010; // 170

	//std::cout << "a = " << std::bitset<8>(a) << " (" << a << ")" << std::endl;
	//std::cout << "b = " << std::bitset<8>(b) << " (" << b << ")" << std::endl;

	// 位与运算
	unsigned int andResult = a & b;
	//std::cout << "a & b = " << std::bitset<8>(andResult) << " (" << andResult << ")" << std::endl;

	// 位或运算
	unsigned int orResult = a | b;
	//std::cout << "a | b = " << std::bitset<8>(orResult) << " (" << orResult << ")" << std::endl;

	// 位异或运算
	unsigned int xorResult = a ^ b;
	//std::cout << "a ^ b = " << std::bitset<8>(xorResult) << " (" << xorResult << ")" << std::endl;

	// 位非运算
	unsigned int notResult = ~a;
	//std::cout << "~a = " << std::bitset<8>(notResult) << " (" << notResult << ")" << std::endl;

	// 左移运算
	unsigned int leftShift = a << 2;
	//std::cout << "a << 2 = " << std::bitset<8>(leftShift) << " (" << leftShift << ")" << std::endl;

	// 右移运算
	unsigned int rightShift = a >> 2;
	//std::cout << "a >> 2 = " << std::bitset<8>(rightShift) << " (" << rightShift << ")" << std::endl;
}
int main()
{
	basicBitOperations();
}

汇编代码

c 复制代码
--- D:\ReverseEngineering\CPP_Code\位运算\位运算\位运算.cpp -----------------------------
     1: #include <iostream>
     2: #include <bitset>
     3: 
     4: void basicBitOperations() {
002A1820  push        ebp  
002A1821  mov         ebp,esp  
002A1823  sub         esp,120h  
002A1829  push        ebx  
002A182A  push        esi  
002A182B  push        edi  
002A182C  lea         edi,[ebp-60h]  
002A182F  mov         ecx,18h  
002A1834  mov         eax,0CCCCCCCCh  
002A1839  rep stos    dword ptr es:[edi]  
002A183B  mov         ecx,offset _3428AB1E_位运算\位运算\位运算@cpp (02AC079h)  
002A1840  call        @__CheckForDebuggerJustMyCode@4 (02A1325h)  
002A1845  nop  
     5: 	unsigned int a = 0b11001100; // 204
002A1846  mov         dword ptr [a],0CCh  
     6: 	unsigned int b = 0b10101010; // 170
002A184D  mov         dword ptr [b],0AAh  
     7: 
     8: 	//std::cout << "a = " << std::bitset<8>(a) << " (" << a << ")" << std::endl;
     9: 	//std::cout << "b = " << std::bitset<8>(b) << " (" << b << ")" << std::endl;
    10: 
    11: 	// 位与运算
    12: 	unsigned int andResult = a & b;
002A1854  mov         eax,dword ptr [a]  
002A1857  and         eax,dword ptr [b]  
002A185A  mov         dword ptr [andResult],eax  
    13: 	//std::cout << "a & b = " << std::bitset<8>(andResult) << " (" << andResult << ")" << std::endl;
    14: 
    15: 	// 位或运算
    16: 	unsigned int orResult = a | b;
002A185D  mov         eax,dword ptr [a]  
002A1860  or          eax,dword ptr [b]  
002A1863  mov         dword ptr [orResult],eax  
    17: 	//std::cout << "a | b = " << std::bitset<8>(orResult) << " (" << orResult << ")" << std::endl;
    18: 
    19: 	// 位异或运算
    20: 	unsigned int xorResult = a ^ b;
002A1866  mov         eax,dword ptr [a]  
002A1869  xor         eax,dword ptr [b]  
002A186C  mov         dword ptr [xorResult],eax  
    21: 	//std::cout << "a ^ b = " << std::bitset<8>(xorResult) << " (" << xorResult << ")" << std::endl;
    22: 
    23: 	// 位非运算
    24: 	unsigned int notResult = ~a;
002A186F  mov         eax,dword ptr [a]  
002A1872  not         eax  
002A1874  mov         dword ptr [notResult],eax  
    25: 	//std::cout << "~a = " << std::bitset<8>(notResult) << " (" << notResult << ")" << std::endl;
    26: 
    27: 	// 左移运算
    28: 	unsigned int leftShift = a << 2;
002A1877  mov         eax,dword ptr [a]  
002A187A  shl         eax,2  
002A187D  mov         dword ptr [leftShift],eax  
    29: 	//std::cout << "a << 2 = " << std::bitset<8>(leftShift) << " (" << leftShift << ")" << std::endl;
    30: 
    31: 	// 右移运算
    32: 	unsigned int rightShift = a >> 2;
002A1880  mov         eax,dword ptr [a]  
002A1883  shr         eax,2  
002A1886  mov         dword ptr [rightShift],eax  
    33: 	//std::cout << "a >> 2 = " << std::bitset<8>(rightShift) << " (" << rightShift << ")" << std::endl;
    34: }
002A1889  pop         edi  
002A188A  pop         esi  
002A188B  pop         ebx  
002A188C  add         esp,120h  
002A1892  cmp         ebp,esp  
002A1894  call        __RTC_CheckEsp (02A1249h)  
002A1899  mov         esp,ebp  
002A189B  pop         ebp  
002A189C  ret  

分析

非常好 👏

你这段代码展示了 C++ 编译后,编译器如何将每一种位运算&, |, ^, ~, <<, >>)翻译为底层汇编指令。

我们来逐行剖析 C 代码 ↔ 汇编指令 ↔ 实际寄存器行为 ↔ 位级变化


🧩 基础背景

源代码:

cpp 复制代码
unsigned int a = 0b11001100; // 204 (0xCC)
unsigned int b = 0b10101010; // 170 (0xAA)
unsigned int andResult = a & b;
unsigned int orResult = a | b;
unsigned int xorResult = a ^ b;
unsigned int notResult = ~a;
unsigned int leftShift = a << 2;
unsigned int rightShift = a >> 2;

在汇编中:

  • 变量 ab 等都分配在函数栈上。
  • 每次操作都是 mov → 运算 → mov 三步。
  • 寄存器使用 EAX(主运算寄存器)。

⚙️ 分析逐步讲解


🧠 1️⃣ 定义变量 a、b

asm 复制代码
002A1846  mov dword ptr [a],0CCh   ; a = 0xCC (204)
002A184D  mov dword ptr [b],0AAh   ; b = 0xAA (170)
变量 二进制 十进制 十六进制
a 11001100 204 0xCC
b 10101010 170 0xAA

这两行只是往栈上保存常数,没有计算。


🧩 2️⃣ 按位与(AND)

asm 复制代码
002A1854  mov eax,dword ptr [a]
002A1857  and eax,dword ptr [b]
002A185A  mov dword ptr [andResult],eax

➤ 执行过程:

步骤 内容
1️⃣ 载入 a → EAX = 11001100b
2️⃣ 与 b 做 AND → EAX = 11001100 AND 10101010 = 10001000
3️⃣ 保存结果到 andResult

➤ 结果:

复制代码
10001000b = 0x88 = 136

➤ 汇编解释:

  • and eax, [b] 是逐位逻辑与。
  • 对每一位:1 & 1 → 1,否则 0
  • 常用于 屏蔽(mask)操作

🧩 3️⃣ 按位或(OR)

asm 复制代码
002A185D  mov eax,dword ptr [a]
002A1860  or  eax,dword ptr [b]
002A1863  mov dword ptr [orResult],eax

➤ 执行过程:

步骤 内容
1️⃣ EAX = 11001100
2️⃣ OR b → 11001100 OR 10101010 = 11101110
3️⃣ 保存结果

➤ 结果:

复制代码
11101110b = 0xEE = 238

➤ 汇编解释:

  • or eax, [b]:任一位为 1 → 结果为 1。
  • 用于 强制开启特定位,如 "设置标志位"。

🧩 4️⃣ 按位异或(XOR)

asm 复制代码
002A1866  mov eax,dword ptr [a]
002A1869  xor eax,dword ptr [b]
002A186C  mov dword ptr [xorResult],eax

➤ 执行过程:

步骤 内容
1️⃣ EAX = 11001100
2️⃣ XOR b → 11001100 XOR 10101010 = 01100110
3️⃣ 保存结果

➤ 结果:

复制代码
01100110b = 0x66 = 102

➤ 汇编解释:

  • xor eax, [b]:相同为 0,不同为 1。

  • 特性:

    • x ^ 0 = x
    • x ^ x = 0
  • 常见技巧:

    • xor eax, eax 用来清零寄存器。

🧩 5️⃣ 按位取反(NOT)

asm 复制代码
002A186F  mov eax,dword ptr [a]
002A1872  not eax
002A1874  mov dword ptr [notResult],eax

➤ 执行过程:

步骤 内容
1️⃣ EAX = 11001100
2️⃣ NOT → 每一位取反 → 00110011
3️⃣ 保存结果

➤ 结果:

复制代码
00110011b = 0x33 = 51

➤ 汇编解释:

  • not eax:1 → 0,0 → 1。
  • 用于 按位反转
  • 不影响标志位(ZF/SF/CF 不变)。

🧩 6️⃣ 左移(SHL)

asm 复制代码
002A1877  mov eax,dword ptr [a]
002A187A  shl eax,2
002A187D  mov dword ptr [leftShift],eax

➤ 执行过程:

步骤 内容
1️⃣ EAX = 11001100b
2️⃣ 左移 2 位 → 00110000b
3️⃣ 保存结果

➤ 结果:

复制代码
00110000b = 0x30 = 48

➤ 汇编解释:

  • shl eax, 2:逻辑左移 2 位。
  • 左移时 高位溢出 → CF,低位补 0。
  • 相当于:a * 2² = a * 4
  • 常用于乘 2 的幂

🧩 7️⃣ 右移(SHR)

asm 复制代码
002A1880  mov eax,dword ptr [a]
002A1883  shr eax,2
002A1886  mov dword ptr [rightShift],eax

➤ 执行过程:

步骤 内容
1️⃣ EAX = 11001100b
2️⃣ 右移 2 位 → 00110011b
3️⃣ 保存结果

➤ 结果:

复制代码
00110011b = 0x33 = 51

➤ 汇编解释:

  • shr eax, 2:逻辑右移 2 位。
  • 低位移出 → CF;高位补 0。
  • 相当于:a / 4(对无符号数)。

🧾 汇总表

操作 C 表达式 汇编指令 结果(二进制) 十进制 说明
AND a & b and eax,[b] 10001000 136 按位与,清零特定位
OR a b or eax,[b] 11101110 238
XOR a ^ b xor eax,[b] 01100110 102 按位异或,反转不同位
NOT ~a not eax 00110011 51 取反
SHL a << 2 shl eax,2 00110000 48 左移(×4)
SHR a >> 2 shr eax,2 00110011 51 右移(÷4)

🧠 编译器生成逻辑分析

在汇编层,所有这些操作都遵循相同模板:

复制代码
mov eax, [变量1]
<位运算指令> eax, [变量2或立即数]
mov [结果变量], eax

也就是三步:

1️⃣ 载入源操作数。

2️⃣ 执行位级运算。

3️⃣ 存回结果。

由于这些是 单指令逻辑操作(单周期执行)

它们在 CPU 中都由 ALU(算术逻辑单元) 直接完成。


✅ 总结要点

类型 汇编指令 操作特性
逻辑运算 and, or, xor, not, test 不涉及进位,纯二进制位逻辑
移位运算 shl, shr, sar, rol, ror 位移动与标志控制
ALU 执行单元 硬件电路级并行完成 比加减更快
标志位变化 ZF, SF, CF, PF 更新(NOT 不影响) 用于分支和条件判断

相关推荐
故乡de云10 小时前
AWS 添加付款方式失败排查清单:卡片、银行风控与账号状态逐项定位
开发语言·php
J_yyy10 小时前
【Qt核心组件类框架】
开发语言·qt
运维行者_10 小时前
如何查看每个IP的带宽使用情况?NetFlow 技术实战指南
开发语言·网络·分布式·后端·架构·带宽
天天进步201511 小时前
Python全栈项目--基于深度学习的图像超分辨率系统
开发语言·python·深度学习
小小晓.11 小时前
C++小白记:C风格字符串和数组用法
c语言·开发语言·c++
Helen_cai11 小时前
OpenHarmony 项目统一全局样式、尺寸、色彩主题封装 ThemeUtil(API23)
开发语言·前端·javascript·华为·harmonyos
郑州光合科技余经理11 小时前
家政O2O平台解析:从0搭建上门预约小程序解决方案
android·java·开发语言·前端·小程序·架构·php
深念Y12 小时前
开发者如何清理和迁移C盘堆积的垃圾
c语言·开发语言
qq_5896660512 小时前
Python 数据可视化与交互式分析工具全总结
开发语言·python·信息可视化
2501_9095091012 小时前
DAY 28
开发语言·python