大道至简--跑马灯程序设计的新思路
学过单片机的人大都知道“流水灯”或“跑马灯”之类的名称,具体实现的效果就是按固定规律地循环地显示某组变化。如用一个字节长度的空间来实现“跑马灯”,可以是使该字节的值的变化过程为:
“0000 0001B” -> "0000 0010B” -> "0000 0100B” -> "0000 1000B” -> "0001 0000B” -> "0010 0000B” -> "0100 0000B” -> "1000 0000B” -> "0000 0001B” (循环)
假设,现在需要实现将一个int类型变量中的值从0至9的“跑马灯”变化过程,那么一般的方法是:
初版:
int val = 0; while(1) { val++; if( val > 9 ) val = 0; }//End;
在Keil uv3环境中使用ATMEL 89C51配置,编译后的汇编代码为:
C:0x0000 020010 LJMP C:0010 2: void main() 3: { 4: unsigned char val = 0; 5: C:0x0003 E4 CLR A C:0x0004 FF MOV R7,A 6: while(1) 7: { 8: val++; C:0x0005 0F INC R7 9: if( val > 9 ) C:0x0006 EF MOV A,R7 C:0x0007 D3 SETB C C:0x0008 9409 SUBB A,#0x09 C:0x000A 40F9 JC C:0005 10: val = 0; C:0x000C E4 CLR A C:0x000D FF MOV R7,A 11: } C:0x000E 80F5 SJMP C:0005 C:0x0010 787F MOV R0,#0x7F C:0x0012 E4 CLR A C:0x0013 F6 MOV @R0,A C:0x0014 D8FD DJNZ R0,C:0013 C:0x0016 758107 MOV SP(0x81),#0x07 C:0x0019 020003 LJMP main(C:0003)
精简修改版:
int val = 0; while(1) { if( (++val) > 9 ) val = 0; }
在Keil uv3环境中使用ATMEL 89C51配置,编译后的汇编代码为:
C:0x0000 020010 LJMP C:0010 2: void main() 3: { 4: unsigned char val = 0; 5: C:0x0003 E4 CLR A C:0x0004 FF MOV R7,A 6: while(1) 7: { 8: if( (++val) > 9 ) C:0x0005 0F INC R7 C:0x0006 EF MOV A,R7 C:0x0007 D3 SETB C C:0x0008 9409 SUBB A,#0x09 C:0x000A 40F9 JC C:0005 9: val = 0; C:0x000C E4 CLR A C:0x000D FF MOV R7,A 10: } C:0x000E 80F5 SJMP C:0005 C:0x0010 787F MOV R0,#0x7F C:0x0012 E4 CLR A C:0x0013 F6 MOV @R0,A C:0x0014 D8FD DJNZ R0,C:0013 C:0x0016 758107 MOV SP(0x81),#0x07 C:0x0019 020003 LJMP main(C:0003)
从上面两个例子来看,KeilC51对源文件进行编译后,生成的汇编代码一模一样,也就是说,前面两个编程方法,虽然从C语言的角度看有些许差异,但最终编译为机器码后,前后两个代码的执行效率是一样的。
以上两种C语言格式的编程方法,是目前为止笔者所掌握的方法,但是今日学习张孝祥所著的《JAVA就业培训教程》时,了解至一种新的编程方法或者说是编程思路,用来实现此例中的”跑马灯“效果过程如下:
unsigned char val = 0; while(1) { val = (val+1)%10; }在Keil uv3环境中使用ATMEL 89C51配置,编译后的汇编代码为:
C:0x0000 020010 LJMP C:0010 2: void main() 3: { 4: unsigned char val = 0; 5: C:0x0003 E4 CLR A C:0x0004 FF MOV R7,A 6: while(1) 7: { 8: val = (val+1)%10; C:0x0005 0F INC R7 C:0x0006 EF MOV A,R7 C:0x0007 D3 SETB C C:0x0008 9409 SUBB A,#0x09 C:0x000A 40F9 JC C:0005 9: } C:0x000C E4 CLR A C:0x000D FF MOV R7,A 10: } C:0x000E 80F5 SJMP C:0005 C:0x0010 787F MOV R0,#0x7F C:0x0012 E4 CLR A C:0x0013 F6 MOV @R0,A C:0x0014 D8FD DJNZ R0,C:0013 C:0x0016 758107 MOV SP(0x81),#0x07 C:0x0019 020003 LJMP main(C:0003)
结果是笔者发现,对上面三种C语言风格的不同的编程方法(或称过程),经过KeilC51编译器编译为汇编代码后,汇编代码竟然一模一样。既然汇编代码一样,那么相应的机器代码也就一样,最终表现出来的代码执行效率、时间就是一样的。
至此,笔者惊讶于Keil公司的编译器竟是如此"高效“和”智能化“,为同一目标而编写的,但使用不同风格的编程方法编写出来的程序,代码经过编译后,最终的执行效率竟然几乎一致。
由此得出,Keil对C语言的源代码有非常高效的编译方法,使同一目的但不同编程方法实现的代码,最终在硬件上实现非常高效的执行效率。
那么,既然编译器如此高效,是否意味着:用户可以随意编程,而不考虑编译效率的问题呢?这个问题,有待继续学习、研究!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述