打印

难道我发现了Keil的BUG?请各位高手看一看——有图有真相

[复制链接]
26364|143
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
XIANSir|  楼主 | 2011-2-28 14:27 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 XIANSir 于 2011-3-5 14:48 编辑

没耐心的请直接看第1楼的现象和第31楼我从汇编发现的问题——看看到底是不是BUG

又有最新进展,见39楼

事情明白了,的确是我对C的理解不到位造成的,并不是KEIL的BUG。详情见48楼。
另外,在47楼123jj前辈也给出了完全正确的解释,虽然我是自己想出问题所在的,不过还是非常感谢前辈的指点。

不过48楼还有一个比较棘手的问题,请高手再点拨点拨。

顺便为了21IC能够更好,提一个题外的建议:21IC的网站兼容性实在不佳啊,我一直都用GOOGLE浏览器,可是在谷歌浏览器里面网站提供的很多功能却没法使用——比如上传照片、修改帖子,害得我还得专门打开IE6去做这些事情。希望21IC能够改进这些问题——纯属建议,只为让21IC越来越好

问题已经解决,结论是:避免出现这种闹心问题的最好方法是对于位变量(bit变量和位域变量)只对其使用逻辑运算符,而不要对其使用按位运算符。
记住能够对位变量(bit变量和位域变量)应用哪些运算符的最简单方式是:把位变量看作是bool类型而不是整数类型。

结贴!!

在看过124楼前辈的发言之后,我深感惭愧,我不得不承认,我在此处以及63楼给的出结论都是根本性错误的,位域不该被看作是bool类型,位域其实就是数量类型(1位的整型类型)。
在标准C语言中,根本就没有布尔类型,而Keil C51中的bit类型与bool类型几乎完全相同,所以将bit类型当作bool类型来用基本上不用有任何的担心

这也就是为什么对bit变量应用按位取反和对位域变量应用按位取反时现象完全不同的根本原因:其实bool类型是不支持按位操作的,这也是为什么不说bit类型就是bool类型的原因,但是在Keil的实现中bit变量的按位取反操作效果和bool类型的逻辑取反操作效果完全相同。而位域呢,由于它本身是数量类型(1位整型),而标准C支持的CPU绝大多数都没有位处理机,所以对位域变量进行计算时必须扩展为char、int等类型然后进行计算,比如对于1位的位域pin.b_1进行按位取反,假设此位域值为1,那么按位取反后的结果在51上是0xFE,而在ARM7上为0xFFFFFFFE。

大家可以试一试,位域类型支持所有整型支持的运算符(我试过加法、乘法、按位取反、位移),但是bit连加法都不支持。









相关帖子

沙发
XIANSir|  楼主 | 2011-2-28 14:29 | 只看该作者
上面是我仿真的情况截图,程序很简单,

最下面是我使用的软件的版本

使用特权

评论回复
板凳
XIANSir|  楼主 | 2011-2-28 14:35 | 只看该作者
这里我我实验的程序源码和工程,有条件的可以试一下:
低成本倒计时牌(程序代码).rar (1.79 MB) test.rar (405 Bytes)

使用特权

评论回复
地板
XIANSir|  楼主 | 2011-2-28 14:38 | 只看该作者
这个简单例子是从我的实际工程中的一段代码抽象出来的,可搞死我了,竟然会有这种现象。
我最初使用的代码是上面第二个图里面的那样子,可是程序运行不符合我想到的情况,改为上面第四个图里面那样子程序才运行正常

使用特权

评论回复
5
XIANSir|  楼主 | 2011-2-28 14:45 | 只看该作者
热烈期盼高手解疑答惑:这是为什么呢???

使用特权

评论回复
6
NE5532| | 2011-2-28 16:59 | 只看该作者
仿真有BUG再正常不过了,所以提倡不要仿真,找这个问题也很无聊,会耽误你赚钱的时间。

使用特权

评论回复
7
XIANSir|  楼主 | 2011-2-28 17:06 | 只看该作者
6# NE5532
我前面已经说过,这是我实际工程里面的代码,在实物上验证就是和仿真的现象一致的,其实是先在实物上发现运行不正确,所以才通过软件仿真来查找出错的原因的,要不是有软件仿真的话,恐怕我到现在还不知道程序哪里出了错误呢——我们公司没有硬件仿真器,都是直接烧到片子里试的。


不过,我也确实不该这么耽误大家的时间,下一步从汇编开始,看看到底是怎么回事

使用特权

