打印

学习与思考之一

[复制链接]
2827|12
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
天雨粟|  楼主 | 2010-9-14 18:49 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
ST, AC, ck, Stack, TI
本帖最后由 天雨粟 于 2010-9-14 18:57 编辑

学习与思考之一 —— 启动配置文件问题
启动配置文件,STARTUP.A51,如果程序空间足够大的话,我顺手就用了。如果空间宝贵,且勿需对内存空间清零、不开放模拟栈、不使用片外页寻址功能,我也就不将其COPY到工程文件里,一直以来,就是这么办。但这个程序到底是怎样运行的呢?惭愧得很,先前我只是粗略地看了下,不知其所以然的,现在想,既然把单片机作为专业,则将这个程序搞清楚,不懂就问,还是很有意义的。
我将其全文拷贝下来附后,思考及问题都放在注释行上,望本坛的大侠给予指点。

$NOMOD51
;------------------------------------------------------------------------------
;  This file is part of the C51 Compiler package
;  Copyright (c) 1988-2005 Keil Elektronik GmbH and Keil Software, Inc.
;  Version 8.01
;
;  *** <<< Use Configuration Wizard in Context Menu >>> ***
;------------------------------------------------------------------------------
;  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
;  Lx51 invocation:
;
;     Lx51 your object file list, STARTUP.OBJ  controls
;
;------------------------------------------------------------------------------
;
;  User-defined <h> Power-On Initialization of Memory
;
;  With the following EQU statements the initialization of memory
;  at processor reset can be defined:
;
; <o> IDATALEN: IDATA memory size <0x0-0x100>
;     <i> Note: The absolute start-address of IDATA memory is always 0
;     <i>       The IDATA space overlaps physically the DATA and BIT areas.
;以上的这些鸟语我也不明究竟,总之
;$,在汇编语言源文件处引用汇编控制命令时的前导符
;NOMOD51,使汇编器对8051的所有BIT及DATA符号都是未知的,从而可以自行定义

IDATALEN        EQU     80H
;
; <o> XDATASTART: XDATA memory start address <0x0-0xFFFF>
;     <i> The absolute start address of XDATA memory
;51的话,IDATA空间是128字节

XDATASTART      EQU     0     
;
; <o> XDATALEN: XDATA memory size <0x0-0xFFFF>
;     <i> The length of XDATA memory in bytes.
XDATALEN        EQU     0      
;
; <o> PDATASTART: PDATA memory start address <0x0-0xFFFF>
;     <i> The absolute start address of PDATA memory
;定义需要清零的片外数据空间

PDATASTART      EQU     0H
;
; <o> PDATALEN: PDATA memory size <0x0-0xFF>
;     <i> The length of PDATA memory in bytes.
PDATALEN        EQU     0H
;
;</h>
;定义需要清零的片外分页寻址空间

;------------------------------------------------------------------------------
;
;<h> Reentrant Stack Initialization
;
;  The following EQU statements define the stack pointer for reentrant
;  functions and initialized it:
;
; <h> Stack Space for reentrant functions in the SMALL model.
;  <q> IBPSTACK: Enable SMALL model reentrant stack
;     <i> Stack space for reentrant functions in the SMALL model.
IBPSTACK        EQU     0       ; set to 1 if small reentrant is used.
;  <o> IBPSTACKTOP: End address of SMALL model stack <0x0-0xFF>
;     <i> Set the top of the stack to the highest location.
IBPSTACKTOP     EQU     0xFF +1     ; default 0FFH+1  
; </h>
;
; <h> Stack Space for reentrant functions in the LARGE model.      
;  <q> XBPSTACK: Enable LARGE model reentrant stack
;     <i> Stack space for reentrant functions in the LARGE model.
;小编译模式下,如果需要使用模拟栈,则应将IBPSTACK置1

