4762|15

72

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

求助关于 C51 的问题 [复制链接]

我的C51版本是 8.12
现在有点问题,如下的程序

  1. ACC=Data;
  2. for(i=8;i;i--)
  3. {
  4. ACC<<=1;
  5. SDA=CY;
  6. SCL=1;
  7. _nop_();
  8. SCL=0;
  9. }
复制代码

为了加快速度,我准备使用ACC累加器的左移功能,
但是编译出来的代码却是这样的,

  1.    640: ACC=Data;
  2. C:0x1B00    EF       MOV      A,R7
  3.    641: for(i=8;i;i--)
  4. C:0x1B01    7F08     MOV      R7,#0x08
  5.    642: {
  6. [color=#FF0000]   643: ACC<<=1;
  7. C:0x1B03    25E0     ADD      A,ACC(0xE0)[/color]
  8.    644: SDA=CY;
  9. C:0x1B05    9280     MOV      SDA(0x80.0),C
  10.    645: SCL=1;
  11. C:0x1B07    D281     SETB     SCL(0x80.1)
  12.    646: _nop_();
  13. C:0x1B09    00       NOP      
  14.    647: SCL=0;
  15. C:0x1B0A    C281     CLR      SCL(0x80.1)
  16.    648: }
复制代码

奇怪的是,使用ACC的右移功能,却能生成正确的代码,如下所示,

  1. ACC=Data;
  2. for(i=8;i;i--)
  3. {
  4. ACC>>=1;
  5. SDA=CY;
  6. SCL=1;
  7. _nop_();
  8. SCL=0;
  9. }
复制代码

生成的代码如下
  1.    640: ACC=Data;
  2. C:0x1B00    EF       MOV      A,R7
  3.    641: for(i=8;i;i--)
  4. C:0x1B01    7F08     MOV      R7,#0x08
  5.    642: {
  6. [color=#FF6600]   643: ACC>>=1;
  7. C:0x1B03    C3       CLR      C
  8. C:0x1B04    13       RRC      A[/color]
  9.    644: SDA=CY;
  10. C:0x1B05    9280     MOV      SDA(0x80.0),C
  11.    645: SCL=1;
  12. C:0x1B07    D281     SETB     SCL(0x80.1)
  13.    646: _nop_();
  14. C:0x1B09    00       NOP      
  15.    647: SCL=0;
  16. C:0x1B0A    C281     CLR      SCL(0x80.1)
  17.    648: }
复制代码

请问哪位知道怎么解决吗,我用最新的C51 9.0 版编译也是一样的。
感觉非常郁闷,为什么右移可以,左移不行呢?

最新回复

谢谢,不过我用的KEIL C51 好像不能编译汇编文件,提示编译成功,结果目录下什么都没有 另外C51里好像是不能直接嵌入汇编指令的,如果加入了汇编指令,那么必须加 SRC 编译选项来生产汇编文件,且仅仅只生成汇编文件。 改善这几条语句的目的主要是因为这是一个保存数据的子程序,需要循环大量的调用。   详情 回复 发表于 2010-2-1 15:29
点赞 关注

回复
举报

72

帖子

0

TA的资源

纯净的硅(初级)

沙发
 
ACC+ACC,就是ACC*2,就是ACC<<1,左移的结果是对的,但对C的影响不是你想要的

改成这样吧:
for(i=8;i;i--)
{
if (Data & 0x80) SDA=1;
else             SDA=0;
Data<<=1;
SCL=1;
_nop_();
SCL=0;
}
 
 

回复

86

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
一般来说,C语言的左移和右移只保证与操作相关的变量有正确的影响,但可能会有多种实现方法,不能保证特定寄存器一定产生某种影响
 
 
 

回复

65

帖子

0

TA的资源

一粒金砂(初级)

4
 
非常感谢楼上的回答,我的目的主要是想提高速度,有没有什么办法把那个位置的指令改成RLC A,我试过了在ACC<<=1;的位置用一条空指令代替然后在HEX文件里把这里改成0x33即RLC A的机器码,结果好像不行,请问怎么修改HEX文件,使ACC<<=1位置变成RLC A
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

5
 
楼主这不是闲得慌吗?这样写C代码还不如用汇编代码好点。
 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

6
 
包含intrins.h头文件:
#inclucle
再调用_crol_(val,n)函数
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

7
 
引用 4 楼 hgjinwei 的回复:
楼主这不是闲得慌吗?这样写C代码还不如用汇编代码好点。

不好意思,关键是只有这么一个地方,如果为了这个全用汇编写,想想也不划算啊
 
 
 

回复

79

帖子

0

TA的资源

一粒金砂(初级)

8
 
引用 5 楼 tcdzyq 的回复:
包含intrins.h头文件:
#inclucle
再调用_crol_(val,n)函数

这个方法我试过了,不行
生成的代码更加复杂
 
 
 

回复

59

帖子

0

TA的资源

一粒金砂(初级)

9
 
还好我找到了一个折中的办法,通过访问ACC的位来提高速度,这样会生成两条指令,可以接受了
MOV C,ACC.7
MOV SDA,C
ADD ACC,ACC
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

10
 
好像不值得为几个周期的改善花费这么大力气.
用一个判断其实是最好的: 逻辑清晰,也不会慢什么.

你那样改的代码,维护进来会是恶梦.
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

11
 
直接嵌入汇编
_asm("LSL A");
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

12
 
注意。左右移动位的时候,最高位和最低位是填充的什么? 1 或者 0?
 
 
 

回复

69

帖子

0

TA的资源

一粒金砂(初级)

13
 
引用 6 楼 fycom200 的回复:
引用 4 楼 hgjinwei 的回复:
楼主这不是闲得慌吗?这样写C代码还不如用汇编代码好点。

不好意思,关键是只有这么一个地方,如果为了这个全用汇编写,想想也不划算啊
Asm.asm

NAME        SEND

SDA                BIT        0x80.0
SCL                BIT        0x80.1

PUBLIC        _Send

SEND SEGMENT CODE

RSEG SEND
_Send :
        MOV                A,R7
        MOV                R7,#08H
SND_LOOP:
        RLC          A
        MOV                SDA,C
        SETB        SCL
        NOP
        CLR                SCL
        DJNZ        R7,SND_LOOP
        RET


END

复制代码

C.c

  1. void Send(unsigned char dat);

  2. int main(void)
  3. {
  4.     unsigned char c;

  5.     while(1)
  6.     {
  7.         Send(c);
  8.         c++;
  9.     }
  10. }
复制代码

不需要全部使用汇编的。
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

14
 
上面的汇编代码不安全,应该改成这样

  1. NAME        SEND

  2. SDA                BIT        0x80.0
  3. SCL                BIT        0x80.1

  4. PUBLIC        _Send

  5. SEND SEGMENT CODE

  6. RSEG SEND
  7. _Send :
  8.         PUSH        ACC
  9.         PUSH        PSW
  10.         MOV                A,R7
  11.         MOV                R7,#08H
  12. SND_LOOP:
  13.         RLC          A
  14.         MOV                SDA,C
  15.         SETB        SCL
  16.         NOP
  17.         CLR                SCL
  18.         DJNZ        R7,SND_LOOP

  19.         POP                PSW
  20.         POP                ACC
  21.         RET


  22. END
复制代码
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

15
 
没有必要.编译器会处理的,如果它调用了函数,它不会假定ACC/B/PSW/R0-R7/DPTR没改变
 
 
 

回复

72

帖子

0

TA的资源

一粒金砂(初级)

16
 
谢谢,不过我用的KEIL C51 好像不能编译汇编文件,提示编译成功,结果目录下什么都没有
另外C51里好像是不能直接嵌入汇编指令的,如果加入了汇编指令,那么必须加 SRC 编译选项来生产汇编文件,且仅仅只生成汇编文件。
改善这几条语句的目的主要是因为这是一个保存数据的子程序,需要循环大量的调用。
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表