c0.asm
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:20k
- page 60, 132
- name c0
- title Paradigm C++ real/extended address mode startup code
- ;
- ; Embedded System Startup Code for Paradigm C++
- ; Copyright (C) 1996, 2000 Paradigm Systems. All rights reserved.
- ;
- ; $Revision: 11 $
- ; $NoKeywords: $
- ;
- ; *********************************************************************
- ; Permission to modify and distribute object files based on this
- ; source code is granted to licensed users of Paradigm C++.
- ;
- ; Under no circumstances is this source code to be re-distributed
- ; without the express permission of Paradigm Systems.
- ; *********************************************************************
- ;
- ; Make sure that this startup module is specified first when linking
- ; the application. Requires Paradigm Assembler 5.0 or later to assemble.
- ;
- ; pasm /mx /d__MDL__ c0.asm
- ;
- ; where
- ; __MDL__ is one of the following:
- ;
- ; __s__ Small memory model startup code
- ; __m__ Medium memory model startup code
- ; __c__ Compact memory model startup code
- ; __l__ Large memory model startup code
- ; __h__ Huge memory model startup code
- ;
- ; These macros are handled in a helper include file.
- ;
- .8086 ; Required for target independence
-
- ;
- ; The macro __ADDR24__ can be used to enable 24-bit address space support.
- ;
- ; The _ALIGN_ macro aligns selected segments on the preferred boundary for
- ; the application.
- ;
- I49OPTIM=1
- IFNDEF __ADDR24__
- _PAD_ = 16
- _ALIGN_ equ <para>
- ELSE
- _PAD_ = 256
- _ALIGN_ equ <page>
- ENDIF
- ;
- ; Some options can be disabled to reduce the size of the startup code
- ; and run-time library helper code. Simply place a semicolon in front
- ; of the following definitions to remove support for selected item.
- ;
- ; __ENABLE_FARDATA Includes code to initialize class FAR_DATA
- ; __ENABLE_FARBSS Includes code to initialize class FAR_BSS
- ; __ENABLE_EXCEPTIONS Includes C++ exception handling support
- ; __ENABLE_TERMINATORS Includes support for exit terminators
- ;
- IFNDEF I49OPTIM
- __ENABLE_FARDATA = 1
- __ENABLE_FARBSS = 1
- __ENABLE_EXCEPTIONS = 1
- __ENABLE_TERMINATORS = 1
- ENDIF
- ;
- ; Be aware that changes made to the startup code can affect the correctness of your
- ; application or the run-time library code.
- ;
- locals @@ ; Define local symbols
- INCLUDE ServicesIncludestartup.inc ; Macros/assembly language definitions
- INCLUDE ServicesIncludec0.inc ; Compiler-specific definitions
- SHOW <Paradigm C++ Startup Support>
- subttl Segment ordering/alignment section
- page
- ;
- ; Segment and group declarations. The order of these declarations is
- ; used to control the order of segments in the .ROM file since the
- ; Paradigm linker copies segments in the same order they
- ; are encountered in the object files.
- ;
- ; Make sure that this startup module is specified first when linking
- ; the application.
- ;
- % DefSeg _TEXT, _ALIGN_, public, CODE, <> ; Default code
- ;
- ; The following segments are used to hold the linked initializers
- ; and terminators. These permit automatic initialization of code
- ; without startup source modification and should be located in ROM.
- ; Terminators are not implemented since an application will normally
- ; not return to the startup code but are supported for run-time library
- ; compatibility.
- ;
- % DefSeg _INIT_, _ALIGN_, public, INITDATA, IGROUP ; Initializers
- % DefSeg _INITEND_, byte, public, INITDATA, IGROUP
- % DefSeg _EXIT_, para, public, EXITDATA, IGROUP ; Terminators
- % DefSeg _EXITEND_, byte, public, EXITDATA, IGROUP
- ;
- ; The following segments are used to mark the place for ROM copies
- ; of initialized data for use by the startup code.
- ;
- % DefSeg _RD, _ALIGN_, public, ROMDATA, <>
- % DefSeg _ERD, _ALIGN_, public, ENDROMDATA, <>
- IFNDEF I49OPTIM
- % DefSeg _BRFD, _ALIGN_, public, ROMFARDATA, <>
- % DefSeg _ERFD, _ALIGN_, public, ENDROMFARDATA, <>
- ENDIF
- IFDEF DEBUG_CACHE_ISSUES
- % DefSeg _BDDC, _ALIGN_, public, FAR_CONST, <> ; Start DSP_DATA_CLASS class
- ENDIF
- ;
- ; The following segments form the Paradigm C++ DGROUP. The startup code
- ; requires thatthe segments in DGROUP follow the Paradigm C++ standard.
- ; The order of these segments/classes must not be changed since the
- ; startup code assumes a specific relationship between classes.
- ;
- % DefSeg _DATA, _ALIGN_, public, DATA, DGROUP ; Initialized data
- % DefSeg _CVTSEG, word, public, DATA, DGROUP ; Output conversion support
- % DefSeg _SCNSEG, word, public, DATA, DGROUP ; Input conversion support
- % DefSeg _BSS, para, public, BSS, DGROUP ; Uninitialized data
- % DefSeg _NVRAM, para, public, NVRAM, DGROUP ; Non-volatile data segment
- IFDEF I49OPTIM
- % DefSeg _NHEAP, _ALIGN_, stack, NHEAP, DGROUP ; Near heap is in DGROUP
- ENDIF
- IFNDEF I49OPTIM
- % DefSeg _EDATA, para, public, EDATA, DGROUP ; End of default data segments
- ENDIF
- ;
- ; The stack in Paradigm C++ is in or out of DGROUP depending on the
- ; memory model.
- ;
- IF @DataSize EQ MM_NEAR
- % DefSeg _NHEAP, _ALIGN_, stack, STACK, DGROUP ; Near heap is in DGROUP
- % DefSeg _STACK, para, stack, STACK, DGROUP ; Stack is in DGROUP
- % DefSeg _ESTACK, para, stack, STACK, DGROUP
- ELSE
- % DefSeg _STACK, _ALIGN_, stack, STACK, SGROUP ; Stack is in its own group
- % DefSeg _ESTACK, para, stack, STACK, SGROUP
- ENDIF ; MM_NEAR
- ;
- ; These are the segments that form the FAR_DATA class which contains any non-const
- ; initialized far objects. Class FAR_DATA is followed by class ENDFAR_DATA, which
- ; is needed to calculate the size of class FAR_DATA at run-time.
- ;
- IFNDEF I49OPTIM
- % DefSeg _BFD, _ALIGN_, public, FAR_DATA, <> ; Start FAR_DATA class
- % DefSeg _EFD, _ALIGN_, public, ENDFAR_DATA,<> ; End FAR_DATA class
- ENDIF
- ;
- ; These are the segments that form the FAR_CONST class which contains any constant
- ; initialized far objects. Class FAR_CONST is followed by class ENDFAR_CONST, which
- ; is needed to calculate the size of class FAR_CONST at run-time.
- ;
- % DefSeg _BFC, _ALIGN_, public, FAR_CONST, <> ; Start FAR_CONST class
- % DefSeg _EFC, _ALIGN_, public, ENDFAR_CONST,<> ; End FAR_CONST class
- ;
- ; These are the segments that form the FAR_BSS class which contains any uninitialized
- ; far objects. Class FAR_BSS is followed by class ENDFAR_BSS, which is needed to
- ; calculate the size of class FAR_BSS at run-time.
- ;
- IFNDEF I49OPTIM
- % DefSeg _BFB, _ALIGN_, public, FAR_BSS, <> ; Start FAR_BSS class
- % DefSeg _EFB, _ALIGN_, public, ENDFAR_BSS, <> ; End FAR_BSS class
- ENDIF
- ;
- ; The following segments will be used to implement the far heap, if dynamic
- ; memory management support is enabled.
- ;
- IFNDEF I49OPTIM
- % DefSeg _FARHEAP, _ALIGN_, public, FAR_HEAP, <> ; Far heap start
- % DefSeg _EFH, _ALIGN_, public, ENDFAR_HEAP,<> ; Far heap end
- ENDIF
- ;
- ; External references
- ;
- ExtProc main ; User application entry point
- ExtProc exit ; Called should main() ever return
- IFDEF __ENABLE_EXCEPTIONS
- ExtProc _ExceptInit ; Exception handling initialization
- ENDIF
- IFDEF __ENABLE_FARDATA
- ExtProc _CopyFarData ; Pull in far data support
- ENDIF
- IFDEF __ENABLE_FARBSS
- ExtProc _InitFarBss ; Pull in far bss support
- ENDIF
- public _sw_startup
- subttl Startup/initialization code
- page
- _TEXT segment
- assume cs:_TEXT
- BegProc _startup, far ; Startup code entry point
- ;Init power up variables, the values are not changed during sw reset
- mov ax,DGROUP
- mov ds,ax
- mov al,55h
- mov bx,offset DGROUP:_g_power_state
- mov ds:[bx],al
- mov al,01h
- mov bx,offset DGROUP:_g_bIsAuxModeOn
- mov ds:[bx],al
-
- _sw_startup: ; Startup code entry point
- ;
- ; Disable interrupts and force the forward direction
- ;
- cli
- cld
- ;
- ; Set up the stack according to the memory model. The default Paradigm
- ; model is to have the stack after the heap in the small and medium
- ; memory models.
- ;
- IF @DataSize EQ MM_NEAR
- mov ax, DGROUP
- mov ss, ax
- mov sp, offset DGROUP:_stack_top
- assume ss:DGROUP
- ELSE
- mov ax, _STACK
- mov ss, ax
- mov sp, offset SGROUP:_stack_top
- assume ss:_STACK
- ENDIF ; @DataSize
- INITIALIZE_STACK = 1 ; used only when CHECK_STACK_SIZE is define
- IFDEF INITIALIZE_STACK
- ;// Initialize stack of main task with 0cafeh
- mov ax, SGROUP
- mov es, ax
- mov bx, ax ;safe the value for CORE stack length calculation
- assume es:SGROUP
- mov ax, 0fecah
- mov di, offset SGROUP:_stack_bottom
- ;// calculate length of the main stack
- mov cx, offset SGROUP:_stack_top
- sub cx, di
- shr cx, 1
- jcxz short fill_main_stack
- ;// fill main stack with AX
- rep stosw
- fill_main_stack:
- ENDIF ;INITIALIZE_STACK
- ;
- ; Prepare the segment registers for initialization. The initialized
- ; data is assumed to have been located in the class ROMDATA which begins
- ; with the segment _RD.
- ;
- mov ax, DGROUP
- mov es, ax
- mov ax, _RD
- mov ds, ax
- assume ds:_RD, es:DGROUP
- ;
- ; Copy DGROUP initialized data from its position in ROM to the target
- ; address in RAM. Because this is a group, there is never more than
- ; 64K of data to copy.
- ;
- mov si, offset _romdata_start
- mov di, offset DGROUP:_data_start
- mov cx, offset DGROUP:_bss_start
- sub cx, di
- shr cx, 1
- jcxz short $$1
- rep movsw
- $$1:
- ;
- ; Zero out the BSS area - always less than 64KB
- ;
- mov ax, DGROUP
- mov ds, ax
- mov es, ax
- assume ds:DGROUP, es:DGROUP
- xor ax, ax
- mov di, offset DGROUP:_bss_start
- mov cx, offset DGROUP:_nvram_start
- sub cx, di
- shr cx, 1
- jcxz short $$5
- rep stosw
- $$5:
- ;
- ; Memory is now initialized. We need to initialize the exception handling
- ; logic if enabled.
- ;
- mov bp, ax
- IFDEF __ENABLE_EXCEPTIONS
- push bp
- call __ExceptInit
- pop ax
- ENDIF
- ;
- ; Fill in value of _stklen so stack checking will work
- ;
- IF @DataSize EQ MM_NEAR
- mov ax, offset DGROUP:_stack_top
- sub ax, offset DGROUP:_stack_bottom
- mov _stklen, ax
- ELSE
- mov ax, offset SGROUP:_stack_top
- sub ax, offset SGROUP:_stack_bottom
- mov _stklen, ax
- IFDEF I49OPTIM
- GlobalW _heaplen ; Needed for heap checking logic
- ENDIF
- ENDIF
- ;
- ; Linked in initializers are in their own group. Load pointers to the start
- ; and end of the table and call the code that processes them.
- ;
- mov si, offset IGROUP:InitStart
- mov di, offset IGROUP:InitEnd
- mov ax, IGROUP
- mov es, ax
- assume es:nothing
- call Initialize
- ;
- ; Call the C/C++ entry point main() - initialization is complete and user
- ; application can take control.
- ;
- ;sti
- call main
- ;
- ; A return from main() is application dependent. We will call exit() and it can decide
- ; what the appropriate behavior will be.
- ;
- push ax
- call exit
- IFDEF I49OPTIM
- ; !!! We should never get her !!!
- jmp _startup
- ENDIF
- EndProc _startup
- page
- ;
- ; Function: Initialize
- ;
- ; Call all of the linked-in initializers in the _INIT_ segment. These
- ; are a series of pointers to routines which are guaranteed to
- ; execute before main() is called. The advantage of this approach is
- ; that the initialization will be made by virtue of the code being
- ; linked in, without any modification to the startup code.
- ;
- ; This implementation permits the initializers to be kept in ROM,
- ; even though there is no ordering of the initializers. The register
- ; use is as follows:
- ; SI - initializers start
- ; DI - initializers end
- ; CX - number of initializers not processed
- ; BX - current initializer
- ; AH - current priority
- ;
- Initialize proc near
- mov ax, di ; Compute the number of initializers
- sub ax, si
- sub dx, dx
- mov cx, SIZE InitRec
- idiv cx
- mov cx, ax ; Number of initializers in the table
- jcxz short @@InitDone
- sub ah, ah ; Start with the highest priority
- @@PriTop:
- mov bx, si ; Point to the start of the table
- @@NextInit:
- cmp bx, di ; Check if this pass is done
- jae short @@PriBottom
- cmp es:[bx.pri], ah ; Compare against the current priority
- jne short @@TableBottom
- push es ; Save registers we don't want trashed
- push ax
- push bx
- push cx
- push si
- push di
- cmp es:[bx.ctype], MM_NEAR ; Is it near or far?
- je short @@NearCall
- call dptr es:[bx.foff] ; Call the initializer
- jmp short @@Cleanup
- @@NearCall:
- call wptr es:[bx.foff] ; Call the initializer
- @@Cleanup:
- pop di ; Restore the registers
- pop si
- pop cx
- pop bx
- pop ax
- pop es
- dec cx
- jz short @@InitDone
- @@TableBottom:
- add bx, SIZE InitRec
- jmp @@NextInit
- @@PriBottom:
- inc ah ; Process the next priority
- jmp @@PriTop
- @@InitDone:
- ret
- Initialize endp
- ;
- ; Called by the exit handling code to execute C++ static destructors and
- ; any #pragma exit routines.
- ;
- __cleanup proc dist
- public __cleanup
- IFDEF __ENABLE_TERMINATORS
- ; Call cleanup routines
- mov ax, IGROUP
- mov es, ax
- push si
- push di
- mov si, offset IGROUP:ExitStart
- mov di, offset IGROUP:ExitEnd
- call Cleanup
- pop di
- pop si
- ENDIF
- ret
- __cleanup endp
- IFDEF __ENABLE_TERMINATORS
- ;
- ; Function: Cleanup
- ;
- ; Call all of the linked-in terminators in the _EXIT_ segment.
- ;
- ; This implementation permits the terminators to be kept in ROM,
- ; even though there is no ordering of the terminators. The register
- ; use is as follows:
- ; SI - terminators start
- ; DI - terminators end
- ; CX - number of terminators not processed
- ; BX - current terminators
- ; AH - current priority
- ;
- Cleanup proc near
- mov ax, di ; Compute the number of terminators
- sub ax, si
- sub dx, dx
- mov cx, SIZE InitRec
- idiv cx
- mov cx, ax ; Number of terminators in the table
- jcxz @@ExitDone
- sub ah, ah ; Start with the highest priority
- @@PriTop:
- mov bx, si ; Point to the start of the table
- @@NextInit:
- cmp bx, di ; Check if this pass is done
- jae @@PriBottom
- cmp es:[bx.pri], ah ; Compare against the current priority
- jne @@TableBottom
- push es ; Save registers we don't want trashed
- push ax
- push bx
- push cx
- push si
- push di
- cmp es:[bx.ctype], MM_NEAR ; Is it near or far?
- je @@NearCall
- call dptr es:[bx.foff] ; Call the terminator
- jmp short @@Cleanup
- @@NearCall:
- call wptr es:[bx.foff] ; Call the terminator
- @@Cleanup:
- pop di ; Restore the registers
- pop si
- pop cx
- pop bx
- pop ax
- pop es
- dec cx
- jz @@ExitDone
- @@TableBottom:
- add bx, SIZE InitRec
- jmp @@NextInit
- @@PriBottom:
- inc ah ; Process the next priority
- jmp @@PriTop
- @@ExitDone:
- ret
- Cleanup endp
- ENDIF
- _TEXT ends
- subttl Data declarations
- page
- ;
- ; Run-time libraries and other modules can insert initializers in this
- ; segment. Initializers are executed by priority, and by link order
- ; when the same priority. Static destructors are not implemented since
- ; we assume that the application never terminates.
- ;
- _INIT_ segment
- LabelD InitStart
- _INIT_ ends
- _INITEND_ segment
- LabelD InitEnd
- _INITEND_ ends
- _EXIT_ segment
- LabelD ExitStart
- _EXIT_ ends
- _EXITEND_ segment
- LabelD ExitEnd
- db 16 dup (0) ; Force the next segment to a new paragraph
- _EXITEND_ ends
- ;
- ; These are the segment definitions for class DATA, BSS, NVRAM, and STACK.
- ; thh size of class DATA is calculated by subtracting the offset of _DATA
- ; from the offset _BSS. The size of the BSS is done by subtracting the
- ; offset of _BSS from the offset of _NVRAM. We don't ever initialize the
- ; segment _NVRAM so we don't care about the size.
- ;
- ; Class NVRAM is followed by class EDATA which is used to mark the end of the
- ; default data segments.
- ;
- _DATA segment
- LabelB _data_start, public ; Offset zero within the DATA class
- LabelB DATASEG@, public ; Symbol used to find data segment
- ;
- ; The check string must NOT be moved or changed without changing the null
- ; pointer check logic
- ;
- NULL db 4 dup (0)
- ChkStr db 'NULL CHECK'
- db 2 dup (0)
- db 4 dup (0) ; Destructor count
- db 2 dup (0) ; Exception list
- db 4 dup (0) ; Exception vptr
- db 6 dup (0) ; Reserved
- GlobalW _Exception_list, -1 ; List of exception handlers
- GlobalW _8086, 0 ; Cpu type
- _DATA ends
- _CVTSEG segment ; Stream I/O conversion helpers
- LabelW _RealCvtVector, public
- _CVTSEG ends
- _SCNSEG segment
- LabelW _ScanTodVector, public
- _SCNSEG ends
- _BSS segment ; Start of BSS is the end of initialized data
- LabelB _bss_start, public ; Offset zero within the BSS class
- GlobalW _stklen ; Needed for stack checking logic
- _BSS ends
- _NVRAM segment ; Start of NVRAM is the end of uninitialized data
- LabelB _nvram_start, public ; Offset zero within the NVRAM class
- LabelB g_power_state, public ; g_power_state hold the power up status and should not be changed
- db ?
- LabelB g_bIsAuxModeOn, public ; g_bIsAuxModeOn hold the status of player
- db ?
- LabelB bHDCPProducKeys, public ; g_power_state hold the power up status and should not be changed
- db ?
- _NVRAM ends
- IFNDEF I49OPTIM
- _EDATA segment ; Default static data class end marker
- LabelB _staticdata_end, public ; Offset of the end of static data
- db _PAD_ dup (0) ; Force the next segment to a new paragraph
- _EDATA ends
- ENDIF
- ;
- ; Create the default application stack and an end marker that allows the stack
- ; size to be set using the linker. These segments must be contiguous to correctly
- ; initialize the SS:SP registers.
- ;
- IF @DataSize EQ MM_NEAR
- _NHEAP segment
- LabelW _nearheap_start, public ; Define the start of the default heap
- LabelW _stack_bottom, public ; Define the bottom of the default stack
- _NHEAP ends
- ENDIF ; @DataSize EQ MM_NEAR
- IFDEF I49OPTIM
- _NHEAP segment
- LabelW _nearheap_start, public ; Define the start of the default heap
- _NHEAP ends
- ENDIF
- _STACK segment
- LabelW STACKSEG@, public ; Symbol used to find the stack segment
- LabelW _stack_segment, public ; Define a label for the default stack segment
- IF @DataSize NE MM_NEAR
- LabelW _stack_bottom, public ; Define the bottom of the default stack
- ENDIF ; @DataSize NE MM_NEAR
- _STACK ends
- _ESTACK segment
- LabelW _stack_top, public ; Define the bottom of the default stack
- ;D_SUPPORT_SACD db _PAD_ dup (0) ; Mark the end of the stack and prevent an alias
- db (0) ; Mark the end of the stack and prevent an alias
- _ESTACK ends
- ;
- ; These are segment definitions for the classes ROMDATA and ENDROMDATA. Class
- ; ROMDATA never contains anything (it is filled in by a Paradigm LOCATE DUP
- ; directive). Class ENDROMDATA is used to mark the end of class ROMDATA and
- ; prevent a segment alias (since class ROMDATA will have zero length).
- ;
- ; NOTE: You can't take the address of segments in class ENDROMDATA as they are
- ; aliased with class ROMDATA.
- ;
- _RD segment
- LabelB _romdata_start, public ; Mark the start of class ROMDATA
- _RD ends
- _ERD segment
- LabelB _romdata_end, public ; Mark the end of class ROMDATA
- db _PAD_ dup (0) ; Force the next segment to a new paragraph
- _ERD ends
- ;
- ; These are the four segments we defined above to support the FAR_DATA class.
- ; Here we open each segment and define a label that we can take the address of
- ; for the purposes of finding the length of class FAR_DATA, and the starting
- ; addresses of the classes FAR_DATA and ROMFARDATA.
- ;
- IFNDEF I49OPTIM
- _BFD segment
- LabelB _fardata_start, public ; Mark the start of far initialized data
- _BFD ends
- _EFD segment
- LabelB _fardata_end, public ; Mark the end of far initialized data
- db _PAD_ dup (0) ; Force the next segment to a new paragraph
- _EFD ends
- ENDIF
- _BFC segment
- LabelB _farconst_start, public ; Mark the start of far constant data
- _BFC ends
- _EFC segment
- LabelB _farconst_end, public ; Mark the end of far const data
- db _PAD_ dup (0) ; Force the next segment to a new paragraph
- _EFC ends
- IFNDEF I49OPTIM
- _BFB segment
- LabelB _farbss_start, public ; Mark the start of far uninitialized data
- _BFB ends
- _EFB segment
- LabelB _farbss_end, public ; Mark the end of far uninitialized data
- db _PAD_ dup (0) ; Force the next segment to a new paragraph
- _EFB ends
- _BRFD segment
- LabelB _romfardata_start, public ; Mark the start of class ROMFARDATA
- _BRFD ends
- _ERFD segment
- LabelB _romfardata_end, public ; Mark the end of the ROMFARDATA
- db _PAD_ dup (0) ; Force the next segment to a new paragraph
- _ERFD ends
- _FARHEAP segment
- LabelW _farheap_start, public ; Mark the start of the far heap
- _FARHEAP ends
- _EFH segment
- LabelW _farheap_end, public ; Mark the end of the far heap
- db _PAD_ dup (0) ; Pad the end of the far heap
- _EFH ends
- ENDIF
- end _startup ; Program entry point