XBPSTACK        EQU     0       ; set to 1 if large reentrant is used.
;  <o> XBPSTACKTOP: End address of LARGE model stack <0x0-0xFFFF>
;     <i> Set the top of the stack to the highest location.
XBPSTACKTOP     EQU     0xFFFF +1   ; default 0FFFFH+1
; </h>
;
; <h> Stack Space for reentrant functions in the COMPACT model.   
;  <q> PBPSTACK: Enable COMPACT model reentrant stack
;     <i> Stack space for reentrant functions in the COMPACT model.
;大编译模式下,如果需要使用模拟栈,则应将IBPSTACK置1
PBPSTACK        EQU     0       ; set to 1 if compact reentrant is used.
;
;   <o> PBPSTACKTOP: End address of COMPACT model stack <0x0-0xFFFF>
;     <i> Set the top of the stack to the highest location.
PBPSTACKTOP     EQU     0xFF +1     ; default 0FFH+1  
; </h>
;</h>
;紧凑编译模式时,相应处理
;------------------------------------------------------------------------------

相关帖子

沙发
天雨粟|  楼主 | 2010-9-14 18:58 | 只看该作者
;  Memory Page for Using the Compact Model with 64 KByte xdata RAM
;  <e>Compact Model Page Definition
;
;  <i>Define the XDATA page used for PDATA variables.
;  <i>PPAGE must conform with the PPAGE set in the linker invocation.
;
; Enable pdata memory page initalization
PPAGEENABLE     EQU     0       ; set to 1 if pdata object are used.
; 如果使用分页寻址,当置1
; <o> PPAGE number <0x0-0xFF>
; <i> uppermost 256-byte address of the page used for PDATA variables.
PPAGE           EQU     0
;
; <o> SFR address which supplies uppermost address byte <0x0-0xFF>
; <i> most 8051 variants use P2 as uppermost address byte
;页号,即将由P2口输出的高位地址

PPAGE_SFR       DATA    0A0H
;
; </e>
;细看,0A0H,正是P2口的字节地址

;------------------------------------------------------------------------------

; Standard SFR Symbols
; 鸟语的意思似乎是,标准特寄器符号.下文要用,所以先自行定义一下
ACC     DATA    0E0H
B       DATA    0F0H
SP      DATA    81H
DPL     DATA    82H
DPH     DATA    83H

                NAME    ?C_STARTUP                ;程序模块名


?C_C51STARTUP   SEGMENT   CODE                ;声明一个再定位CODE段
?STACK          SEGMENT   IDATA                ;声明一个再定位IDATA段

                RSEG    ?STACK                ;将?STACK段作为当前段
                DS      1                       
;留一字节空间备用,后文没有对其寻址,这样做有何妙用呢?问题一

                EXTRN CODE (?C_START)
;声明一个外部CODE符号,此符号当在C模块的main()中定义,本汇编程序结束后,就是跳
;至?C_START处的.是不是这样呢?求证,问题二.

                PUBLIC  ?C_STARTUP
;将程序标号 ?C_STARTUP声明为全局型,其它模块可以对其寻址

                CSEG    AT      0
;声明一个绝对CODE段,从地址0开始,这显然是复位后的程序入口

?C_STARTUP:     LJMP    STARTUP1
; 显然,?C_STARTUP就是常数0,为何要进行前面一些操作,我直接定义一个绝对段,然后把可
;执行指令写在其下,这不是简单易懂吗?上面的安排是何道理呢?问题三

                RSEG    ?C_C51STARTUP

STARTUP1:

IF IDATALEN <> 0
                MOV     R0,#IDATALEN - 1
                CLR     A
IDATALOOP:      MOV     @R0,A
                DJNZ    R0,IDATALOOP
ENDIF
;51的话,R0开始时指向7F,这样循环127次,RAM的地址0未清零,但该地址即R0
;显然是顺手清零了的,一手二牍,精妙绝伦!

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      ;向P2口输出页地址
ENDIF

IF PDATALEN <> 0
                MOV     R0,#LOW (PDATASTART)
                MOV     R7,#LOW (PDATALEN)
                CLR     A
PDATALOOP:      MOVX    @R0,A
                INC     R0
                DJNZ    R7,PDATALOOP
ENDIF

IF IBPSTACK <> 0        ;如果开通模拟栈功能,
EXTRN DATA (?C_IBP);声明一个外部DATA符号,当在C模块中定义,求证,问题4

                MOV     ?C_IBP,#LOW IBPSTACKTOP;;初始化栈指针
