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 小时前
数据结构——二十二、并查集(王道408)
c语言·数据结构·笔记·学习·考研
x_feng_x3 小时前
Java从入门到精通 - 集合框架(二)
java·开发语言·windows
Le1Yu3 小时前
雪崩问题及其解决方案(请求限流、线程隔离、服务熔断、fallback、sentinel实现以上功能)
java·开发语言
大飞记Python3 小时前
Chromedriver放项目里就行!Selenium 3 和 4 指定路径方法对比 + 兼容写法
开发语言·python
std78793 小时前
用C++ 实现屏幕保护程序
开发语言·c++
CHANG_THE_WORLD3 小时前
if条件语句 三目运算符 汇编分析
汇编·算法·条件语句·if 语句·汇编分析·条件语句汇编分析
tumu_C3 小时前
无用知识研究:在trailing return type利用decltype,comma operator在对函数进行sfinae原创 [二]
开发语言·c++·算法
jjjxxxhhh1233 小时前
【项目-】Qt + QCustomPlot 实现频谱监测仪:四图联动、高频信号注入、鼠标交互全解析
开发语言·qt·交互
web安全工具库3 小时前
告别刀耕火种:用 Makefile 自动化 C 语言项目编译
linux·运维·c语言·开发语言·数据库·算法·自动化