用KeilC编写C51的程序时,在执行main函数之前,还执行了一大段的代码
它们是用来清空内存、初始化全局变量的,下面是V3.3版本生成的代码
; 清空内存
MOV R0,#0x7F
CLR A
Label5:
MOV @R0,A
DJNZ R0,Label5
MOV SP(0x81),#0x55
LJMP InitVar
GotoMain:
LJMP main(C:1358)
; 第二个字节为变量的起始地址,存入R0
InitBytes:
CLR A
MOVC A,@A+DPTR
INC DPTR
MOV R0,A
; R7=变量大小,CY=0表示内部RAM,CY=1表示外部RAM
NextByte:
CLR A
MOVC A,@A+DPTR
INC DPTR
JC Label6
MOV @R0,A
SJMP Label7
Label6:
MOVX @R0,A
Label7:
INC R0
DJNZ R7, NextByte
SJMP NextVar
; 对位变量进行初始化
InitBits:
CLR A
MOVC A,@A+DPTR
INC DPTR
MOV R0,A ; 位地址
; 转换为XX.Y格式
; XX存在R0中,Y存在ACC中
ANL A,#0x07
; 为什么加0x0C?因为0x0C等于Table - AccessTable
ADD A,#0x0C
XCH A,R0
CLR C
RLC A
SWAP A
ANL A,#0x0F
ORL A,#0x20
XCH A,R0
AccessTable:
MOVC A,@A+PC
JC Label3
CPL A
ANL A,@R0
SJMP Label4
Label3:
ORL A,@R0
Label4:
MOV @R0,A
DJNZ R7,InitBits
SJMP NextVar
Table:
DS 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
; 入口地址
InitVar:
MOV DPTR,#12A1
NextVar:
CLR A
MOV R6,#0x01
MOVC A,@A+DPTR
JZ GotoMain
INC DPTR
MOV R7,A
ANL A,#0x3F
JNB ACC.5,C08D8
; 需要初始化的区域大于256字节
; 第一个字节的低5位,加上第二个字节,才是区域大小
ANL A,#0x1F
MOV R6,A
CLR A
MOVC A,@A+DPTR
INC DPTR
JZ Label7
INC R6 ; 方便后面使用DJNZ指令
Label7:
XCH A,R7
ANL A,#0xC0
ADD A,ACC(0xE0)
JZ InitBytes ; Bit6=0跳转
JC InitBits ; Bit7=1跳转
; 初始化需要DPTR寻址的外部RAM
; R6:R7为数据长度
; 为了能使用DJNZ指令,区域大小不是256整数倍时,R6比实际值大一
; 用R2:R0保存变量所在地址
InitLargeBytes:
CLR A
MOVC A,@A+DPTR
INC DPTR
MOV R2,A ; 变量起始地址高8位
CLR A
MOVC A,@A+DPTR
INC DPTR
MOV R0,A ; 变量起始地址低8位
NextLargeByte:
CLR A
MOVC A,@A+DPTR ; 从源地址取一字节
INC DPTR ; 源地址加一
; DPTR和R2:R0进行了交换,ACC内容不变
XCH A,R0
XCH A,DPL(0x82)
XCH A,R0
XCH A,R2
XCH A,DPH(0x83)
XCH A,R2
MOVX @DPTR,A ; 向目标地址写一字节
INC DPTR ; 目标地址加一
; DPTR和R2:R0进行了交换
XCH A,R0
XCH A,DPL(0x82)
XCH A,R0
XCH A,R2
XCH A,DPH(0x83)
XCH A,R2
DJNZ R7,NextLargeByte
DJNZ R6,NextLargeByte
SJMP NextVar
本文详细解析了使用KeilC编写C51程序时,在main函数执行前的一系列初始化代码。这些代码负责清空内存、初始化全局变量等任务,确保程序能够正确运行。
2524

被折叠的 条评论
为什么被折叠?



