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

相关推荐
Han.miracle18 小时前
Java的多线程——多线程(3)线程安全
java·开发语言·jvm·学习·安全·线程·多线程
周杰伦_Jay19 小时前
【主流开发语言深度对比】Python/Go/Java/JS/Rust/C++评测
开发语言·python·golang
ldmd28419 小时前
Go语言实战:入门篇-5:函数、服务接口和Swagger UI
开发语言·后端·golang
xskukuku19 小时前
华为技术有限公司 C语言编程规范
c语言·嵌入式
光子物联单片机19 小时前
C语言基础开发入门系列(八)C语言指针的理解与实战
c语言·开发语言·stm32·单片机·mcu
是苏浙19 小时前
零基础入门C语言之文件操作
c语言·开发语言
盈电智控19 小时前
体力劳动反而更难被AI取代?物联网科技如何守护最后的劳动阵地
开发语言·人工智能·python
隔壁阿布都19 小时前
Spring Boot中的Optional如何使用
开发语言·spring boot·python
小龙报19 小时前
《C语言疑难点 --- C语内存函数专题》
c语言·开发语言·c++·创业创新·学习方法·业界资讯·visual studio
国服第二切图仔20 小时前
Rust开发实战之简单游戏开发(piston游戏引擎)
开发语言·rust·游戏引擎