打印

想了20年的一道小学生题目(奖金30元): 答案在61楼

[复制链接]
楼主: Cortex-M0
手机看帖
扫描二维码
随时随地手机跟帖
21
唉,C51要是玩不了PUSH/POP,叫什么C51?中国人总以为别人差劲,别忘了KEIL是德国人,——自诩地球第一优等民族。别人早解决了,我们中国大侠不知道而已。
   
    LZ真是白学单片机这么多年了,20年?俺2小时就想通了。—— 所长前一阵写的抢占式OS确实不错,但是中断没有跳出汇编,而且只能在C51_V9.0 以上通过,俺放入未来候选资料夹了。

    哈哈……,300元先拿出来放到站长或公证人手上,免得俺公布了答案,LZ不付账。众网友在此做个证啊。


、、

使用特权

评论回复
22
Cortex-M0|  楼主 | 2012-4-10 10:19 | 只看该作者
呵呵~~~

LS  V5 !

2小时就想通了,俺穷,300元俺拿不出,只能拿出30元~~~






继续做广告~~~

哪位高手行行好,帮俺解答这一道小学生题目,奖金30元~~~

使用特权

评论回复
23
airwill| | 2012-4-10 13:50 | 只看该作者
本帖最后由 airwill 于 2012-4-10 13:51 编辑

嗯, C51 支持内联的 PUSH  POP 指令函数
严格讲, 不能将函数, 必须成对使用(跟 PUSH POP 一样). 否则死机

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
Cortex-M0 + 1
24
Cortex-M0|  楼主 | 2012-4-10 13:58 | 只看该作者
嗯, C51 支持内联的 PUSH  POP 指令函数
严格讲, 不能将函数, 必须成对使用(跟 PUSH POP 一样). 否则死机
airwill 发表于 2012-4-10 13:50



C51 支持内联的 PUSH  POP 指令函数,  只能应用在高8位的特殊寄存器上(如ACC等),对低8位的寄存器(如R0-R7等),均不支持,因此,无法有效保存R0-R7等寄存器值。

使用特权

评论回复
25
刘前辈| | 2012-4-10 15:49 | 只看该作者
本帖最后由 刘前辈 于 2012-4-10 15:55 编辑

唉,还想不通?提示一下:

1、把中断C函数写成一个单独的模块,——例如:Int.C;
2、自己接着想……
3、将Int.C 加入项目与main主函数一起连接,妥啦!

Int.C是纯C语言写的中断函数,无任何汇编语句;内容举例:

void  timer0(  )  interrupt  0
{
if ( TI ){……};
……
}

用C51_V9.0以上版本编译,L51连接,看看中断程序0003H是不是自动压栈所有寄存器?——kEIL早就想到并解决了的问题。

不过不能怨LZ,C51_V9.0是2009年才升级出来的。3年以前(V7版本)这么写可得不到压栈所有寄存器。


、、

使用特权

评论回复
26
Cortex-M0|  楼主 | 2012-4-10 18:49 | 只看该作者
谢谢LS盆友解答~~~

根据LS盆友要求:
1.  特地从网上下载了C51_V9.0版本,并安装之。
2.  将中断C函数写成一个单独的模块,Int.C
3.  将LS盆友的示例程序拷贝并加入单独的Int.C 模块。
4.  将Int.C 加入项目与main主函数一起连接编译。

得出如下结果,请见下图中的反汇编。中断程序0003H并没有自动压栈所有寄存器。





使用特权

评论回复
27
zoomone| | 2012-4-10 21:05 | 只看该作者
围观

使用特权

评论回复
28
ejack| | 2012-4-11 07:52 | 只看该作者
……这坛里的奇人异士,前辈绝对算一个……

使用特权

评论回复
29
lixiaoxu2meng| | 2012-4-11 08:13 | 只看该作者
关注

使用特权

评论回复
30
刘前辈| | 2012-4-11 08:25 | 只看该作者
本帖最后由 刘前辈 于 2012-4-11 08:29 编辑

#27楼版主LZ没注意到我26楼说的内容?关键诀窍就在2、自己接着想……

哈哈,不加入第2.条,C51_V9.0可发挥不了作用。这第2.条,LZ想了三年,俺想了+实验一共2小时。

看俺给你演示一个:






、、

使用特权

评论回复
31
Cortex-M0|  楼主 | 2012-4-11 08:27 | 只看该作者
继续求解,顶贴有分~~~   

哪位高手行行好,帮俺解答这一道小学生题目,奖金30元~~~

使用特权

评论回复
32
highgear| | 2012-4-11 21:58 | 只看该作者
20楼的 ejack 很有道理。

其实这个问题,还是得看视角。 如果从实用的角度,那么毫无疑问, 效率优先,内核必须使用汇编;但如果从学习的角度看, 那么最好是纯 C.

使用纯c, 那么就面临一个如何控制中断stack 的问题,Keil的智能化并未智能到能辨别出任务的地步。 类似的问题在 Borland C++ 中也存在,由于不同类型的 cpu 选项 (8086, 80286, 80386, 80486等)会导致register 保存的长度不一, 但此问题可以同过 macro 来解决, 而Keil C 的问题只能通过compiler 中的特殊特性来解决,也就是说,通过找到 keil C 的“漏洞", 避开编译器的限制来解决。

一个简单的方法是:在中断中嵌入一句汇编,比如 nop. 此时, Keil 会把所有 context register (r0-r7,A,B,dptr,psw)push/pop. 这种 undocumented 特性非常令人沮丧,因为你得自己去挖掘,测试,而且不知道以后的版本是否支持。

