Chinaunix首页 | 论坛 | 博客
  • 博客访问: 947369
  • 博文数量: 175
  • 博客积分: 2788
  • 博客等级: 少校
  • 技术积分: 2060
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-25 12:25
个人简介

知之者不如好之,好之者不如乐之

文章分类

全部博文(175)

文章存档

2016年(1)

2015年(20)

2014年(8)

2013年(68)

2012年(16)

2011年(35)

2010年(1)

2008年(26)

分类: 嵌入式

2015-09-20 16:38:34

原文:http://blog.chinaunix.net/uid-22597935-id-1772452.html

$NOMOD51       ;Ax51宏汇编器控制命令:禁止预定义的8051
;------------------------------------------------------------------------------
; This file is part of the C51 Compiler package
; Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
;------------------------------------------------------------------------------
; STARTUP.A51: This code is executed after processor reset.
; STARTUP.A51: STARTUP.A51文件所生成的代码将在单片机复位后被执行!

; To translate this file use A51 with the following invocation:
;  将按照下面的命令行语句调用A51编译器进行编译产生目标文件
;     A51 STARTUP.A51
;
; To link the modified STARTUP.OBJ file to your application use the following
; BL51 invocation:
;  将按照下面的命令行语句调用BL51连接器把STARTUP.OBJ定位连接到您的程序代码中
;     BL51 , STARTUP.OBJ 
;
;------------------------------------------------------------------------------
;
; User-defined Power-On Initialization of Memory
自定义上电后需要初始化的储存区域

; With the following EQU statements the initialization of memory
; at processor reset can be defined:
使用下列EQU伪指令定义初始化的存储区域 在单片机复位后定义生效
;                   ; the absolute start-address of IDATA memory is always 0
IDATALEN            EQU     80H     ; the length of IDATA memory in bytes.
; IDATA(间接寻址区)其起始地址固定为0IDATALEN用于指定需要初始化的IDATA区长度(以字节为单位)*

XDATASTART      EQU     0H      ; the absolute start-address of XDATA memory
XDATALEN           EQU      0H      ; the length of XDATA memory in bytes.
;XDATA (外部直接寻址区) XDATASTART用于指定需要初始化的XDATA区起始地址

;XDATALEN 
用于指定需要初始化的XDATA区长度(以字节为单位)*

PDATASTART      EQU     0H      ; the absolute start-address of PDATA memory
PDATALEN           EQU     0H      ; the length of PDATA memory in bytes.
;PDATA(页寻址区) PDATASTART用于指定需要初始化的PDATA区起始地址

;PDATALEN
用于指定需要初始化的;PDATA区长度(以字节为单位)*

; Notes: The IDATA space overlaps physically the DATA and BIT areas of the
;            8051 CPU. At minimum the memory space occupied from the C51 
;           run-time routines must be set to zero.

;注释:8051 IDATA 区物理上已经包括了DATA区(直接寻址区)以及 BIT (位寻址区)。C51(库)占用了 最小化内存空间,运行时程序需要把它设为0

;------------------------------------------------------------------------------
;
; Reentrant Stack Initilization
重入堆栈初始化


; The following EQU statements define the stack pointer for reentrant
; functions and initialized it:
下面的EQU语句定义重入函数的堆栈指针并初始化它

; Stack Space for reentrant functions in the SMALL model.
; SMALL模式下的重入函数的堆栈空间

