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;

在汇编中:

  • 变量 a、b 等都分配在函数栈上。
  • 每次操作都是 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 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
Navigator_Z4 小时前
LeetCode //C - 1291. Sequential Digits
c语言·算法·leetcode
顽疲5 小时前
Java vue 养老系统源码详解:月账单 care_month_bill 与 Quartz 扣费 Job 实践
java·开发语言·vue.js·vue养老·springboot养老·java养老
Wang's Blog5 小时前
Java 项目实战: 交友项目 - 安装开发工具与环境准备
java·开发语言·交友
水饺编程7 小时前
第2章:Linux 基础,clear 命令
linux·c语言·汇编
程序喵大人7 小时前
【C++入门】编译链接模型 - 07 链接器怎样把符号对上号
开发语言·c++·编译器·编译链接·链接器
无敌贵点大王8 小时前
嵌入式软件面试经(自用)
c语言·stm32·单片机·学习·mongodb·面试·职场和发展
微三云 - 廖会灵 (私域系统开发)8 小时前
供应链系统实战:多渠道订单聚合与分布式库存一致性方案总结
开发语言·分布式·php
学逆向的8 小时前
C 数据溢出与精度丢失
c语言·开发语言·网络安全
霸道流氓气质9 小时前
AgentFlow 入门与实战:Task-Based 并发、EWMA 动态调度与四道门禁的 Java 生产级编排
java·开发语言