位运算代码

#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();
      }

汇编代码

--- 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 代码 ↔ 汇编指令 ↔ 实际寄存器行为 ↔ 位级变化


基础背景

源代码:

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

002A1846  mov dword ptr [a],0CCh   ; a = 0xCC (204)
002A184D  mov dword ptr [b],0AAh   ; b = 0xAA (170)
变量二进制十进制十六进制
a110011002040xCC
b101010101700xAA

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


2️⃣ 按位与(AND)

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)

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)

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)

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)

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)

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 表达式汇编指令结果(二进制)十进制说明
ANDa & band eax,[b]10001000136按位与,清零特定位
ORabor eax,[b]11101110238
XORa ^ bxor eax,[b]01100110102按位异或,反转不同位
NOT~anot eax0011001151取反
SHLa << 2shl eax,20011000048左移(×4)
SHRa >> 2shr eax,20011001151右移(÷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 不影响)用于分支和条件判断