led_pattern = (led_pattern << 1) | (led_pattern >> 7)执行顺序

1. 执行步骤分解

cpp 复制代码
unsigned char led_pattern = 0xFE;  // 二进制: 1111 1110

// 第一步:计算 (led_pattern << 1)
// 第二步:计算 (led_pattern >> 7)  
// 第三步:将两个结果进行 | (按位或) 运算
// 第四步:将最终结果赋值给 led_pattern

2. 具体数值演算

led_pattern = 0xFE (1111 1110) 为例:

cpp 复制代码
步骤1: led_pattern << 1
       1111 1110 << 1 = 1111 1100
       // 注意:最高位的1移出,最低位补0

步骤2: led_pattern >> 7
       1111 1110 >> 7 = 0000 0001
       // 右移7位,最低位的0移出,高位补0
       // 原最低位的0被丢弃,原来第7位(最高位)的1移到最低位

步骤3: (步骤1的结果) | (步骤2的结果)
       1111 1100  (来自步骤1)
       0000 0001  (来自步骤2)
       ---------- |
       1111 1101  // 最终结果

步骤4: led_pattern = 1111 1101 (0xFD)

3. 完整8次循环演算表

循环次数 原值(二进制) <<1结果 >>7结果 OR结果 新值(十六进制) 点亮位置
初始 1111 1110 1111 1100 0000 0001 1111 1101 0xFD LED1
1次 1111 1101 1111 1010 0000 0001 1111 1011 0xFB LED2
2次 1111 1011 1111 0110 0000 0001 1111 0111 0xF7 LED3
3次 1111 0111 1110 1110 0000 0001 1110 1111 0xEF LED4
4次 1110 1111 1101 1110 0000 0001 1101 1111 0xDF LED5
5次 1101 1111 1011 1110 0000 0001 1011 1111 0xBF LED6
6次 1011 1111 0111 1110 0000 0001 0111 1111 0x7F LED7
7次 0111 1111 1111 1110 0000 0000 1111 1110 0xFE LED0
8次 1111 1110 回到初始值,循环重复 - - - -

4. 运算优先级说明

C语言中运算符优先级(从高到低):

cpp 复制代码
1. 括号 ()          // 最高优先级
2. 移位 << >>       // 优先级较高
3. 按位与 &         // 中等
4. 按位异或 ^       // 中等
5. 按位或 |         // 较低
6. 赋值 =           // 最低优先级

// 因此原表达式等价于:
led_pattern = ((led_pattern << 1) | (led_pattern >> 7));

5. 为什么这样写能实现循环左移?

cpp 复制代码
// 以 8位为例,原始数据 bits[7..0]
// 循环左移1位的结果 = bits[6..0] + bits[7]

// led_pattern << 1  : 得到 bits[6..0] + 0
// led_pattern >> 7  : 得到 0...0 + bits[7]  
// 两者 OR 合并      : 得到 bits[6..0] + bits[7]

// 这就是循环左移(ROL)的效果!

6. 等效的汇编指令

您原来的汇编代码:

cpp 复制代码
ROL AL, 1    ; 循环左移1位

7. 验证代码(可测试执行过程)

cpp 复制代码
#include <stdio.h>

int main() {
    unsigned char led_pattern = 0xFE;
    
    for(int cycle = 0; cycle < 10; cycle++) {
        printf("循环%2d: 0x%02X = ", cycle, led_pattern);
        
        // 显示二进制
        for(int bit = 7; bit >= 0; bit--) {
            printf("%d", (led_pattern >> bit) & 1);
        }
        
        // 执行循环左移
        led_pattern = (led_pattern << 1) | (led_pattern >> 7);
        
        printf("  -> 0x%02X\n", led_pattern);
    }
    
    return 0;
}

输出结果:

bash 复制代码
循环 0: 0xFE = 11111110  -> 0xFD
循环 1: 0xFD = 11111101  -> 0xFB
循环 2: 0xFB = 11111011  -> 0xF7
循环 3: 0xF7 = 11110111  -> 0xEF
循环 4: 0xEF = 11101111  -> 0xDF
循环 5: 0xDF = 11011111  -> 0xBF
循环 6: 0xBF = 10111111  -> 0x7F
循环 7: 0x7F = 01111111  -> 0xFE
循环 8: 0xFE = 11111110  -> 0xFD

关键要点总结

  1. 先计算两边的移位表达式(互不影响,都使用原值)

  2. 再进行按位或运算

  3. 最后赋值给左侧变量

  4. 由于是unsigned char类型,移位超出8位的部分会被丢弃

  5. 整个过程实现了汇编ROL指令的功能

相关推荐
2CM_Embed9 小时前
Altium Designer 原理图与 PCB 快速相互定位:Cross Probe 交叉探针
嵌入式硬件·pcb·altium designer·c2000
恒锐丰-罗生10 小时前
宽压大电流同步降压优选|CN3906 DC-DC 电源芯片,车载 / 工控 / IoT 全能供电方案
嵌入式硬件·硬件工程
happygrilclh13 小时前
STM32,串口单字节中断接受,每次上电后,会收到一个0x00的解决办法。
单片机·嵌入式硬件
智闲电子设计14 小时前
STM32 独立看门狗 IWDG 实战:系统跑飞,它来兜底复位
stm32·单片机·嵌入式硬件
zcmodeltech15 小时前
智能制造教学实训沙盘模型多系统协同控制系统设计:基于STM32与Modbus RTU的工业机器人-智慧工厂-数字孪生全场景联动方案
数据库·stm32·嵌入式硬件·机器人·制造·多分类
程序员与背包客_CoderZ16 小时前
Linux D-Bus通信协议详解:从入门到C/C++编码实战
linux·服务器·c语言·c++·嵌入式硬件·嵌入式软件·dbus
嵌入式阿蔡17 小时前
HAL库 vs LL库 vs 寄存器:到底用哪个?
c语言·stm32·单片机·嵌入式硬件·嵌入式实时数据库
天空'之城18 小时前
单片机基础核心知识点汇总(三)
单片机·嵌入式硬件
嵌入式阿蔡18 小时前
CAN总线入门:从协议帧到STM32实战
c语言·stm32·单片机·嵌入式硬件·嵌入式实时数据库
恒锐丰科技韩生19 小时前
率能 SS8847E|2.7~15V 双通道 H 桥电机驱动 ETSSOP16 散热封装 家电 / 打印 / 舞台灯光专用
嵌入式硬件·硬件工程