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 不影响) 用于分支和条件判断

相关推荐
黎雁·泠崖3 分钟前
【C语言指针精讲】从内存到运算,吃透指针核心逻辑
c语言·开发语言
秦苒&9 分钟前
【C语言指针四】数组指针变量、二维数组传参本质、函数指针变量、函数指针数组
c语言·开发语言·c++·c#
秋雨雁南飞10 分钟前
C# 字符串占位
开发语言·c#
拾贰_C10 分钟前
[Python | pytorch | torchvision ] models like ResNet... 命名变量说明
开发语言·pytorch·python
傅里叶的耶11 分钟前
C++ Primer Plus(第6版):第三章 处理数据
开发语言·c++
CC.GG30 分钟前
【C++】AVL树
java·开发语言·c++
CoderCodingNo1 小时前
【GESP】C++四级真题 luogu-B4416 [GESP202509 四级] 最长连续段
开发语言·c++·算法
a程序小傲1 小时前
京东Java面试被问:Fork/Join框架的使用场景
java·开发语言·后端·postgresql·面试·职场和发展
⑩-1 小时前
Java四种线程创建方式
java·开发语言
月光在发光1 小时前
22_GDB调试记录(未完成)
java·开发语言