ENDIF

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
;按照Keil的定位规则,堆栈段总是在最后定位,由于段名即首地址,固将其减一正好作为栈指
;针,自解问题一,留一个字节空间正是语法所需,并无积极意义,是否如此?如果工程里不加这
;个启动配置文件,堆栈指针是何处赋值呢?问题五

; This code is required if you use L51_BANK.A51 with Banking Mode 4
;<h> Code Banking
; <q> Select Bank 0 for L51_BANK.A51 Mode 4
#if 0   
; <i> Initialize bank mechanism to code bank 0 when using L51_BANK.A51 with Banking
; Mode 4.
EXTRN CODE (?B_SWITCH0)
                CALL    ?B_SWITCH0      ; init bank mechanism to code bank 0
#endif
;</h>
;以上条件汇编完全不明所以,问题六
                LJMP    ?C_START

                END

使用特权

评论回复
板凳
天雨粟|  楼主 | 2010-9-15 21:12 | 只看该作者
我的问题能成立吗?盼解答!

使用特权

评论回复
地板
yuyi21ic| | 2010-9-15 22:00 | 只看该作者
完全不懂

使用特权

评论回复
5
天雨粟|  楼主 | 2010-9-15 22:11 | 只看该作者
感谢楼上的顶贴,希望这个问题能引起高手的注意!

使用特权

评论回复
6
ayb_ice| | 2010-9-16 15:36 | 只看该作者
CSEG    AT      0
51MCU复位后就从0这里开始运行了
首先清零RAM,XRAM,然后设备模拟堆栈,然后设置堆栈指针,然后跳转到程序?C_START...
完了
如果你没有将STARTUP.A51复制到你的工程,其实KEIL仍然会自动加入这个文件,并且使用默认配置,除非你的程序显示的占用0这个向量
....

使用特权

评论回复
7
xlsbz| | 2010-9-16 15:54 | 只看该作者
无非就是 清零   设置对战指针

还有就是 重入  还有就是那个bank

OK!

使用特权

评论回复
8
xlsbz| | 2010-9-16 15:55 | 只看该作者
如果 不加 a51.s 的 话 keil会默认添加 A51.LIB   名称可能不对 但是后缀起码正确

使用特权

评论回复
9
天雨粟|  楼主 | 2010-9-17 19:38 | 只看该作者
我把各位大侠给予的解答梳理一下:
加,是为方便自己修改启动配置
不加,Keil仍要添加,并以默认值运行
这是书上未讲的,很重要,不能怪学者有杞人之忧也

bank如是是分组配置,用以巨寻址,就可以暂不理会了。

感谢各位给予解答。分数不好分,就给ayb_ice大侠罢!

使用特权

评论回复
10
448738516| | 2013-1-27 18:25 | 只看该作者
回复9#,学习要知其然且知其所以然,尤其在自己时间充足的时候,我最近也在思考STARTUP.A51,也是一头晕,以前没加,因为看别人也没加,但是,最近看别人的工程里加了这个STARTUP.A51,我就郁闷了,怎么可以加也可以不加啊?看到这几人的回复,还是有点不太懂,希望有人可以系统的整理总结一下啊

使用特权

评论回复
11
dong_abc| | 2013-1-27 19:16 | 只看该作者
本帖最后由 dong_abc 于 2013-1-27 19:18 编辑

这个必须弄懂,不只8051,其他芯片也有启动代码的,百度一下就有了。

使用特权

评论回复
12
448738516| | 2013-1-27 20:47 | 只看该作者
dong_abc 发表于 2013-1-27 19:16
这个必须弄懂,不只8051,其他芯片也有启动代码的,百度一下就有了。

怎么有的教程里添加了STARTUP.A51,有的教程里却没添加呢?

使用特权

评论回复
评论
dong_abc 2013-1-27 20:51 回复TA
添加了就按这个文件进行配置芯片,没加的话,编译器也会给他一个默认的,用户看不见而已。 
13
448738516| | 2013-1-28 20:23 | 只看该作者
448738516 发表于 2013-1-27 20:47
怎么有的教程里添加了STARTUP.A51,有的教程里却没添加呢?

搜噶

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

168

帖子

0

粉丝