[51单片机] 51单片机程序活见鬼,求解释!

[复制链接]
1217|5
 楼主| hualiming025 发表于 2015-7-15 11:13 | 显示全部楼层 |阅读模式
    现象比较奇葩。且听我细细将来。
    话说当前在keil(版本4.12)中编写51程序,用到switch()语句,其中用到按位左移<<。发现其中case跳转异常,发现和左移<<操作有关,但不知为何会这样,甚是郁闷(已经多天没吃饭了)。
    我将程序做了简化处理,但能反应问题。
    先看问题程序,见下图,其中使用了switch语句,注意在语句内部使用到了按位左移<<,且左移最大超过16位(不知道这个是不是原因)。
    问题的现象是:当channel=18时,switch会先跳转到case 17,再转到case 18,然后跳出switch。但switch执行完之后,标志寄存器没有预想中的被赋值为(1<<16),或(1<<17),仍然是0。

再看对应的汇编代码,其中选中部分,分别对应c程序中的case 16和case17两句,注意这两句的跳转地址是一样的,这也印证了为什跳转有问题。

但是,如果我把程序中的按位左移去掉,改为直接赋值,就不存在这个问题了,见下图改后的C程序。

下面这张是对应的汇编,注意其中case 16 和case 17两句的跳转地址已经正常了。

    现象显然和左移操作有关。并且程序中是对长整型l(32位)变量进行操作,如果改为char型变量就不存在这个现象了,我试过。注意其中左移位数最大17位,如果channel的值小于17,比如16,也不存在这个问题。
所以怀疑是不是keil中C51左移最大只能是16?但也不应该,没看到相关规定。
把程序源码附件附后,可下载调试看看。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
diweo 发表于 2015-7-15 13:00 | 显示全部楼层
建议你先把1强制转型。比如
fla|=((unsigned long)1)<<17;

评论

正解!!!  发表于 2015-7-15 14:24
datouyuan 发表于 2015-7-15 14:17 | 显示全部楼层
本帖最后由 datouyuan 于 2015-7-15 14:29 编辑

正确的写法:
  1. case 1        :       标志寄存器_ |=(1ul<<0);                break;
abc_ |=(1ul<<17);

未做特别说明,编译器把“1”看成是INT类型的常数,而51的INT是16bit的。


dirtwillfly 发表于 2015-7-15 16:59 | 显示全部楼层
diweo 发表于 2015-7-15 13:00
建议你先把1强制转型。比如
fla|=((unsigned long)1)


正解。1默认的不是32位无符号数
ayb_ice 发表于 2015-7-15 21:09 来自手机 | 显示全部楼层
有啥诡异的,数字默认是整型的,16位的
您需要登录后才可以回帖 登录 | 注册

本版积分规则

32

主题

114

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部