您的位置:首页 > 编程语言

解读KeilC给C51程序自动添加的代码

2010-11-21 00:03 323 查看
用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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: