作者ksmrt0123 (ksmrt)
看板ASM
标题Re: [问题] 变数问题
时间Sat Jan 16 01:00:48 2010
因为应该会有其它人可能会碰到类似问题,
就直接回版上了, 这样讨论也比较方便.
简单重覆你遇到的问题.
main() 中有段code
: test = 0;
: while(test<0x0130) {...}
而在isr()中会做
: ++test;
除此之外并无其它对test之读写.
遇到的问题是 while 回圈"偶而"会在非预期的时候
(test的值明明还小於0x0130时)就跳出来.
※ 引述《ksmrt0123 (ksmrt)》之铭言:
: 下面有我disasemble的结果.
: test 是定义成unsigned int, 放在 data 0x08(MSB) 跟 0x09(LSB).
: 可看出 test<0x0130要由好几个组合语言指令来完成.
: 你可想看看当test<0x0130做到一半,
: 若发生 RI interrupt,
: 是否有什麽状况会造成你遇到的错误?
: 18: while(test<0x0130) {
: C:0x0012 C3 CLR C
: C:0x0013 E509 MOV A,0x09
: C:0x0015 9430 SUBB A,#0x30
: C:0x0017 E508 MOV A,test(0x08)
: C:0x0019 9401 SUBB A,#0x01
: C:0x001B 500A JNC C:0027
从反组译的程式可看出, test是两个byte的变数,
MSB放0x08, LSB放在0x09. 判断 test<0x0130 是由
0x0015跟0x0019两个SUBB组成, 经过这两个SUBB若
C==0, 表示test<0x0130不成立, 就跳出回圈(0x001B JNC ...).
会发生错误的情况是, 当test==0x00ff时, main()执行
上面那段code 执行到一半时
(0x0015的SUBB已执行完, 但0x0019的尚未执行),
发生interrupt, isr()因此会做 ++test, 故isr()
结束後 test的值是 0x0100.
51现在又回到main()继续刚才未完成的工作.
执行到0x0019那个SUBB, 此时test的MSB的值已是0x01,
前一个SUBB(0xFF-0x30)也不会设定C, 所以运算结果C会是0,
就跳出回圈了. 这就是你遇到的状况.
这个问题最简单的解决方法就是在计算 test<0x0130 时暂时
disable interrupt, 这样 isr()就不会来插一脚造成错误.
但要disable interrupt以这段C code来说, 因为 test<0x0130
是embedded在while loop中, 所以从C直接加不太好加...
另有个相关的问题, main()中的 test = 0; 把test的值写为0
需要分成至少两个指令做, 那会不会有类似的状况造成错误呢?
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 219.68.71.218
※ 编辑: ksmrt0123 来自: 219.68.71.218 (01/16 01:14)
※ 编辑: ksmrt0123 来自: 219.68.71.218 (01/16 11:50)
1F:推 manchester77:分析的真详细... 01/18 10:51
2F:推 Anal:同上... 01/18 13:45
3F:推 ruemann:Good!! 01/18 19:34
4F:→ proach:改用16bits MCU就好了 .......来乱的XD 01/21 21:11