IBPSTACK        EQU     0       ; set to 1 if small reentrant is used.
;如果再SMALL模式下使用重入则设为1
IBPSTACKTOP     EQU     0FFH+1 ; set top of stack to highest location+1.
;设置堆栈顶 最高位置+1
;
; Stack Space for reentrant functions in the LARGE model.
; LARGE模式下的重入函数的堆栈空间
XBPSTACK        EQU     0       ; set to 1 if large reentrant is used.
;如果再LARGE模式下使用重入则设为1
XBPSTACKTOP     EQU     0FFFFH+1; set top of stack to highest location+1.
;设置堆栈顶 最高位置+1
;
; Stack Space for reentrant functions in the COMPACT model.    
; COMPACT模式下的重入函数的堆栈空间
PBPSTACK        EQU     0       ; set to 1 if compact reentrant is used.
;如果再COMPACT模式下使用重入则设为1
PBPSTACKTOP     EQU     0FFFFH+1; set top of stack to highest location+1.
;设置堆栈顶 最高位置+1
;
;------------------------------------------------------------------------------
;
; Page Definition for Using the Compact Model with 64 KByte xdata RAM
使用COMPACT模式时为64KBXDATA RAM定义页

; The following EQU statements define the xdata page used for pdata
; variables. The EQU PPAGE must conform with the PPAGE control used
; in the linker invocation.
下面的EQU语句定义PDATA变量的使用了XDATA

PPAGEENABLE     EQU     0       ; set to 1 if pdata object are used.
;如果使用PDATA页则设为1
;
PPAGE           EQU     0       ; define PPAGE number.
;定义页号
;
PPAGE_SFR       DATA    0A0H    ; SFR that supplies uppermost address byte
;SFR的最高地址字节
; (most 8051 variants use P2 as uppermost address byte)
; (大多数8051变量要用P2的最高地址字节)

;------------------------------------------------------------------------------

; Standard SFR Symbols 
标准SFR符号

ACC     DATA    0E0H
B          DATA    0F0H
SP      DATA    81H
DPL     DATA    82H
DPH     DATA    83H

                                NAME    ?C_STARTUP


?C_C51STARTUP   SEGMENT   CODE
?STACK                  SEGMENT   IDATA

                               RSEG    ?STACK
                                 DS      1

                               EXTRN CODE (?C_START)
;外部代码(这个标号将代表用户程序的启始地址)

                                PUBLIC ?C_STARTUP
;给外部使用的符号

                                CSEG    AT      0
;code段的0地址处放以下代码(使用AT指令进行绝对地址的定位)

?C_STARTUP:     LJMP    STARTUP1

                              RSEG    ?C_C51STARTUP

STARTUP1:

IF IDATALEN <> 0   
;如果长度大于1则初始化IDATA

                MOV     R0,#IDATALEN - 1
                CLR     A
IDATALOOP:      MOV     @R0,A
                DJNZ    R0,IDATALOOP
ENDIF

IF XDATALEN <> 0  
;如果长度大于1则初始化XDATA

                MOV     DPTR,#XDATASTART
                MOV     R7,#LOW (XDATALEN)


IF (LOW (XDATALEN)) <> 0
;预置初始化时的外循环次数到R6

                MOV     R6,#(HIGH (XDATALEN)) +1
ELSE
                MOV     R6,#HIGH (XDATALEN)
ENDIF
                CLR     A
XDATALOOP:      MOVX    @DPTR,A
                INC     DPTR
                DJNZ    R7,XDATALOOP
                DJNZ    R6,XDATALOOP
ENDIF

IF PPAGEENABLE <> 0
                MOV     PPAGE_SFR,#PPAGE
ENDIF

IF PDATALEN <> 0  
;如果长度大于1则初始化PDATA

                MOV     R0,#LOW (PDATASTART)
                MOV     R7,#LOW (PDATALEN)
                CLR     A
PDATALOOP:      MOVX    @R0,A
                INC     R0
                DJNZ    R7,PDATALOOP
ENDIF

IF IBPSTACK <> 0   
;SMALL模式下使用重入函数时要设置的堆栈

EXTRN DATA (?C_IBP)

                MOV     ?C_IBP,#LOW IBPSTACKTOP
ENDIF

IF XBPSTACK <> 0   
;COMPACT模式下使用重入函数时要设置的堆栈

EXTRN DATA (?C_XBP)

                MOV     ?C_XBP,#HIGH XBPSTACKTOP
                MOV     ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF

