keil C51 Startup 过程分析
第一步:跳转到STARTUP1
?C_STARTUP作为整个程序执行的入口,对应代码段地址C:0x0000,跳转到STARTUP1代码段。
?C_STARTUP: LJMP STARTUP1
1
第二步:清零数据存储区
keil默认设置情况下只是清零idata数据,而没有去清零xdata数据;如果需要清零xdata数据则需另外设置。
IDATALEN EQU 80H
XDATASTART EQU 0H
XDATALEN EQU 0H
PDATASTART EQU 0H
PDATALEN EQU 0H
PPAGE_SFR DATA 0A0H
IF IDATALEN <> 0
MOV R0,#IDATALEN - 1
CLR A
IDATALOOP: MOV @R0,A
DJNZ R0,IDATALOOP
ENDIF
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
IF PPAGEENABLE <> 0
MOV PPAGE_SFR,#PPAGE
ENDIF
IF PDATALEN <> 0
MOV R0,#LOW (PDATASTART)
MOV R7,#LOW (PDATALEN)
CLR A
PDATALOOP: MOVX @R0,A
INC R0
DJNZ R7,PDATALOOP
ENDIF
第三步:设置堆栈指针?C_XBP、?C_PBP、SP
处理器SP指向idata堆栈空间,如果对堆栈的空间要求比较大,则需要使用xdata作为堆栈空间,?C_XBP指向xdata堆栈空间。
IBPSTACK EQU 0
IBPSTACKTOP EQU 0FFH+1
XBPSTACK EQU 1
XBPSTACKTOP EQU 0DFFFH+1
PBPSTACK EQU 0
PBPSTACKTOP EQU 0FFFFH+1
IF XBPSTACK <> 0
EXTRN DATA (?C_XBP)
MOV ?C_XBP,#HIGH XBPSTACKTOP
MOV ?C_XBP+1,#LOW XBPSTACKTOP
ENDIF
IF PBPSTACK <> 0
EXTRN DATA (?C_PBP)
MOV ?C_PBP,#LOW PBPSTACKTOP
ENDIF
MOV SP,#?STACK-1
第四步:初始化C语言定义的变量
按顺序对c语言定义的全局变量进行初始化。
LJMP ?C_START
keil是如何对C变量进行初始化?
程序跳转到变量初始化代码段,该代码段的首地址为?C_INITSEG,然后按照CtrlByte + DataBytes格式依次完成对各个变量的初始化过程。
变量初始化主要分2个部分:控制字节CtrlByte+数据段DataBytes
控制字节分3个部分:CtrlByte[7-6] + CtrlByte[5] + CtrlByte[4-0]
CtrlByte[7-6]为11b时表示bit变量初始化,CtrlByte[5]固定为0,CtrlByte[4-0]固定为00001b,此时DataBytes只有一个字节。
DataBytes分为3个部分:DataBytes[7] + DataBytes[6-4] + DataBytes[3-0];
51单片机可位寻址区为 0x20-0x2F共16字节,可以按2个字节分为一个字段(如0x20、0x21作为一个字段),共8个字段,每个字段有16位;DataBytes[6-4]作为字段的选择,DataBytes[3-0]作为位的选择。(例如:0xC1 0x81则表示0x20.1为1,0xC1 0x1F,则表示0x23.7为0)
CtrlByte[7-6]为01b时表示xdata变量初始化;CtrlByte[5]为1则表示变量大小大于31字节,需要多1个字节与CtrlByte[4-0]组成13位的变量ExtLen,此时DataBytes总长度为1(扩展长度字节) + 2(地址)+ExtLen(数据); CtrlByte[5]为0则DataBytes总长度为2(地址)+ CtrlByte[4-0](数据)
CtrlByte[7-6]为00b时表示data或者idata变量初始化;DataBytes数据长度为 1(地址) + CtrlByte[4-0](数据)
CtrlByte[7-6]为10b 时表示pdata变量初始化;DataBytes数据长度为 1(地址) + CtrlByte[4-0](数据)