STARTUP.A51 文件分析

$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://home.eeworld.com.cn/my/space-uid-173779-blogid-66425.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章