独闷闷网

 找回密码
 立即注册
搜索
查看: 3916|回复: 0
收起左侧

[原创] 51单片机main函数如果没有while(1),执行到main最后一行时程序会重新运行吗?已解答。

[复制链接]
发表于 2015-3-2 08:15:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
王华—四川:

  1. #include <reg52.h>          
  2. void Delay10ms(unsigned int);   

  3. void main()
  4. {
  5. /*        while(1) */
  6. //        {            
  7. P2  = 0x00;    //置P0口为低电平
  8. Delay10ms(50); //调用延时程序
  9. P2  = 0xff;    //置P0口为高电平
  10. Delay10ms(50); // 调用延时程序
  11. //        }
  12. }
  13. void Delay10ms(unsigned int c)   
  14. {
  15.     unsigned char a,b;
  16.     for(;c>0;c--)
  17.         for(b=38;b>0;b--)
  18.             for(a=130;a>0;a--);
  19. }
复制代码

为啥子while的作用去不掉呢?灯还在闪烁呀?

斌+汕头:
问你,main函数中最后一条指令执行完后,应该跳转到哪里?

王华—四川:
呃,不晓得,求指点。

斌+汕头:
因为51单片机我们开发,main函数并没有使用标准的C语言。
main

        ***********
        ***********

最后是跳转到mian;

详细分析如下:
一、没有while(1)示例代码(示例一):
  1. #include <reg52.h>             
  2. void delay(int x);
  3. void main()
  4. {   
  5.                 P2  = ~P2;
  6.                 delay(2);
  7.                 P1=0;
  8. }

  9. void delay(int x)
  10. {
  11.         for(;x>0;x--);
  12. }
复制代码


二、反汇编
  1. C:0x0000    020024   LJMP     C:0024
  2.     10: void delay(int x)
  3.     11: {
  4.     12:         for(;x>0;x--);
  5. C:0x0003    D3       SETB     C
  6. C:0x0004    EF       MOV      A,R7
  7. C:0x0005    9400     SUBB     A,#0x00
  8. C:0x0007    EE       MOV      A,R6
  9. C:0x0008    6480     XRL      A,#P0(0x80)
  10. C:0x000A    9480     SUBB     A,#P0(0x80)
  11. C:0x000C    4007     JC       C:0015
  12. C:0x000E    EF       MOV      A,R7
  13. C:0x000F    1F       DEC      R7
  14. C:0x0010    70F1     JNZ      delay(C:0003)
  15. C:0x0012    1E       DEC      R6
  16. C:0x0013    80EE     SJMP     delay(C:0003)
  17.     13: }
  18. C:0x0015    22       RET      
  19.      3: void main()
  20.      4: {   
  21.      5:                 P2  = ~P2;  
  22. C:0x0016    63A0FF   XRL      P2(0xA0),#0xFF
  23.      6:                 delay(2);
  24. C:0x0019    7F02     MOV      R7,#0x02
  25. C:0x001B    7E00     MOV      R6,#0x00
  26. C:0x001D    120003   LCALL    delay(C:0003)
  27.      7:                 P1=0;
  28. C:0x0020    E4       CLR      A
  29. C:0x0021    F590     MOV      P1(0x90),A
  30.      8: }
  31. C:0x0023    22       RET      
  32. C:0x0024    787F     MOV      R0,#0x7F
  33. C:0x0026    E4       CLR      A
  34. C:0x0027    F6       MOV      @R0,A
  35. C:0x0028    D8FD     DJNZ     R0,C:0027
  36. C:0x002A    758107   MOV      SP(0x81),#0x07
  37. C:0x002D    020016   LJMP     main(C:0016)
复制代码

三、解释说明(示例一):
1、汇编都是从0x0000处开始运行程序,反汇编中,0x0000处直接跳转至0x0024;
2、0x24 ~ 0x002D为启动代码,该段代码的主要功能是,清内存、置堆栈、跳转至main。
3、 RET :子程序返回指令,  LCALL:子程序调用指令。
4、若main函数中没有while(1)循环,则main函数最后一条指令是ret,也就是说main函数被当作子函数一样调用了,有ret返回。那么问题来了,如下:
主函数不能被调用,只能被执行,也就是说只有ret,没有call。
主函数只能存在一个,在启动代码中main是使用跳转指令进入的,并不是使用LCALL,如若使用ret进行返回,必然导致程序复位,跳转至0x0000处,程序将重新运行。



乐于分享,勇于质疑!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|独闷闷网 ( 粤ICP备12007667号-2 )

GMT+8, 2021-4-22 11:43 , Processed in 0.141422 second(s), 18 queries .

快速回复 返回顶部 返回列表