IF PBPSTACK <> 0  
;LARGE模式下使用重入函数时要设置的堆栈

EXTRN DATA (?C_PBP)
                MOV     ?C_PBP,#LOW PBPSTACKTOP
ENDIF

                MOV     SP,#?STACK-1
; This code is required if you use L51_BANK.A51 with Banking Mode 4
如果你的程序使用了Mode 4 程序分组技术(BANKING)请启用下面的程序代码

; EXTRN CODE (?B_SWITCH0)
;               CALL    ?B_SWITCH0      ; init bank mechanism to code bank 0
;程序从第一个块(bank0)开始执行
                LJMP    ?C_START ;
从这里跳到你的程序入口

                END

;*******************************************************************

原来的工程中没有加入startup.A51文件,程序有时会出现乱码和指针溢出的情况导致系统异常。 加入此文件后,针对C8051F340单片机4K Xdata,我采样如下设置:

;
; Stack Space for reentrant functions in the LARGE model.
; LARGE模式下的重入函数的堆栈空间
XBPSTACK        EQU     1       ; set to 1 if large reentrant is used.
;如果再LARGE模式下使用重入则设为1
XBPSTACKTOP     EQU    0FFFH+1; set top of stack to highest location+1.
;设置堆栈顶 最高位置+1

系统已可以稳定运行!


原文:http://blog.sina.com.cn/s/blog_59ab74940100bh9g.html
启动文件STARTUP.A51中包含目标板启动代码,可在每个project中加入这个文件,只要复位,则该文件立即执行,其功能包括:
l 定义内部RAM大小、外部RAM大小、可重入堆栈位置
l 清除内部、外部或者以此页为单元的外部存储器
l 按存储模式初使化重入堆栈及堆栈指针
l 初始化8051硬件堆栈指针
l 向main( )函数交权
开发人员可修改以下数据从而对系统初始化
常数名 意义
IDATALEN 待清内部RAM长度
XDATA START 指定待清外部RAM起始地址
XDATALEN 待清外部RAM长度
IBPSTACK 是否小模式重入堆栈指针需初始化标志,1为需要。缺省为0
IBPSTACKTOP 指定小模式重入堆栈顶部地址
XBPSTACK 是否大模式重入堆栈指针需初始化标志,缺省为0
XBPSTACKTOP 指定大模式重入堆栈顶部地址
PBPSTACK 是否Compact重入堆栈指针,需初始化标志,缺省为0
PBPSTACKTOP 指定Compact模式重入堆栈顶部地址
PPAGEENABLE P2初始化允许开关
PPAGE 指定P2值
PDATASTART 待清外部RAM页首址
PDATALEN 待清外部RAM页长度
提示:如果要初始化P2作为紧凑模式高端地址,必须:PPAGEENAGLE=1,PPAGE为P2值,例如指定某页1000H-10FFH,则PPAGE=10H,而且连接时必须如下:
L51
 PDATA(1080H),其中1080H是1000H-10FFH中的任一个值。

原文:http://blog.csdn.net/assemble8086/article/details/44033789
转自:http://home.eeworld.com.cn/my/space-uid-173779-blogid-66425.html

$NOMOD51  ; Ax51宏汇编器控制命令禁止预定义的8051使编译器不使能预定义的;8051符号,避免产生重复定义的错误。
;------------------------------------------------------------------------------
;  This file is part of the C51 Compiler package
;  Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
;------------------------------------------------------------------------------
;  STARTUP.A51:  This code is executed after processor reset.
;
;  To translate this file use A51 with the following invocation:
;
;     A51 STARTUP.A51
;
;  To link the modified STARTUP.OBJ file to your application use the following
;  BL51 invocation:
;
;     BL51 <your object file list>, STARTUP.OBJ <controls>
;     
BL51Keil使用的链接器(Linker),这是命令行的使用格式,一般不用,使用IDE环境,