评论回复
8
mohanwei| | 2011-2-28 18:11 | 只看该作者
对于bit的逻辑操作,应用“!”
例如把pin.b_3 = (~pin.b_1) && (~pin.b_2);改成
        pin.b_3 = (!pin.b_1) && (!pin.b_2);就符合你的设计目标了

使用特权

评论回复
9
chen3bing| | 2011-2-28 18:27 | 只看该作者
楼主搞错了,应该用按位与&。

使用特权

评论回复
10
XIANSir|  楼主 | 2011-2-28 19:29 | 只看该作者
9# chen3bing
我没搞错,我的表达式结果是要用于if语句的条件,所以我需要的肯定是逻辑与。

而且,为什么第一张图片的结果是对的呢,那里也是逻辑与啊。而且我认为,您应该仔细看一下第一张图和第三张图,比较一下其实是一模一样的——难道不是吗?但结果就完全相反,这是为什么呢??

使用特权

评论回复
11
XIANSir|  楼主 | 2011-2-28 19:34 | 只看该作者
8# mohanwei
谢谢,你的方法的确能得到正确的结果。

但我更想知道的是,图片1中的情况和图片三中的情况完全一样——难道不是吗?为什么图片1得到了正确的结果,但图片3却得到了错误的结果呢??

还有,图片3和图片7为什么会有不同的结果呢?为什么图片5和图片7的结果又是一样的呢??

您难道不认为这值得深入思考吗???

使用特权

评论回复
12
Hello_LeeHom| | 2011-2-28 19:44 | 只看该作者
白娘子、你好白、

使用特权

评论回复
13
sdpz| | 2011-2-28 19:46 | 只看该作者
不认为。图片看得眼花缭乱。

使用特权

评论回复
14
XIANSir|  楼主 | 2011-2-28 19:53 | 只看该作者
13# sdpz
图片很简单吧:一共8幅程序的图片,共展示了两个程序,每个程序有四张图片。图片里展示了程序运行到while(1)时8个主要变量的值。就这么简单

如果还看不懂的话,可以下载程序自己试一下。

使用特权

评论回复
15
XIANSir|  楼主 | 2011-2-28 20:06 | 只看该作者
12# Hello_LeeHom
娶妻能如白娘子,此生再苦又如何!

头像是俺滴梦中情人!

使用特权

评论回复
16
NE5532| | 2011-2-28 20:14 | 只看该作者
6# NE5532
我前面已经说过,这是我实际工程里面的代码,在实物上验证就是和仿真的现象一致的,其实是先在实物上发现运行不正确,所以才通过软件仿真来查找出错的原因的,要不是有软件仿真的话,恐怕我到现在还不知 ...
XIANSir 发表于 2011-2-28 17:06


我搞了7年都没用过硬件仿真器哈,你可在目标板上找个东东来跟踪,比如用串口发送变量值,看是在哪里被改的。

使用特权

评论回复
17
XIANSir|  楼主 | 2011-2-28 20:18 | 只看该作者
16# NE5532
我有更好的方法,直接读产生的汇编代码——这总不会受软件仿真的影响了吧。

正在进行中,有一句不懂:

ANL A,#B(0xF0)

不知道#B是什么意思啊,希望知道的指点一下

使用特权

评论回复
18
NE5532| | 2011-2-28 20:26 | 只看该作者
16# NE5532
我有更好的方法,直接读产生的汇编代码——这总不会受软件仿真的影响了吧。

正在进行中,有一句不懂:

ANL A,#B(0xF0)

不知道#B是什么意思啊,希望知道的指点一下 ...
XIANSir 发表于 2011-2-28 20:18


除非找非常BT的故障,一般不需要去读反汇编,keil是一个很成熟的软件,仿真可能有漏洞,但是编译上出问题的概率很小,遇到这种现象,先应该从自己是不是犯了低级错误入手去寻找,把程序分段,用对外接口(例如串口和显示屏)的方式跟踪程序的运行结果,而不是一头扎进深水里。

使用特权

评论回复
19
ayb_ice| | 2011-2-28 20:26 | 只看该作者
LS
B寄存器的地址就是0xf0

对于位建议用!b而不是~b,类似的问题我在IAR的EW8051中也有出现过,这种位域的&操作甚至直接被优化掉了,但用&&就很正常

可见应该不是KEIL的BUG,这里面的细节可能只有C专家知道了,或者写编译器的人清楚

使用特权

评论回复
20
chen3bing| | 2011-2-28 20:28 | 只看该作者
漂亮的白娘子,我试了一下,用&也可以得到正确的结果。

使用特权

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

本版积分规则

个人签名:冷暖自知,泰然处之;持之以恒,必有所成!

0

主题

609

帖子

2

粉丝