|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
王华—四川:
- #include <reg52.h>
- void Delay10ms(unsigned int);
- void main()
- {
- /* while(1) */
- // {
- P2 = 0x00; //置P0口为低电平
- Delay10ms(50); //调用延时程序
- P2 = 0xff; //置P0口为高电平
- Delay10ms(50); // 调用延时程序
- // }
- }
- void Delay10ms(unsigned int c)
- {
- unsigned char a,b;
- for(;c>0;c--)
- for(b=38;b>0;b--)
- for(a=130;a>0;a--);
- }
复制代码
为啥子while的作用去不掉呢?灯还在闪烁呀?
斌+汕头:
问你,main函数中最后一条指令执行完后,应该跳转到哪里?
王华—四川:
呃,不晓得,求指点。
斌+汕头:
因为51单片机我们开发,main函数并没有使用标准的C语言。
main
{
***********
***********
}
最后是跳转到mian;
详细分析如下:
一、没有while(1)示例代码(示例一):
- #include <reg52.h>
- void delay(int x);
- void main()
- {
- P2 = ~P2;
- delay(2);
- P1=0;
- }
- void delay(int x)
- {
- for(;x>0;x--);
- }
复制代码
二、反汇编
- C:0x0000 020024 LJMP C:0024
- 10: void delay(int x)
- 11: {
- 12: for(;x>0;x--);
- C:0x0003 D3 SETB C
- C:0x0004 EF MOV A,R7
- C:0x0005 9400 SUBB A,#0x00
- C:0x0007 EE MOV A,R6
- C:0x0008 6480 XRL A,#P0(0x80)
- C:0x000A 9480 SUBB A,#P0(0x80)
- C:0x000C 4007 JC C:0015
- C:0x000E EF MOV A,R7
- C:0x000F 1F DEC R7
- C:0x0010 70F1 JNZ delay(C:0003)
- C:0x0012 1E DEC R6
- C:0x0013 80EE SJMP delay(C:0003)
- 13: }
- C:0x0015 22 RET
- 3: void main()
- 4: {
- 5: P2 = ~P2;
- C:0x0016 63A0FF XRL P2(0xA0),#0xFF
- 6: delay(2);
- C:0x0019 7F02 MOV R7,#0x02
- C:0x001B 7E00 MOV R6,#0x00
- C:0x001D 120003 LCALL delay(C:0003)
- 7: P1=0;
- C:0x0020 E4 CLR A
- C:0x0021 F590 MOV P1(0x90),A
- 8: }
- C:0x0023 22 RET
- C:0x0024 787F MOV R0,#0x7F
- C:0x0026 E4 CLR A
- C:0x0027 F6 MOV @R0,A
- C:0x0028 D8FD DJNZ R0,C:0027
- C:0x002A 758107 MOV SP(0x81),#0x07
- 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处,程序将重新运行。
|
|