;project管理,有相应的按钮可以实现该功能.
;------------------------------------------------------------------------------
;
;  User-defined Power-On Initialization of Memory
 ---  初始化RAM单元
;
;  With the following EQU statements the initialization of memory
---用下面的EQU声明初

;始化ram单元
;  at processor reset can be defined:
;
;               ; the absolute start-address of
 IDATA memory is always 0
IDATALEN
  EQU  80H ; the length of IDATA memory in bytes.--根据你选用的芯片可以适

; 的修改这些值 IDATALEN  只是一个标号,EQU只是做宏一样的替换,类似于C;言中的#define uint (unsigned int) ,以上的代码使得程序以后在碰到IDATALEN时替换;80H

XDATASTART      EQU     0H      ; the absolute start-address of 
XDATA memory--以下

;两项根据目标系统的外设配置和连接自己修改  
XDATALEN        EQU     0H      ; the length of XDATA memory in bytes.


PDATASTART      EQU     0H      ; the absolute start-address of 
PDATA memory
PDATALEN        EQU     0H      ; the length of 
PDATA memory in bytes.
;
;  Notes:  The IDATA space overlaps physically the DATA and BIT areas of the
;          8051 CPU. At minimum the memory space occupied from the C51 
;          run-time routines must be set to zero.
;------------------------------------------------------------------------------
;
;  Reentrant Stack Initilization  
 --注意再入堆栈的方向区别芯片自带的堆栈的生长方

;式,自顶向下生长的!而SP是是自底向上的!        
;   --
且再入堆栈是由编译器自己管理的,一般不必去关心,只是在有再入函数的时候,根据

;函数的存储器模式使用相应的RAM空间做为再入堆栈。 
;  The following EQU statements define the stack pointer for reentrant
;  functions and initialized it:
;Keil C默认情况不是用堆栈来传递参数的,所以造成函数不可重入,Keil要求用户显示声

;明函数是否具有可重入属性,以便为C函数调用初始化栈。
;  Stack Space for reentrant functions in the 
SMALL model.
IBPSTACK        EQU     0       ; set to 1 if small reentrant is used.
IBPSTACKTOP     EQU     0FFH+1  ; set top of stack to highest location+1.
;
;  Stack Space for reentrant functions in the 
LARGE model.      
XBPSTACK        EQU     0       ; set to 1 if large reentrant is used.
XBPSTACKTOP     EQU     0FFFFH+1; set top of stack to highest location+1.
;
;  Stack Space for reentrant functions in the 
COMPACT model.    
PBPSTACK        EQU     0       ; set to 1 if compact reentrant is used.
PBPSTACKTOP     EQU     0FFFFH+1; set top of stack to highest location+1.
;不同内存模式下的堆栈。Keil 编译器中有三种模式设置:
;Small
:所有的变量都放在内部RAM
;Compact
:所有变量在默认情况下都会放在外部RAM的低256字节中(可由R0寻址)
;Large
:所有变量都放在外部RAM(DPTR寻址)
;
这是由51处理器繁多的寻址模式导致的,不同的寻址模式有不同的效率
;

;------------------------------------------------------------------------------
;
;  Page Definition for Using the 
Compact Model with 64 KByte xdata RAM
;
;  The following EQU statements define the xdata page used for pdata
;  variables. The EQU PPAGE must conform with the PPAGE control used
;  in the linker invocation.
;
PPAGEENABLE     EQU     0       ; set to 1 if pdata object are used.
;
PPAGE           EQU     0       ; define PPAGE number.
;
PPAGE_SFR       DATA    0A0H    ; SFR that supplies uppermost address byte
;
     (most 8051 variants use P2 as uppermost address byte) 很多的外部页面寻址以P2

;口为高位地址的数值,有使用外部页面RAM的情况
;     
PPAGEENABLE 设置为,根据硬件连接修改PPAGE的值
;------------------------------------------------------------------------------

