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指令的功能

相关推荐
Zevalin爱灰灰8 小时前
能源与电源管理电路——防倒灌电路
单片机·嵌入式硬件·电源管理
jianqiang.xue10 小时前
ESP-IDF保姆级入门02|Ubuntu24.04搭建EIM-GUI开发环境,打通Windows_Linux双平台统一开发
stm32·单片机·物联网
无垠的广袤11 小时前
【工业树莓派 CM0 Dev Board】扩展板设计
linux·python·嵌入式硬件·pcb设计·模块化·传感器
嵌入式-老费11 小时前
esp32开发与应用(添加数据分区)
单片机·嵌入式硬件
嵌入式-老费12 小时前
esp32开发与应用(OTA升级)
嵌入式硬件
CYLAM202515 小时前
STC32G 单片机0.96“OLED 西历农历可调万年历 (1901-2100)
单片机·嵌入式硬件·stc32g·万年历·西历农历·0.96”oled 12864·4x4 矩阵键盘
Discipline~Hai15 小时前
ARM03-蜂鸣器和中断
c语言·arm开发·单片机·嵌入式硬件·嵌入式
KaifuZeng16 小时前
电源面试问题汇总一
单片机·嵌入式硬件·面试·电路
驱动探索者18 小时前
RISC-V PLIC 深度解析:从 Spec 到 Zephyr 驱动实现
单片机·嵌入式硬件·中断控制器
LCG元18 小时前
STM32 FreeRTOS 实战:任务调度 + 互斥锁 + 消息队列 + 串口命令解析器
stm32·单片机·嵌入式硬件