IDATALEN EQU 80H ; the length of IDATA memory in bytes.
这里IDATALEN只是一个标号而已,和idata不是一回事!你要是愿意,这段程序里的 IDATALEN你完全可以改成dog呀,pig呀,playboy呀这些标号(其实我的理想是过猪一 样的生活,不愁吃喝,无忧无虑,可惜做不到),上面的这一句是说程序里面凡是用
到IDATALEN的地方其实就是可以看成是80H这个数,你用80H去代替IDATALEN是完全对 的。
之所以取IDATALEN这么个名字,只是为了好记,表明和idata有一点点关系,不至于你 的程序长了,假使你本来是用了playboy作为标号的,写到后来你就会忘了playboy到 底是什么含义了。idata的范围是0~FFH。如果你想改成FFH,完全可以。 2。清零
IF IDATALEN <> 0
MOV R0,#IDATALEN - 1 CLR A
IDATALOOP: MOV @R0,A DJNZ R0,IDATALOOP
关于这一段,很明显是在清零,如果上面idatalen=80H,那么是对0~7FH清零;如果 你的程序是改写成:
IDATALEN EQU 0100H ; 就是对0~FFH清零。
还要注意的是那条IF语句,下面再谈。 二、如何按你意愿加载这段程序
一般考虑到这个往往是你的设计中要区分上电复位和程序复位。有时候当程序复位时 你不希望一些内存单元被清零了,那么你不对startup.a51作点修改,就不行了。 默认是自动加载这段startup.a51的。 所以你要这样做:
把lib目录下的原始startup.a51文件拷到你的项目所在目录下,再把你项目目录下的 这个startup.a51加入到你的项目中(在keil的集成环境中,希望你对这个是知道如何 做的),然后对这个startup.a51加以修改。 比如改成:
IDATALEN EQU 00H ; the length of IDATA memory in bytes. 然后编译链接。这样你的程序中就不会包含对idata清零的内码了。
为什么?上面提到的IF语句的作用呀!当定义IDATALEN=0时,清零代码被跳过!
------------------------------------------------------------------------------------------------------------------------------------------ Startup.a51的中文说明
;------------------------------------------------------------------------------ ; STARTUP.A51: 用户上电初始化程序
;------------------------------------------------------------------------------ ;
; 用户定义需上电初始化的内存空间
;
; 使用以下EQU命令可定义在CPU复位时需用0进行初始化的内存空间 ;
;; ; IDATA 存储器的空间的绝对起始地址总是0.;
IDATALEN EQU 80H ; 需用0进行初始化的IDATA存储器空间的字节数 ;
XDATASTART EQU 0H ; XDATA存储器空间的绝对起始地址
XDATALEN EQU 0H ; 需用0进行初始化的XDATA存储器的空间字节数. ;
PDATASTART EQU 0H ; PDATA存储器的空间的绝对起始地址
PDATALEN EQU 0H ; 需用0进行初始化的PDATA存储器的空间字节数. ;
; 注意: IDATA 存储器的空间在物理上包括了8051单片机的DATA和BIT存储器空间. ; 听 说 至少要保证与C51编译器运行库有关的存储器的空间进行0初始化 不知是否 ;------------------------------------------------------------------------------ ;
; 再入函数模拟初始化 ;
; 以下用EQU指令定义了再入函数模拟堆栈指针的初始化 ;
; 使用SMALL存储器模式时再入函数的堆栈空间 .
IBPSTACK EQU 0 ; 使用SMALL存储器模式再入函数时将其设置成1. IBPSTACKTOP EQU 0FFH+1 ; 将堆栈顶设置为最高地址+1. ;
; 使用LARGE存储器模式时再入函数的堆栈空间.; 使用LARGE存储器模式时再入函数的堆栈空间. XBPSTACK EQU 0 ; 使用LARGE存储器模式再入函数时将其设置成1. XBPSTACKTOP EQU 0FFFFH+1; 将堆栈顶设置为最高地址+1. ;
; 使用COMPACT存储器模式时再入函数的堆栈空间.; 使用COMPACT存储器模式时再入函数的堆栈空间.
PBPSTACK EQU 0 ; 使用COMPACT存储器模式再入函数时将其设置成1. PBPSTACKTOP EQU 0FFFFH+1; 将堆栈顶设置为最高地址+1. ;
;------------------------------------------------------------------------------ ;
; 使用COMPACT存储器模式时64K字节XDATA存储器空间的分页定义 ;
; 以下用EQU指令定义PDATA类型变量在XDATA存储器空间的页地址
; 使用EQU指令定义PFAGE时必须与L51连接定位器PDATA指令的控制参数一致 ;
PPAGEENABLE EQU 0 ; 使用PDATA类型变量时将其设置成1. PPAGE EQU 0 ; 定义页号. ;
;------------------------------------------------------------------------------
NAME ?C_STARTUP; 模块名为 ?C_STAUTUP ?C_C51STARTUP SEGMENT CODE ; 代码 ?STACK SEGMENT IDATA ; 堆栈 RSEG ?STACK ; 堆栈 DS 1
EXTRNEXTRN CODE ((?C_START)) ; 程序开始地址 PUBLIC ?C_STARTUP
CSEG AT 0x8000 ; 定义用户程序的起始地址,用MON51仿真器时可能有用 ?C_STARTUP: LJMP STARTUP1 RSEG ?C_C51STARTUP STARTUP1:: ;
; 初始化串口
MOV SCON,#40H MOV TMOD,#20H MOV TH1,#0fdH SETB TR1 CLR TI
; 单片机上电IDATA内存清零 如果不需要上电清零IDATA 可以注销IF到IFEDN之间的话句 ; 或者修改IDTALEN的长度 为了具有掉电保护功能 不知IDTALEN多长为好 IF IDATALEN <> 0
MOV R0,#IDATALEN - 1 CLR A
IDATALOOP: MOV @R0,A DJNZ R0,IDATALOOP ENDIF ;
; 单片机上电XDATA内存清零 如果不需要上电清零XDATA 可以注销IF到IFEDN之间的话句 ; 或者修改XDATALEN的长度 IF XDATALEN <> 0
MOV DPTR,#XDATASTART MOV R7,#LOW ((XDATALEN) IF (LOW (XDATALEN) <> 0
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 ;
; 送PDATA存储器页面高位地址 IF PAGEENABLE <> 0 MOV P2,#PPAGE ENDIF ;
; 单片机上电PDATA内存清零 如果不需要上电清零XDATA 可以注销IF到IFEDN之间的话句 ; 或者修改PDATALEN的长度 IF PDATALEN <> 0
MOV R0,#PDATASTART MOV R7,#LOW (PDATALEN) CLR A
PDATALOOP: MOVX @R0,A INC R0
DJNZ R7,PDATALOOP ENDIF ;
; 设置使用SMALL存储器模式时再入函数的堆栈空间. IF IBPSTACK <> 0 EXTRN DATA (?C_IBP)
MOV ?C_IBP,#LOW IBPSTACKTOP ENDIF ;
; 设置使用LARGE存储器模式时再入函数的堆栈空间. IF XBPSTACK <> 0 EXTRN DATA (?C_XBP)
MOV ?C_XBP,#HIGH XBPSTACKTOP MOV ?C_XBP+1,#LOW XBPSTACKTOP ENDIF ;
; 设置使用COMPACT存储器模式时再入函数的堆栈空间. IF PBPSTACK <> 0 EXTRN DATA (C_PBP)
MOV ?C_PBP,#LOW PBPSTACKTOP ENDIF ;
; 设置堆栈的起始地址
MOV SP,#?STACK-1 ; 例如 MOV SP,#4FH;
; This code is required if you use L51_BANK.A51 with Banking Mode 4
; 如果你的程序使用了Mode 4 程序分组技术 请启动下面的程序,不会吧你的程序超过64K 利害 ; EXTRN CODE (?B_SWITCH0)
; CALL ?B_SWITCH0 ; init bank mechanism to code bank 0 ;; 程序从第一组bank 0 块开始执行 ; 跳转到用户程序MAIN函数 LJMP ?C_START
END
;lINSHENGFENG
----------------------------------------------------------------------------------------------------------------------
让我们先来看看STARTUP.A51文件(默认设置)吧!根据源文件中的说明文字,我们很容易分析出STARTUP.A51文件的工作方式和作用!让我们把它先汉化一下看看!
$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 ;------------------------------------------------------------------------------ ; ; 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(间接寻址区)其起始地址固定为0;IDATALEN用于指定需要初始化的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模式时为64KB的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. ; 下面的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
因篇幅问题不能全部显示,请点此查看更多更全内容