; Standard SFR Symbols ---标准的SFR符号
ACC   DATA   0E0H;
关键字DATA A51伪指令定义单片机内部数据存储器字节地址的符号
B       DATA    0F0H
SP      DATA    81H
DPL     DATA    82H
DPH     DATA    83H

                                  NAME          ?C_STARTUP   ;定义当前程序模块的目标模块名


?C_C51STARTUP   
  SEGMENT   CODE       ;定义一个可再定位的段符号名和段所在的

;存储空间,汇编器产生的这个段符号名在BL51/L51连接定位时用
?STACK          
           SEGMENT   IDATA      ;定义一个IDATA段,段名?STACK ,符合

;C51编译器的命名规则   SEGMENT   用于定义一个段)

                                  RSEG           ?STACK    ;声明当前段是IDATA段,段中保留空间

;RSEG伪指令用于选择一个事先用SEGMENT伪指令声明的普通段
                
                  DS                1  ; DS是预留空间定义指令

                                  EXTRN  CODE (?C_START)  ;声明本模块引用的外部全局符号,

;用于和C相连接在.src文件中可以看到这个符号 
                                  PUBLIC        ?C_STARTUP     ;声明可被其他模块使用的全局符

;号,由.src文件中可以看出这个符号的作用。

                                  CSEG           AT         0      ;结束当前的IDATA段,产生一个位于

;CODE中新段,起始地址是0000H。代码段的起始点 
?C_STARTUP:     
      LJMP           STARTUP1       ;C编译器编译源程序后,芯片复位之

;后的复位代码第一个就是执行这条语句

                                  RSEG           ?C_C51STARTUP  ;选择段名为?C_C51STARTUP

;CODE段为当前段,存储程序代码。

STARTUP1:

IF IDATALEN <> 0                      ;条件汇编指令,有IDATA区的话,清IDATA区。
                
                  MOV                   R0,#IDATALEN – 1  ;区域为0——IDATALEN-1
                
                  CLR             A

IDATALOOP:      
MOV                   @R0,A
                
                  DJNZ                  R0,IDATALOOP
ENDIF
   
;(一)如果上;idatalen80H,那么是对07FH清零;如果你的程序是改写成:
;IDATALEN    EQU    0100H    ;
;就是对0FFH清零。

;             (二)二、如何按你意愿加载这段程序
;一般考虑到这个往往是你的设计中要区分上电复位和程序复位。有时候当程序复位时
;你不希望一些内存单元被清零了,那么你不对startup.a51作点修改,就不行了。

;默认是自动加载这段startup.a51的。

;所以你要这样做:
;lib目录下的原始startup.a51文件拷到你的项目所在目录下,再把你项目目录下的
;这个startup.a51加入到你的项目中

;比如改成:
;IDATALEN    EQU    00H    ; the length of IDATA memory in bytes.
;然后编译链接。这样你的程序中就不会包含对idata清零的内码了。

;为什么?上面提到的IF语句的作用呀!当定义IDATALEN0时,清零代码被跳过!

 

 

IF XDATALEN <> 0          ;如果有外部数据区,则把外部数据区中从XDATASTART

;XDATASTART+ XDATALEN的区域清零
                                  MOV                   DPTR,#XDATASTART
                
                  MOV                   R7,#LOW (XDATALEN)
    IF (LOW (XDATALEN)) <> 0
                
                  MOV                   R6,#(HIGH (XDATALEN)) +1
 ;如果低地址是零,一个

;高地址就代表256字节
ELSE
                
           MOV           R6,#HIGH (XDATALEN)
ENDIF
                
           CLR             A

XDATALOOP:            MOVX          @DPTR,A
                
           INC              DPTR
                
           DJNZ                  R7,XDATALOOP
                
           DJNZ                  R6,XDATALOOP

ENDIF

IF PPAGEENABLE <> 0                   ;清外部页RAM区域
                
                  MOV                   PPAGE_SFR,#PPAGE ;P2口赋相应的值,根据用

;户自己的目标系统。
ENDIF

