最好从编译出来的汇编代码来比较
- 20 void delayus(unsigned char i)
- 21 {
- 22 1 while(i--);
- 23 1 }
- 24 void delayu(unsigned char i)
- 25 {
- 26 1 unsigned char a;
- 27 1 for(a=0; a<i; a++)
- 28 1 {
- 29 2 _nop_();
- 30 2 }
- 31 1 }
- 下面来说说汇编的传统计算方法:
-
- 指令周期、机器周期与时钟周期
- 指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。
- 时钟周期:也称为振荡周期,一个时钟周期 =晶振的倒数。
- MCS-51单片机的一个机器周期=6个状态周期=12个时钟周期。
- MCS-单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/12000000)=1us。
- 了解了上面这些我们来看一个例子
-
- 汇编延时子程序的延时计算问题
- 对于程序
- ; FUNCTION _delayus (BEGIN)
- ; SOURCE LINE # 20
- ;---- Variable 'i' assigned to Register 'R7' ----
- ; SOURCE LINE # 21
- ?C0008:
- ; SOURCE LINE # 22
- MOV R6,AR7 ;2指令周期
- DEC R7 ;1指令周期
- MOV A,R6 ;1指令周期
- JNZ ?C0008 ;2指令周期
- ?C0009:
- ; SOURCE LINE # 23
- ?C0010:
- RET ;2指令周期
- ; FUNCTION _delayus (END)
- R7 * (2+1+1+2) + 2
- 整个循环执行完应该是 =(R7 * 6) + 2 指令周期
- ; FUNCTION _delayu (BEGIN)
- ; SOURCE LINE # 24
- ;---- Variable 'i' assigned to Register 'R7' ----
- ; SOURCE LINE # 25
- ; SOURCE LINE # 27
- ;---- Variable 'a' assigned to Register 'R6' ----
- CLR A ;1指令周期
- MOV R6,A ;1指令周期
- ?C0011:
- MOV A,R6 ;1指令周期
- CLR C ;1指令周期
- SUBB A,R7 ;1指令周期
- JNC ?C0014 ;2指令周期
- ; SOURCE LINE # 28
- ; SOURCE LINE # 29
- NOP ;1指令周期
- ; SOURCE LINE # 30
- INC R6 ;1指令周期
- SJMP ?C0011 ;2指令周期
- ; SOURCE LINE # 31
- ?C0014:
- RET ;2指令周期
- ; FUNCTION _delayu (END)
- (1+1+1+2)+ R7 * (1+1+2+1+1+1+2) +1 +1 +2
- 整个循环执行完应该是 = (R7 * 9) + 9 指令周期
- 还说明一下:
- nop指令或者_nop_(); 函数占一个机器周期,
- 在stc单片机的12T模式下一个机器周期是一个振荡周期的12分频,如果你的晶振是12MHZ,那你的一个机器周期就是1微秒.一个nop指令的执行时间也就是1US
- 当在6T模式(下载的时候可选择模式)下12M晶振的时候,一个nop就是0.5US了.
复制代码 |