找回密码
 立即注册
查看: 513|回复: 0

8051指令集机器代码赏析——逻辑移位与循环移位

[复制链接]
  • 打卡等级:常住居民III
  • 打卡总天数:123
  • 最近打卡:2025-04-19 16:12:35
已绑定手机

60

主题

777

回帖

4001

积分

论坛元老

自定义头衔

积分
4001
发表于 2024-11-2 21:37:12 | 显示全部楼层 |阅读模式
本帖最后由 a496298685 于 2024-11-2 21:38 编辑

关于逻辑移动问题 - 学习打卡区 | 感悟 国芯技术交流网站 - AI32位8051交流社区贴子里,楼主问:
【C语言已经提供了逻辑位移指令<<和>>为什么keil还要在INTRINS.H提供_cror_等指令】


借着这个问题,探究一下8051指令集究竟是如何完成的逻辑移位和循环移位


8051指令集只有如下5个和移位有关的指令

截图202411022054072198.jpg

分别是

RL——ACC循环左移1位,例如ACC={B7 B6 B5 B4 B3 B2 B1 B0},执行后ACC变为B6 B5 B4 B3 B2 B1 B0 B7
RR——ACC循环右移1位,例如ACC={B7 B6 B5 B4 B3 B2 B1 B0},执行后ACC变为B0 B7 B6 B5 B4 B3 B2 B1
RLC——ACC带进位C左移1位,例如ACC={B7 B6 B5 B4 B3 B2 B1 B0},执行后ACC变为B6 B5 B4 B3 B2 B1 B0 C,进位标志变为B7
RRC——ACC带进位C右移1位,例如ACC={B7 B6 B5 B4 B3 B2 B1 B0},执行后ACC变为C B7 B6 B5 B4 B3 B2 B1,进位标志变为B0
SWAP——ACC半字节交换(循环移4位),例如ACC={B7 B6 B5 B4 B3 B2 B1 B0},执行后ACC变为B3 B2 B1 B0 B7 B6 B5 B4


下面测试6个案例,看看它们是如何用8051指令集完成的
分别包括:
1. 左移2位
2. 右移2位
3. 右移4位
4. 右移7位
5. 循环右移3位
6. 循环右移1位

一起来感受8051指令集的魅力吧~


案例1
左移2位是如何实现的?

在keil仿真窗口可以看到:
截图202411022106262139.jpg
编译器并没有使用任何移位指令

而是:
1. 将原始数据从P0送入累加器A
2. 执行A <--- A+A
3. 执行A <--- A+A
4. 将数据从A送入SFR寄存器P0
其中两步加法实现了A <--- A*4的效果,和左移2位是等效的


案例2
右移2位是如何实现的?

在keil仿真窗口可以看到:
截图202411022112116501.jpg
编译器使用了带进位循环右移指令(个人认为带不带进位都是等效的)

具体:
1. 将原始数据从P0送入累加器A,记为{B7 B6 B5 B4 B3 B2 B1 B0}
2. A带符号位循环右移1位,变为{C B7 B6 B5 B4 B3 B2 B1}
3. A带符号位循环右移1位,变为{B0 C B7 B6 B5 B4 B3 B2}
4. 执行A <--- A&0x3F,变为{0 0 B7 B6 B5 B4 B3 B2}
5. 将数据从A送入SFR寄存器P0

案例3
右移4位是如何实现的?

在keil仿真窗口可以看到:
截图202411022117558946.jpg
编译器使用了8051特有的SWAP命令,极度简洁!

具体:
1. 将原始数据从P0送入累加器A,记为{B7 B6 B5 B4 B3 B2 B1 B0}
2. A进行半字交换,变为{B3 B2 B1 B0 B7 B6 B5 B4}
3. 执行A <--- A&0xF0,变为{B3 B2 B1 B0 0 0 0 0}
4. 将数据从A送入SFR寄存器P0

案例4
右移7位是如何实现的?

在keil仿真窗口可以看到:
截图202411022130504772.jpg
编译器使用了很多条指令

具体:
1. 将原始数据从P0送入累加器A,记为{B7 B6 B5 B4 B3 B2 B1 B0}
2. A进行半字交换,变为{B3 B2 B1 B0 B7 B6 B5 B4}
3. 执行A带进位循环右移,变为{C B3 B2 B1 B0 B7 B6 B5}
4. 执行A带进位循环右移,变为{B4 C B3 B2 B1 B0 B7 B6}
5. 执行A带进位循环右移,变为{B5 B4 C B3 B2 B1 B0 B7}
6. 执行A <--- A&0x01,变为{0 0 0 0 0 0 0 B7}
7. 将数据从A送入SFR寄存器P0

案例5
循环右移3位是如何实现的?

在keil仿真窗口可以看到:
截图202411022129042700.jpg
好长啊……

具体:
1. 将原始数据从P0送入寄存器R7,记为{B7 B6 B5 B4 B3 B2 B1 B0}
2. 将立即数3送入寄存器R0
3. 将暂存在R7里P0状态数据送入累加器A【疑问,为什么不在第一步直接将数据送入累加器A呢?】
4. 使寄存器R0自增【疑问,为什么不在第二步直接将数据4送入寄存器R0呢?】
5. R0自减,如果自减后R0≠0,那么执行A循环右移指令(共发生3次移位)
6. 将数据从A送入SFR寄存器P0

案例6
循环右移1位是如何实现的?

在keil仿真窗口可以看到:
截图202411022128516872.jpg
似乎和上面的循环右移3位一模一样,唯一区别就是MOV进R0的立即数有变化。看来_cror_这个实现得非常草率啊,没有任何优化

具体:
1. 将原始数据从P0送入寄存器R7,记为{B7 B6 B5 B4 B3 B2 B1 B0}
2. 将立即数3送入寄存器R0
3. 将暂存在R7里P0状态数据送入累加器A【疑问,为什么不在第一步直接将数据送入累加器A呢?】
4. 使寄存器R0自增【疑问,为什么不在第二步直接将数据4送入寄存器R0呢?】
5. R0自减,如果自减后R0≠0,那么执行A循环右移指令(共发生3次移位)
6. 将数据从A送入SFR寄存器P0

本帖被以下淘专辑推荐:

联系我请点击左下角的【回复】按钮,否则我收不到消息提
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 02:36 , Processed in 0.115502 second(s), 48 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表