IF PDATALEN <> 0                     ;清外部页RAM区域
                
                  MOV                   R0,#LOW (PDATASTART)
                
                  MOV                   R7,#LOW (PDATALEN)
                
                  CLR             A
PDATALOOP:      
      MOVX          @R0,A
                
                  INC              R0
                
                  DJNZ                  R7,PDATALOOP
ENDIF

IF IBPSTACK <> 0        ;使用再入堆栈的情况,用户自己在程序中定义函数的存储模式。
 ; C51
定义了三个全局变量,?C_IBP,?C_XBP,?C_PBP来存储再入堆栈的栈顶地址
EXTRN DATA (?C_IBP)     声明本模块使用的外部全局符号,符号的段类型限制了符号

;的使用范围,而符号本身则代表的是一个RAM单元的地址址

                                  MOV                   ?C_IBP,#LOW IBPSTACKTOP
ENDIF                                  

IF XBPSTACK <> 0                      ;函数是Large存储模式的时候,存储再入堆栈的区域。
EXTRN DATA (?C_XBP)                   ;

                                  MOV                   ?C_XBP,#HIGH XBPSTACKTOP
                
                  MOV                   ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF

IF PBPSTACK <> 0       ;函数是Compact模式的时候,存储再入堆栈栈顶地址的存储单元

;和栈的利用空间
EXTRN DATA (?C_PBP)         
                
                  MOV                   ?C_PBP,#LOW PBPSTACKTOP
ENDIF

                                  MOV                   SP,#?STACK-1  ;定义的硬件栈的常数。区别再入堆

;栈和硬件栈。定义的段符号代表该段的首地址 
; This code is required if you use L51_BANK.A51 with Banking Mode 4

#if  0
EXTRN CODE (?B_SWITCH0)
              
                    CALL    ?B_SWITCH0  ; init bank mechanism to code bank 0

#endif
                
                  LJMP           ?C_START       ;把执行的权力交给C主函数。也就是;说指定函数的入口点。改句话结束以后将跳入Cmain函数开始执行。

                                  END


原文:http://blog.csdn.net/misskissc/article/details/9029063

keil 版本:uVision 4

 

      单片机是没有上操作系统的东西,在keil中编写的代码都是裸机代码,深入编写裸机代码有助于了解硬件的特性。

      若不是硬件特性已定的情况之下的其它流程都是代码作祟。忽然想到来探探51单片机的执行流程。这个念头起源于最初见到每个51程序里面的主函数里面最终都挂一个while(1);语句。为何要加一句while死循环让程序停留在main函数中呢。将while(1);语句去掉有什么影响么?

 

写一个很简单的程序试一下。

  1. #include <reg52.h>  
  2.   
  3.   
  4. void delay_ms( int ms );  
  5.   
  6. int main()  
  7. {  
  8.       
  9.     P1  = ~P1;  
  10.     delay_ms( 500 );   
  11.       
  12.     while(1);  
  13.     return 0;             
  14. }  
  15.   
  16.   
  17. //-----------------------  
  18. //约延迟ms毫秒  
  19. //-----------------------  
  20. void delay_ms( int ms )  
  21. {  
  22.     int i, j;  
  23.     for( i = ms; i > 0; i-- ){  
  24.         for( j = 110; j > 0; j-- ){  
  25.             ;  
  26.         }  
  27.     }  
  28. }  


 

执行以上程序,由P1端口控制的流水灯闪了一下。程序最终进入while(1);里纠缠去了,这个到好解释。

现将while(1);语句屏蔽掉。我还以为程序不能被正确执行了呢,因为退出了main主函数,就像Render需要循环来实现一样(尽管刚刚闪灯的程序不在循环之内,但我还是不由产生了这一错觉)。程序执行的结果是:流水灯不停的闪烁!

 

看到这个现象后的猜想及动作^-^

