• 大道至简跑马灯程序设计的新思路


    学过单片机的人大都知道“流水灯”或“跑马灯”之类的名称,具体实现的效果就是按固定规律地循环地显示某组变化。如用一个字节长度的空间来实现“跑马灯”,可以是使该字节的值的变化过程为:

    “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语言的源代码有非常高效的编译方法,使同一目的但不同编程方法实现的代码,最终在硬件上实现非常高效的执行效率。

    那么,既然编译器如此高效,是否意味着:用户可以随意编程,而不考虑编译效率的问题呢?这个问题,有待继续学习、研究!




  • 相关阅读:
    vue seven day
    vue six day
    vue five day
    vue four day
    vue three day
    vue two day
    vue one day
    leetcode105-Golang根据前序遍历与中序遍历构建二叉树
    配置树莓派的frp反向代理与supervisor进程守护与开机自启脚本
    Golang实现二分查找算法
  • 原文地址:https://www.cnblogs.com/techstone/p/3321305.html
Copyright © 2020-2023  润新知