本帖最后由 sedatefire 于 2014-12-17 01:31 编辑
缘起:
前阵子,在博客写个了跑马灯变形记,小火了下,六篇连载霸占了博客热度前六。可惜评论很少,所以这次决定写在论坛里。我在那个博客尾巴留了QQ号,倒是蛮多人加我询问的。最近有个新手问我,遇到51编译一堆报警 uncall segment。表面上是函数没有调用,但本质上还是51的静态编译所致。我觉得有必要以吐槽的方式好好为菜鸟“出气”一下,遂有此文。虽我是新手园地版主,但我觉得这个主题还是放在侃单片机论坛,比较能够得到有价值的共鸣,来佐证我的笔误,毕竟两三年没碰51了。
背景知识理解:
这两个背景知识,就是51万恶的根源....
1. 静态栈编译方式:
连局部变量的地址都是固定的哦。它不是栈压出来的,是编译器他老人家静态分析整个系统树,计算调用深度,运筹帷幄,一次分配给你的。
所以,一旦有游离在外的uncall,不管是函数还是变量,他老人家就紧张兮兮的,非得给你一个黄牌。遇到函数指针那种严重烧脑的动态调用关系,他老人家就崩溃了。
2. C51的四个bank寄存器组。每个using 数字对应一个个bank。
效率靠它,bug也靠它。
C51的吐槽点:
1.waning: uncall segment
不仅是未调用的函数会报Waning,没用到的code也报。
在M3这里,只有static声明的东西没有使用,才会报警。
解决方式:
void uncall_func(void)
{
uint8_t f = 0;
if (f) /* 许多编译器都默许这样的做法,不能吐槽C51暮气昏庸 */
{
As you know
}
}
2. using搞不清
. 不是每个中断要一个单独using,只要优先级不嵌套,用同一个也可以,
. 一处using处处using, 指定using的函数其所调用的所有子子孙孙,都要using或者NOAREG.
. 如果要提高某个效率,可单独分配一个bank给它,就是单独的using数字。
3. 函数指针:不做死就不会死。
51的函数指针,形同**肋,想用它,就要去了解reentry,重入,搞个动态栈,然后就是做死的节奏。
我唯一一次用到,是这样写的
static const FUNC_TYPE func = xxxxxxxxx_function_name;
告诉你,就这样子,编译器都紧张得要死,老版本也分析不了全局树,还会出错。
4. 51的存储类别
xdata/data/code/sbit算是菜鸟能够了解的,加上idata/pdata连我也要爆粗口了
然而其本质上是bus总线访问数据的区别,就是MOV等汇编指令的不同变体。
这方面,还是请个大牛来讲解吧,我目前的理解深度,还没法一气呵成。吐槽无力了
5.大端结构
包括许多老工程师,把51的程序移植到M3后,才发现噩梦其实才刚刚开始。
实际上,许多网络协议,包括自定义的,默认是大端的,我想它的初衷是方便人眼抓包阅读。
但作为一个菜鸟,切不可贪图51的大端便利,写出大小端移植性不好的代码。
不去了解大小端,心里没有度,出来混的,总有还的一天。
6.应该还有很多,但我真心忘却了。
菜鸟大虾们,来尽情吐槽吧... 诸位牛人也会有很强的解答欲望。
|