(1)    这块板坏了吧!(在带操作系统如linux字符界面下运行一个不带死循环的C语言文件完毕后就会返回到linux shell程序中)。赶紧换个板再测试一下,显然还是一样的结果。

(2)    单片机中将一直执行main函数中的最后一个(些)语句?(基于带OS平台下运行标准C语言文件的经验,可从来没有想过是main函数被多次调用或多次进入)

(3)    单片机内将C语言指令取出来加载到单片机内,单片机内自动生成一个主程序循环执行C语言中main函数的内容?(虽然很荒唐,还是想了)

(4)    赶快谷歌百度一下单片机的执行流程(虽然在谷歌百度时以“51单片机程序执行流程”搜索,没有搜到相关内容)。换朴实的搜索词:“51单片机main”。然后就出现跟我一样带有疑问的问题:为什么main函数中不加while(1);语句之后程序会反复执行呢?回答的关键词包括“程序跑飞、看门狗、复位”。

(5)    趁上嵌入式的机会将“51单片机程序执行流程”搬出来并向老师讲述了我所写程序的得到的现象,包括我怎么验证呀等等。

 

老师的回答:Keil C51程序自动加载了一个名为”STARTUP.A51”的文件,在这个文件里面进行了一系列的初始化操作后进入用户编写的C语言程序入口main函数中,main函数执行完毕后,STARTUP.A51文件后有一句跳转到程序入口main函数的语句,所以会再次进入C语言主程序main函数中执行相关内容。

 

 

然后我用keil软件模拟了运行一下以上那一段代码:

 


程序开始运行就在程序入口main函数的第一条语句之处,Disassembly窗口是c语言代码与汇编代码相对应的窗口,前面是地址,后面的是C语言对应的汇编语句。下面的窗口是相应文件的运行代码的位置,由黄色箭头指向当前正要执行的代码。然后点击单步运行工具条,指导跳出main函数为止,程序跳转到STARTUP.A51中的以下代码位置:

 


继续点击单步调试直到进入一个循环中:

 


这里是一个循环,根据DJNZ指令的功能:每执行一次DJNZ RO, IDATALOOP就将R0的值减1,若R0的值不为0则就跳到IDATALOOP地址去。很显然这是一个循环,那么RO的值是多少呢,在以下窗口显示:

 


可见r0的初值为0x7f,这里将要循环0x7f(128)次,具体在这里r0值的含义可查看一下子的。那么在这个循环之后程序又将去哪里呢?跳过这个循环后程序运行的地方如下:

 


再单步运行一次:

 


根据Disassembly的内容,此条语句执行了就又要回到main函数中去了,执行一下试试:

 


是的!

 

所以,在51单片机中,程序的执行流程就是会不断( 以r0的值作为延迟条件, 具体含义可继续探索 )的进入main函数中执行main函数中的代码。

 

为什么我们在linux等上面运行不带死循环的C语言代码后程序就会自行终止呢?这是不同的操作流程:

(1)    C51单片机不带OS(操作系统),代码的执行形势在此看来就由STARTUP.A51来安排了,没有一个更大的程序来管理怎么调用main函数

(2)    像Linux这类的平台是带了OS的,运行一个C语言程序对linux来说就是一个任务,除了运行C语言程序这个任务外还有其它的任务。当运行一个C语言程序完毕时,此次的任务也算是完成了。如在linux shell界面运行一个文件名为“hello.c”功能为输出“hello world!”的C语言程序,过程如下:

编译:gcc hello.c  –o  hello

运行:./hello

在运行hello可执行文件时,可以当做是shell调用了hello这个可执行程序。在hello运行完毕后,将返回值等返回给shell界面。整个C语言文件的生死全有linux  shell程序管理

 

归其原因,还是代码规定的机制不一样吧。

 

此次笔记记录完毕。




其他相关文档
http://home.eeworld.com.cn/my/space-uid-173779-blogid-66425.html
http://blog.sina.com.cn/s/blog_a2b34859010129b5.html



阅读(3911) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~