你知道C51循环语句中的小秘密吗
时间:06-12 15:50 阅读:1540次
*温馨提示:点击图片可以放大观看高清大图
简介:我本篇文章,其实主要表达的是C51拥有特殊的指令DJNZ,利用它可以提高循环的时空效率。而且,我第一次知道C编译器居然支持这样的写法。这种代码,会让我极为担心编译平台能否理解这些C语言的意图。在单片机的世界里,这个好冒险。
上面两段示例代码中,循环次数都一样,但是在有些平台中,时空效率却大不相同。以51架构单片机为例,我们来分析它编译出来的汇编代码。
从上述的汇编代码中,我们发现用“++”和“--”的两段代码,前者比后者的代码,在空间上多了4条指令共5个字节。时间上,由于这是一个循环语句,累计至少多花费了8次*4=32个指令周期,如果循环次数进一步加大,这一差距就不能忽视。
为何会有如此之多的差异?其本质原因是因为C51拥有一条“复合指令DJNZ”,其定义如下,意为:将“寄存器或者某个ram内的byte变量”的值减1,完事后判断不为0则跳转”。该指令融合了“算术运算 + 逻辑运算 + 跳转”三个功能。
而对于M3平台,两段代码并没有带来明显的时空差异。
这两段汇编,前者之所以比后者多了一句“UXTB r1,r1”,因为加法的值需要32位和8位的数值转换,归零的减法不需要。这又应那个原则:“零值”操作效率较高。
因此,一个软件工程师,需要对其操作平台的指令系统有足够的熟悉,对基本C语句的汇编转换了然于心,才能写出高质、高效的代码。老工程师的价值,也体现在此。
另外值得一提的是,在这个实验中我发现一个比较有意思的现象:在函数while_dec中变量声明兼初始化代码“uint8_t i = 0;”,紧随其后就是“i = 8”的覆盖赋值代码。而它在C51平台编译器上,却产生了一个冗余代码“CLR A”,令人困惑。在M3平台的编译中,就没有这样的现象了。不管怎样,随着编译器越来越智能,变量声明时即刻初始化,是一个非常好的编程习惯,它不会对代码空间增加额外的负担。