打印

关于keil C中RLC A的问题

[复制链接]
4989|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
walkrain|  楼主 | 2009-12-16 09:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
HWM| | 2009-12-16 09:20 | 只看该作者
RLC A 是带进位左环移,A(类加器)的最高位移入CY(进位标志)

这条指令和 CY = ACC & 0X80 严格意义上不等价,因为PLC A将对A产生副作用。具体作用要看上下文。

使用特权

评论回复
板凳
cubasa| | 2009-12-16 09:22 | 只看该作者
CY = ACC & 0X80,取ACC的最高位,然后赋值给CY,但 ACC 的内容应该不会变,可能事先有备份,RLC A下面还有语句来恢复ACC内容的。
如果直接用嵌入汇编行不行啊?

使用特权

评论回复
地板
不亦心| | 2009-12-16 10:22 | 只看该作者
本帖最后由 不亦心 于 2009-12-16 12:08 编辑
看到了CY = ACC & 0X80; 这条语句会被直接编译成"RLC A"指令,请问这是怎么回事啊 ...
walkrain 发表于 2009-12-16 09:06

这个不可能等价吧
RLC   A,等价于(cy=acc&0x80)&&(acc<<=1)才对吧

使用特权

评论回复
5
walkrain|  楼主 | 2009-12-16 14:17 | 只看该作者
我也知道不等价,但却是被反编译成了"RLC A"指令,我也确实不知道怎么回事

使用特权

评论回复
6
xwj| | 2009-12-16 14:47 | 只看该作者
这个只是Keil编译器下的一个巧合罢了,只是刚好被老Hot找出来的。

要实现CY = ACC & 0X80;,最直接的语句就是编译成
MOV    C,ACC.7
这条语句执行时间是一个机器周期,但是需要2个字节来保存,但肯定不会破坏ACC;

而要现CY = ACC & 0X80;,直接用RLC左移一位,ACC.7当然就会被移入CY中,所以用
RLC    A
的话,也能达到同样的目的,只是这时ACC是变化的(左移了一位)。
而这条语句执行时间也是一个机器周期,但是只需要1个字节来保存,所以在不需保留ACC或者ACC本来就是要移位时,当然就会被编译器优先考虑。


最后,猜测下老Hot发现这个的过程:
我们要移位输出一个字节的每一位是,通常会这样写:
void send(uchar dat)
uchar i;
for(i=0;i<8;i++)
{
    PORT=dat&0x80;
    dat<<=1;
}
而这时,只要肯观察下Keil的汇编代码,就会发现:Keil很聪明的把它编译成了:
MOV   ACC,dat
...
RLC    A                  ;1周期1字节
MOV   PORT,C         ;2周期2字节
...
Keil太聪明了,直接把
    PORT=dat&0x80;
      dat<<=1;
编译成了RLC   A。而且只要你把for(i=0;i<8;i++)写成for(i=8;i;i--),它还会把循环自动优化成DJNZ!
(Keil的优化确实聪明。当然,这还是设计的人聪明,肯花功夫优化:))


而老Hot的红杏出墙是为了得到用C语句出一对一的汇编的效果,当然会仔细观察编译器的语句对应关系,而要得出RLC  A的只要写cy=acc&0x80即可,而不会被编译成MOV    C,ACC.7,所以红杏出墙里也就有了对应RLC A的C语句定义。
——虽然cy=acc&0x80的语义并不只是RLC  A:lol

使用特权

评论回复
7
不亦心| | 2009-12-16 15:23 | 只看该作者
借LZ地盘,跟着LS学到不少东东

使用特权

评论回复
8
walkrain|  楼主 | 2009-12-16 15:42 | 只看该作者
这个只是Keil编译器下的一个巧合罢了,只是刚好被老Hot找出来的。

要实现CY = ACC & 0X80;,最直接的语句就是编译成
MOV    C,ACC.7
这条语句执行时间是一个机器周期,但是需要2个字节来保存,但肯定不会破坏ACC;
...
xwj 发表于 2009-12-16 14:47


真是学习了,看来以前学习还是不够细,细到深处出**

使用特权

评论回复
9
zhy433| | 2009-12-16 16:31 | 只看该作者
牛人

使用特权

评论回复
10
xuexiwen33| | 2009-12-16 16:54 | 只看该作者
学习一下,以前学习没注意这些细节~~

使用特权

评论回复
11
ejack| | 2009-12-16 17:58 | 只看该作者
当初我发现这个编译结果时,还企图给Keil发邮件,被老大阻止:“俺们用盗版,低调,要低调”

使用特权

评论回复
12
不亦心| | 2009-12-16 18:56 | 只看该作者
哈哈,用盗版的都这样:P

使用特权

评论回复
13
hotpower| | 2009-12-16 19:22 | 只看该作者
思路产生于PC编程的bit=A==B;或bit=A>B;bit=(A&1)>0;
故在MCU中就产生了CY=ACC&0x80;CY=ACC&0x01;

XWJ分析基本正确,出处来源于PC端编程的思路
bit=A==B;
肯定比bit=(A==B)?1:0;if (A==B) bit=1;else bit=0;好些。

使用特权

评论回复
14
cubasa| | 2009-12-17 09:39 | 只看该作者
看来真正要玩转C51一定还要有扎实的汇编基础啊。

使用特权

评论回复
15
耕在此行| | 2009-12-17 10:07 | 只看该作者
看来真正要玩转C51一定还要有扎实的汇编基础啊。
cubasa 发表于 2009-12-17 09:39

呵呵 那是肯定的...................

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

47

主题

82

帖子

0

粉丝