home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1991
/
10
/
embedcp
/
code
/
c0.asm
< prev
next >
Wrap
Assembly Source File
|
1991-05-27
|
19KB
|
561 lines
NAME c0
PAGE 60,132
LOCALS
;[]-------------------------------------------------------------------[]
;| C0.ASM -- Start Up Code for MIO |
;| |
;| Turbo C++ Run Time Library |
;| |
;| Portions Copyright (c) 1991, Stuart G. Phillips. |
;| All rights reserved. |
;| |
;| Copyright (c) 1987, 1991 by Borland International Inc. |
;| All rights reserved. |
;| |
;| This software is subject to the terms and conditions of the |
;| license agreement distributed with Borland C++. |
;[]-------------------------------------------------------------------[]
__C0__ = 1
INCLUDE RULES.ASI
; Segment and Group declarations
_BOOT SEGMENT BYTE PUBLIC 'CODE' AT 0FFFFh
ORG 0
boot_vector LABEL BYTE
ENDS
_TEXT SEGMENT BYTE PUBLIC 'CODE'
ENDS
_FARDATA SEGMENT PARA PUBLIC 'FAR_DATA'
ENDS
_FARBSS SEGMENT PARA PUBLIC 'FAR_BSS'
ENDS
IFNDEF __TINY__
_OVERLAY_ SEGMENT PARA PUBLIC 'OVRINFO'
ENDS
_1STUB_ SEGMENT PARA PUBLIC 'STUBSEG'
ENDS
ENDIF
_DATA SEGMENT PARA PUBLIC 'DATA'
ENDS
_INIT_ SEGMENT WORD PUBLIC 'INITDATA'
InitStart label byte
ENDS
_INITEND_ SEGMENT BYTE PUBLIC 'INITDATA'
InitEnd label byte
ENDS
_EXIT_ SEGMENT WORD PUBLIC 'EXITDATA'
ExitStart label byte
ENDS
_EXITEND_ SEGMENT BYTE PUBLIC 'EXITDATA'
ExitEnd label byte
ENDS
_CVTSEG SEGMENT WORD PUBLIC 'DATA'
ENDS
_SCNSEG SEGMENT WORD PUBLIC 'DATA'
ENDS
IFNDEF __HUGE__
_BSS SEGMENT WORD PUBLIC 'BSS'
ENDS
_BSSEND SEGMENT BYTE PUBLIC 'BSSEND'
ENDS
ENDIF
IFNDEF __TINY__
_STACK SEGMENT STACK 'STACK'
ENDS
ENDIF
ASSUME CS:_TEXT, DS:DGROUP
; External References
extrn _main:DIST
extrn __stklen:word
IF LDATA EQ false
extrn __heaplen:word
ENDIF
SUBTTL Start Up Code
PAGE
;/* */
;/*-----------------------------------------------------*/
;/* */
;/* Start Up Code */
;/* ------------- */
;/* */
;/*-----------------------------------------------------*/
;/* */
; public __AHINCR
; __AHINCR equ 1000h
; public __AHSHIFT
; __AHSHIFT equ 12
IFDEF __NOFLOAT__
MINSTACK equ 128 ; minimal stack size in words
ELSE
MINSTACK equ 256 ; minimal stack size in words
ENDIF
;
; At the start, DS and ES both point to the segment prefix.
; SS points to the stack segment except in TINY model where
; SS is equal to CS
;
_TEXT SEGMENT
IFDEF __TINY__
ENDIF
STARTX PROC NEAR
jmp START
ORG 2000h
START:
; Save general information, such as :
; DGROUP segment address
; Top of far heap
IFDEF __TINY__
mov dx, cs ; DX = GROUP Segment address
ELSE
mov dx, DGROUP ; DX = GROUP Segment address
ENDIF
mov cs:DGROUP@@, dx
mov ds,dx ; Set DGROUP as data segment
mov bp,0c000h ; BP = segment at top of memory
; Calculate the first free segment value by finding the top of data
; in the DGROUP data group - add in the offset of the end and convert
; to paragraphs.
mov ax,dx
mov dx,offset DGROUP:edata@
add dx,15
mov cl,4
shr dx,cl
add ax,dx
mov word ptr _heaptop@ + 2, ax
; Set temporary stack at top of used memory - it gets changed later
cli
mov ss,ax
mov sp,100h
sti
push ax
;
; Save several vectors and install default divide by zero handler.
;
call SaveVectors
; Determine the amount of memory that we need to keep
pop ax
IFDEF _DSSTACK_
mov dx, ds
ELSE
mov dx, ax
ENDIF
sub bp, dx ; BP = remaining size in paragraphs
IF LDATA
mov di, seg __stklen
mov es, di
mov di, es:__stklen ; DI = Requested stack size
ELSE
mov di, __stklen ; DI = Requested stack size
ENDIF
;
; Make sure that the requested stack size is at least MINSTACK words.
;
cmp di, 2*MINSTACK ; requested stack big enough ?
jae AskedStackOK
mov di, 2*MINSTACK ; no --> use minimal value
IF LDATA
mov es:__stklen, di ; override requested stack size
ELSE
mov __stklen, di ; override requested stack size
ENDIF
AskedStackOK label near
IFDEF _DSSTACK_
add di, offset DGROUP: edata@
jb InitFailed ; DATA segment can NOT be > 64 Kbytes
ENDIF
IF LDATA EQ false
add di, __heaplen
jb InitFailed ; DATA segment can NOT be > 64 Kbytes
ENDIF
mov cl, 4
shr di, cl ; $$$ Do not destroy CL $$$
inc di ; DI = DS size in paragraphs
cmp bp, di
IF LDATA EQ false
jb InitFailed ; Not enough memory
cmp __stklen, 0
je ExpandDS ; Expand DS up to 64 Kb
cmp __heaplen, 0
jne ExcessOfMemory ; Much more available than needed
ExpandDS label near
mov di, 1000h
cmp bp, di
ja ExcessOfMemory ; Enough to run the program
mov di, bp
jmp short ExcessOfMemory ; Enough to run the program
ELSE
jnb ExcessOfMemory ; Much more available than needed
ENDIF
; All initialization errors arrive here
InitFailed label near
jmp near ptr _abort
; Set far heap base and pointer
ExcessOfMemory label near
mov bx, di
add bx, dx
mov word ptr _heapbase@ + 2, bx
mov word ptr _brklvl@ + 2, bx
shl di, cl ; $$$ CX is still equal to 4 $$$
cli ; req'd for pre-1983 88/86s
mov ss, dx ; Set the program stack
mov sp, di
sti
mov word ptr _first_stack@, di
mov word ptr _first_stack@ + 2, dx
IFNDEF _DSSTACK_
; Set the stack to a known pattern
mov bx,di
mov es,dx ; ES is stack segment
mov cx,di
shr cx,1 ; Convert to words
mov di,0
mov ax,'ST'
cld
rep stosw
mov di,bx
ENDIF
IFNDEF _DSSTACK_
mov ax, seg __stklen
mov es, ax
mov es:__stklen, di ; If separate stack segment, save size
ENDIF
IFNDEF __HUGE__
; Reset uninitialized data area
xor ax, ax
mov es, cs:DGROUP@@
mov di, offset DGROUP: bdata@
mov cx, offset DGROUP: edata@
sub cx, di
cld
rep stosb
ENDIF
; Prepare main arguments
xor bp,bp ; set BP to 0 for overlay mgr
IFNDEF __TINY__
mov ax,DGROUP
mov ds,ax
mov si,offset DGROUP:InitStart ;si = start of table
mov di,offset DGROUP:InitEnd ;di = end of table
ELSE
mov si,offset DGROUP:InitStart ;si = start of table
mov di,offset DGROUP:InitEnd ;di = end of table
ENDIF
call StartExit
mov ds, cs:DGROUP@@
; OK, to save space we use self-modifying code.
; Replace the JA instruction in the startup/exit logic with
; a JB instruction. This allows us to scan the table on exit
; executing functions in reverse priority. Also change the
; immediate which is stored in ah at the first instruction to a 0.
mov byte ptr cs:JA_JB,72h
mov byte ptr cs:StartExit+1,0
; MIO main program is called with no parameters - set argc to
; a zero count and argv to a null pointer
; ExitCode = main(argc,argv);
xor ax,ax
IF LDATA
push ax
push ax ; Null argv pointer
ELSE
push ax ; Null argv pointer
ENDIF
push ax ; arc = 0
call _main
; Clean up - MIO has no files or streams but clean up the
; interrupt vectors and then jump back to the EPROM boot code
; ready for the next download
push ax
jmp far ptr boot_vector
;---------------------------------------------------------------------------
; _exit()
;
; Restore interrupt vectors taken during startup.
;
; Jump back to EPROM boot code
;
;---------------------------------------------------------------------------
__exitclean PROC NEAR
PUBLIC __exitclean
IFNDEF __TINY__
mov ax,DGROUP
mov ds,ax
mov si,offset DGROUP:ExitStart
mov di,offset DGROUP:ExitEnd
ELSE
mov si,offset DGROUP:ExitStart
mov di,offset DGROUP:ExitEnd
ENDIF
call StartExit
mov ds, cs:DGROUP@@
ENDP
__exit PROC DIST
PUBLIC __exit
mov ds, cs:DGROUP@@
call DIST ptr __restorezero ; restore captured INT vectors
jmp far ptr boot_vector
ENDP
STARTX ENDP
SUBTTL Vector save/restore & default Zero divide routines
PAGE
;[]------------------------------------------------------------[]
;| |
;| Interrupt Save/Restore routines and default divide by zero |
;| handler. |
;| |
;[]------------------------------------------------------------[]
ZeroDivision PROC FAR
ret
ZeroDivision ENDP
;
; Install default divide by zero handler.
;
SaveVectors PROC FAR
mov ax, 0
push es ; Save current es
push di ; ... and di
mov es,ax
mov di,0
mov es:[di], cs
mov dx, offset ZeroDivision
mov es:[di+2],dx
pop di
pop es
ret
SaveVectors ENDP
;--------------------------------------------------------------------------
; restorezero() resets the divide by zero interrupt to point to the
; boot prom entry point
;
;--------------------------------------------------------------------------
__restorezero PROC DIST
PUBLIC __restorezero
push es ; Save es
push di ; ...and di
xor ax,ax
mov es,ax
mov di,0
mov word ptr es:[si],0
mov word ptr es:[si+2],0ffffh
pop di
pop es
ret
ENDP
;------------------------------------------------------------------
; Loop through a startup/exit (SE) table,
; calling functions in order of priority.
; DS:SI is assumed to point to the beginning of the SE table
; DS:DI is assumed to point to the end of the SE table
; First 64 priorities are reserved by Borland
;------------------------------------------------------------------
PNEAR EQU 0
PFAR EQU 1
NOTUSED EQU 0ffh
SE STRUC
calltype db ? ; 0=near,1=far,ff=not used
priority db ? ; 0=highest,ff=lowest
addrlow dw ?
addrhigh dw ?
SE ENDS
StartExit PROC NEAR
@@Start: mov ah,0ffh ; start with lowest priority
mov dx,di ; set sentinel to end of table
mov bx,si ; bx = start of table
@@TopOfTable: cmp bx,di ; and the end of the table?
je @@EndOfTable ; yes, exit the loop
cmp [bx.calltype],NOTUSED ; check the call type
je @@Next
cmp [bx.priority],ah ; check the priority
JA_JB: ja @@Next ; too high? skip
mov ah,[bx.priority] ; keep priority
mov dx,bx ; keep index in dx
@@Next: add bx,SIZE SE ; bx = next item in table
jmp @@TopOfTable
@@EndOfTable: cmp dx,di ; did we exhaust the table?
je @@Done ; yes, quit
mov bx,dx ; bx = highest priority item
push ds ; save ds
pop es
push es ; es = ds
cmp [bx.calltype],PNEAR ; is it near or far?
mov [bx.calltype],NOTUSED ; wipe the call type
mov ds, cs:DGROUP@@
je @@NearCall
@@FarCall: call DWORD PTR es:[bx.addrlow]
pop ds ; restore ds
jmp @@Start
@@NearCall: call WORD PTR es:[bx.addrlow]
pop ds ; restore ds
jmp @@Start
@@Done: ret
StartExit ENDP
_abort PROC DIST
PUBLIC _abort
mov ax, 3
push ax
call __exit ; _exit(3);
ENDP
; The DGROUP@ variable is used to reload DS with DGROUP
PubSym@ DGROUP@, <dw ?>, __PASCAL__
; __MMODEL is used to determine the memory model or the default
; pointer types at run time.
public __MMODEL
__MMODEL dw MMODEL
_TEXT ENDS
SUBTTL Start Up Data Area
PAGE
;[]------------------------------------------------------------[]
;| Start Up Data Area |
;| |
;| WARNING Do not move any variables in the data |
;| segment unless you're absolutely sure |
;| that it does not matter. |
;[]------------------------------------------------------------[]
_DATA SEGMENT
; Magic symbol used by the debug info to locate the data segment
public DATASEG@
DATASEG@ label byte
CopyRight db 4 dup(0)
db 'Borland C++ - Copyright 1991 Borland Intl.',0
;
; Miscellaneous variables
;
PubSym@ _C0argc, <dw 0>, __CDECL__
dPtrPub@ _C0argv, 0, __CDECL__
dPtrPub@ _C0environ, 0, __CDECL__
PubSym@ _envLng, <dw 0>, __CDECL__
PubSym@ _envseg, <dw 0>, __CDECL__
PubSym@ _envSize, <dw 0>, __CDECL__
PubSym@ _psp, <dw 0>, __CDECL__
PubSym@ _version, <label word>, __CDECL__
PubSym@ _osmajor, <db 0>, __CDECL__
PubSym@ _osminor, <db 0>, __CDECL__
PubSym@ errno, <dw 0>, __CDECL__
PubSym@ _StartTime, <dw 0,0>, __CDECL__
; Memory management variables
IF LDATA EQ false
PubSym@ __heapbase, <dw DGROUP:edata@>, __CDECL__
PubSym@ __brklvl, <dw DGROUP:edata@>, __CDECL__
ENDIF
PubSym@ _heapbase, <dd 0>, __CDECL__
PubSym@ _brklvl, <dd 0>, __CDECL__
PubSym@ _heaptop, <dd 0>, __CDECL__
PubSym@ _first_stack <dd 0>, __CDECL__
; If stack in DS and Large data model then override location of __emu
; IFDEF _DSSTACK_
; IF LDATA
; public __emu
; __emu db 044h DUP (0)
; db 0CCh DUP (?)
; ENDIF
; ENDIF
_DATA ENDS
_CVTSEG SEGMENT
; PubSym@ _RealCvtVector, <label word>, __CDECL__
ENDS
_SCNSEG SEGMENT
; PubSym@ _ScanTodVector, <label word>, __CDECL__
ENDS
IFNDEF __HUGE__
_BSS SEGMENT
bdata@ label byte
ENDS
_BSSEND SEGMENT
edata@ label byte
ENDS
ENDIF
IFNDEF __TINY__
_STACK SEGMENT
db 128 dup(?) ;minimum stack size
ENDS
ENDIF
END STARTX