综合来看, 以前 Cortex-M0 给出的方案最佳,用最少的汇编避开编译器的statck 控制,这样最大程度地保留了程序的“端庄”性。
  

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
Cortex-M0 + 1
33
airwill| | 2012-4-11 22:33 | 只看该作者
技术需要精益求精, 不断探索.
但是如果走到了玩弄技巧, 甚至"钻牛角尖" 的地步, 就又不可取了.
其实这个问题, 还是关键取决于 Keil c 编译器的特性.
所以可能未必有个完美的 解.

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
Cortex-M0 + 1
34
Cortex-M0|  楼主 | 2012-4-12 07:22 | 只看该作者
技术需要精益求精, 不断探索.
但是如果走到了玩弄技巧, 甚至"钻牛角尖" 的地步, 就又不可取了.
其实这个问题, 还是关键取决于 Keil c 编译器的特性.
所以可能未必有个完美的 解. ...
airwill 发表于 2012-4-11 22:33



做产品,俺一定精益求精, 不断探索,寻找成本最低性能最好之方案。

但是玩玩呢,有时“玩弄点技巧”, “钻点牛角尖”并不是不可取了,为自已为大伙图点笑料乐一乐罢了。

至于有解没解,是否是完美的解,要看各人的造化了。

使用特权

评论回复
35
Cortex-M0|  楼主 | 2012-4-12 07:32 | 只看该作者
20楼的 ejack 很有道理。

其实这个问题,还是得看视角。 如果从实用的角度,那么毫无疑问, 效率优先,内核必须使用汇编;但如果从学习的角度看, 那么最好是纯 C.

使用纯c, 那么就面临一个如何控制中断stack 的问题,Keil的智能化并未智能到能辨别出任务的地步。 类似的问题在 Borland C++ 中也存在,由于不同类型的 cpu 选项 (8086, 80286, 80386, 80486等)会导致register 保存的长度不一, 但此问题可以同过 macro 来解决, 而Keil C 的问题只能通过compiler 中的特殊特性来解决,也就是说,通过找到 keil C 的“漏洞", 避开编译器的限制来解决。

一个简单的方法是:在中断中嵌入一句汇编,比如 nop. 此时, Keil 会把所有 context register (r0-r7,A,B,dptr,psw)push/pop. 这种 undocumented 特性非常令人沮丧,因为你得自己去挖掘,测试,而且不知道以后的版本是否支持。

综合来看, 以前 Cortex-M0 给出的方案最佳,用最少的汇编避开编译器的statck 控制,这样最大程度地保留了程序的“端庄”性。

highgear 发表于 2012-4-11 21:58



由于插入了汇编,哪怕再少,也违背了highgear老师的本意,破坏了C代码的美感,对C程序的"端庄"性也有影响。


此小学生题目,能被匠人看中置顶,一定有其道理和合理性~~~

面包会有的,粮食会有的,一切都会有的~~~

俺坚信,二姨家高手如云,最后一定有个比 highgear老师推荐的 Cortex-M0给出的方案更佳的方案,完全脱离汇编,又能避开编译器的statck 控制,C代码又简洁明了,完完全全保留了C程序的“端庄”性。

使用特权

评论回复
36
Cortex-M0|  楼主 | 2012-4-12 07:36 | 只看该作者
按照 31楼盆友 的指示, 关键诀窍就在2、自己接着想……


继续接着想,顶贴者人人有分~~~   

哪位高手行行好,指点一下,帮俺解答这一道小学生题目,奖金30元~~~

使用特权

评论回复
37
刘前辈| | 2012-4-12 12:20 | 只看该作者
本帖最后由 刘前辈 于 2012-4-12 12:24 编辑

小意思,看咱解的,不用加入任何汇编语句,一样让C51编译器自动保存13R。
哈哈,早就说过,KEIL已经想到过这个问题,它的V9.0以上版本具有这个功能,设置一下,告诉编译器就行了。——谁都知道C51和RTX51嵌入式多任务操作系统是关联的!是同时一起设计的。




不需要在中断C函数中加入任何技巧性汇编语句。


、、

使用特权

评论回复
38
Cortex-M0|  楼主 | 2012-4-12 12:45 | 只看该作者
本帖最后由 Cortex-M0 于 2012-4-12 13:19 编辑

俺笨,实在弄不懂理不顺~~~

一会儿,   关键诀窍就在2、自己接着想……

一会儿又, 不用加入任何汇编语句,一样让C51编译器自动保存13R。……

图片真伪先不说,结果,程序所占Flash增加了N多~~~ :dizzy:

任何实验,都需要列出方法,让其他网友克隆照抄验证通过。

否则,跟周老虎PS一下图片,没啥两样~~~

使用特权

评论回复
39
Cortex-M0|  楼主 | 2012-4-12 12:46 | 只看该作者
将革命继续到底,顶贴者人人有分~~~   

哪位高手行行好,指点一下,帮俺解答这一道小学生题目,奖金30元~~~

使用特权

评论回复
40
Cortex-M0|  楼主 | 2012-4-12 13:08 | 只看该作者
本帖最后由 Cortex-M0 于 2012-4-12 16:46 编辑

现在讨论的是 highgear老师 玩耍的 8051 下的任务调度器 OSex,要求在 highgear老师的示范程序中,不插入任何汇编代码,保护所有受影响的特殊寄存器,并且要求程序简洁明了,按照26楼:盆友的要求,在 highgear老师的示范程序中,加入 Int.c 函数,再根据38楼:盆友示范程序所示,加入了STARTUP.A51,编译后的程序总长度不到 700H,而38楼:盆友的示范程序,长度为多少呢?程序总长度已超过了990H ,  程序长度增加了 290H之多, 这个这个水平之高。。。。。。俺小学生永远也比不上~~~  :curse:





根据26楼:盆友要求,所写的程序总长度不到 700H。






38楼:盆友所写的程序总长度已超过了990H。

使用特权

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

本版积分规则