head 1.1; access ; symbols ; locks ; comment @@; 1.1 date 89.06.13.18.28.26; author pkern; state Exp; branches ; next ; desc @@ 1.1 log @Initial revision @ text @ NAME c0 PAGE 60,132 ;[]------------------------------------------------------------[] ;| C0.ASM -- Start Up Code | ;| | ;| Turbo-C Run Time Library version 2.0 | ;| | ;| Copyright (c) 1988 by Borland International Inc. | ;| All Rights Reserved. | ;[]------------------------------------------------------------[] INCLUDE RULES.ASI _Strict87_ equ false ; emulation skips peculiar details ; Segment and Group declarations _TEXT SEGMENT BYTE PUBLIC 'CODE' _TEXT ENDS _DATA SEGMENT PARA PUBLIC 'DATA' _DATA ENDS IFNDEF __NOFLOAT__ _EMUSEG SEGMENT WORD COMMON 'DATA' _EMUSEG ENDS ENDIF _CRTSEG SEGMENT WORD COMMON 'DATA' _CRTSEG ENDS _CVTSEG SEGMENT WORD PUBLIC 'DATA' _CVTSEG ENDS _SCNSEG SEGMENT WORD PUBLIC 'DATA' _SCNSEG ENDS IFNDEF __HUGE__ _BSS SEGMENT WORD PUBLIC 'BSS' _BSS ENDS _BSSEND SEGMENT BYTE PUBLIC 'STACK' _BSSEND ENDS ENDIF IFNDEF __TINY__ _STACK SEGMENT STACK 'STACK' _STACK ENDS ENDIF IFNDEF __NOFLOAT__ IF LDATA IFNDEF __HUGE__ DGROUP GROUP _DATA, _EMUSEG, _CRTSEG, _CVTSEG, _SCNSEG, _BSS, _BSSEND ELSE DGROUP GROUP _DATA, _EMUSEG, _CRTSEG, _CVTSEG, _SCNSEG ENDIF ELSE IFNDEF __TINY__ DGROUP GROUP _DATA, _EMUSEG, _CRTSEG, _CVTSEG, _SCNSEG, _BSS, _BSSEND ELSE DGROUP GROUP _TEXT, _DATA, _EMUSEG, _CRTSEG, _CVTSEG, _SCNSEG, _BSS, _BSSEND ENDIF ENDIF ELSE IF LDATA IFNDEF __HUGE__ DGROUP GROUP _DATA, _CRTSEG, _CVTSEG, _SCNSEG, _BSS, _BSSEND ELSE DGROUP GROUP _DATA, _CRTSEG, _CVTSEG, _SCNSEG ENDIF ELSE IFNDEF __TINY__ DGROUP GROUP _DATA, _CRTSEG, _CVTSEG, _SCNSEG, _BSS, _BSSEND ELSE DGROUP GROUP _TEXT, _DATA, _CRTSEG, _CVTSEG, _SCNSEG, _BSS, _BSSEND ENDIF ENDIF ENDIF ASSUME CS:_TEXT, DS:DGROUP ; External References ExtProc@@ main, __CDECL__ ExtProc@@ _setargv, __CDECL__ ExtProc@@ _setenvp, __CDECL__ ExtProc@@ exit, __CDECL__ IF LDATA EQ false ExtSym@@ _heaplen, WORD, __CDECL__ ENDIF ExtSym@@ _stklen, WORD, __CDECL__ SUBTTL Start Up Code PAGE ;/* */ ;/*-----------------------------------------------------*/ ;/* */ ;/* Start Up Code */ ;/* ------------- */ ;/* */ ;/*-----------------------------------------------------*/ ;/* */ PSPHigh equ 00002h PSPEnv equ 0002ch PSPCmd equ 00080h 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__ ORG 100h ENDIF STARTX PROC NEAR ; Save general information, such as : ; DGROUP segment address ; DOS version number ; Program Segment Prefix address ; Environment 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 ah, 30h int 21h mov bp, ds:[PSPHigh]; BP = Highest Memory Segment Addr mov bx, ds:[PSPEnv] ; BX = Environment Segment address mov ds, dx mov _version@@, ax ; Keep major and minor version number mov _psp@@, es ; Keep Program Segment Prefix address mov _envseg@@, bx ; Keep Environment Segment address mov word ptr _heaptop@@ + 2, bp mov _8087@@, -1 ; ; Save several vectors and install default divide by zero handler. ; call SaveVectors ; Look for a '87' environment variable, and use this loop to ; count the number of environment variables and to compute the ; environment size. ; Each variable is ended by a 0 and a zero-length variable stops ; the environment. The environment can NOT be greater than 32k. les di, dword ptr _envLng@@ mov ax, di mov bx, ax mov cx, 07FFFh ; Environment cannot be > 32 Kbytes IsIt87Var label near cmp word ptr es:[di], '78' jne GetVarLng mov dx, es:[di+2] cmp dl, '=' jne GetVarLng and dh, not ' ' inc _8087@@ cmp dh, 'Y' jne GetVarLng inc _8087@@ GetVarLng label near repnz scasb jcxz InitFailed ; Bad environment !!! inc bx ; BX = Nb environment variables cmp es:[di], al jne IsIt87Var ; Next variable ... or ch, 10000000b neg cx mov _envLng@@, cx ; Save Environment size mov cx, dPtrSize / 2 shl bx, cl add bx, dPtrSize * 4 and bx, not ((dPtrSize * 4) - 1) mov _envSize@@, bx ; Save Environment Variables Nb. ; Determine the amount of memory that we need to keep IF LDATA mov dx, ss sub bp, dx ; BP = remaining size in paragraphs IFDEF __HUGE__ 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 IFDEF __HUGE__ mov es:_stklen@@, di ; override requested stack size ELSE mov _stklen@@, di ; override requested stack size ENDIF AskedStackOK label near mov cl, 4 shr di, cl ; $$$ Do not destroy CL $$$ inc di ; DI = Stack size in paragraphs cmp bp, di jnb ExcessOfMemory ; Much more available than needed ELSE mov dx, ds sub bp, dx ; BP = remaining size in paragraphs mov di, _stklen@@ ; DI = Requested stack size ; ; 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 mov _stklen@@, di ; override requested stack size AskedStackOK label near add di, offset DGROUP: edata@@ jb InitFailed ; DATA segment can NOT be > 64 Kbytes add di, _heaplen@@ jb InitFailed ; DATA segment can NOT be > 64 Kbytes mov cl, 4 shr di, cl ; $$$ Do not destroy CL $$$ inc di ; DI = DS size in paragraphs cmp bp, di 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 ENDIF ; All initialization errors arrive here InitFailed label near jmp near ptr abort@@ ; Return to DOS the amount of memory in excess ; 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 mov ax, _psp@@ sub bx, ax ; BX = Number of paragraphs to keep mov es, ax ; ES = Program Segment Prefix address mov ah, 04Ah push di ; preserve DI int 021h ; this call clobbers SI,DI,BP !!!!!! pop di ; restore DI ; ; Set the program stack. Take care to prevent the disastrous ; interrupt that could happen with a stack that is half switched. ; shl di, cl ; $$$ CX is still equal to 4 $$$ cli mov ss, dx mov sp, di sti 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 rep stosb ENDIF IFNDEF __NOFLOAT__ ; Install floating point software push cs ;Simulation of a FAR call call ds:[__emu1st] ENDIF ; Prepare main arguments call _setargv@@ call _setenvp@@ mov ah, 0 int 1ah ; get current BIOS time in ticks mov word ptr _StartTime@@,dx ; save it for clock() fn mov word ptr _StartTime@@+2,cx IFNDEF __OLDCONIO__ IF LPROG push cs ; Simulation of a FAR call ENDIF call ds:[__crt1st] ; Initialize window sizes, etc. ENDIF ; ExitCode = main(argc,argv,envp); IF LDATA push word ptr environ@@+2 push word ptr environ@@ push word ptr _argv@@+2 push word ptr _argv@@ ELSE push word ptr environ@@ push word ptr _argv@@ ENDIF push _argc@@ call main@@ ; Flush and close streams and files push ax call exit@@ ;--------------------------------------------------------------------------- ; _exit() ; ; Restore interrupt vectors taken during startup. signal() functions ; could have grabbed vectors 0, 4, 5 or 6. ; ; Check for NULL pointer errors. ; ; Exit to DOS. ; ;NOTE : _exit() doesn't close any files or run exit functions. This is a ; minimal 'cleanup & quit' program exit. ;--------------------------------------------------------------------------- PubProc@@ _exit, __CDECL__ mov ds, cs:DGROUP@@@@ IF LPROG call far ptr _restorezero@@ ; restore captured INT vectors ELSE call near ptr _restorezero@@ ENDIF IFNDEF __NOFLOAT__ ; Restore interrupt vectors taken by __emu1st push cs ;Simulation of a FAR call call ds:[__emuLast] ENDIF IF LDATA EQ false IFNDEF __TINY__ ; Check for null pointers before exit xor ax, ax mov si, ax mov cx, lgth_CopyRight cld ComputeChecksum label near add al, [si] adc ah, 0 inc si loop ComputeChecksum sub ax, CheckSum jz ExitToDOS mov cx, lgth_NullCheck mov dx, offset DGROUP: NullCheck call ErrorDisplay ENDIF ENDIF ; Exit to DOS ExitToDOS label near mov bp,sp mov ah,4Ch mov al,[bp+cPtrSize] int 21h ; Exit to DOS EndProc@@ _exit, __CDECL__ STARTX ENDP SUBTTL Vector save/restore & default Zero divide routines PAGE ;[]------------------------------------------------------------[] ;| | ;| Interrupt Save/Restore routines and default divide by zero | ;| handler. | ;| | ;[]------------------------------------------------------------[] ZeroDivision PROC FAR mov cx, lgth_ZeroDivMSG mov dx, offset DGROUP: ZeroDivMSG jmp MsgExit3 ZeroDivision ENDP ;-------------------------------------------------------------------------- ; savevectors() ; ; Save vectors for 0, 4, 5 & 6 interrupts. This is for extended ; signal()/raise() support as the signal functions can steal these ; vectors during runtime. ;-------------------------------------------------------------------------- SaveVectors PROC NEAR push ds ; Save INT 0 mov ax, 3500h int 021h mov word ptr _Int0Vector@@, bx mov word ptr _Int0Vector@@+2, es ; Save INT 4 mov ax, 3504h int 021h mov word ptr _Int4Vector@@, bx mov word ptr _Int4Vector@@+2, es ; Save INT 5 mov ax, 3505h int 021h mov word ptr _Int5Vector@@, bx mov word ptr _Int5Vector@@+2, es ; Save INT 6 mov ax, 3506h int 021h mov word ptr _Int6Vector@@, bx mov word ptr _Int6Vector@@+2, es ; ; Install default divide by zero handler. ; mov ax, 2500h mov dx, cs mov ds, dx mov dx, offset ZeroDivision int 21h pop ds ret SaveVectors ENDP ;-------------------------------------------------------------------------- ; restorezero() puts back all the vectors that SaveVectors took. ; ;NOTE : TSRs must BE AWARE that signal() functions which take these ; vectors will be deactivated if the keep() function is executed. ; If a TSR wants to use the signal functions when it is active it ; will have to save/restore these vectors itself when activated and ; deactivated. ;-------------------------------------------------------------------------- PubProc@@ _restorezero, __CDECL__ IFDEF __HUGE__ push ds mov ds, cs: DGROUP@@@@ ENDIF push ds mov ax, 2500h lds dx, _Int0Vector@@ int 21h pop ds push ds mov ax, 2504h lds dx, _Int4Vector@@ int 21h pop ds push ds mov ax, 2505h lds dx, _Int5Vector@@ int 21h pop ds IFNDEF __HUGE__ push ds ENDIF mov ax, 2506h lds dx, _Int6Vector@@ int 21h pop ds ret EndProc@@ _restorezero, __CDECL__ SUBTTL Miscellaneous PAGE ;[]------------------------------------------------------------[] ;| | ;| Miscellaneous functions | ;| | ;[]------------------------------------------------------------[] IFNDEF __NOFLOAT__ NoEmulator PROC FAR mov _8087@@, 0 ret NoEmulator ENDP ENDIF IFNDEF __OLDCONIO__ Proc@@ NoConsole, __CDECL__ ret EndProc@@ NoConsole, __CDECL__ ENDIF ErrorDisplay PROC NEAR mov ah, 040h mov bx, 2 int 021h ret ErrorDisplay ENDP PubProc@@ abort, __CDECL__ mov cx, lgth_abortMSG mov dx, offset DGROUP: abortMSG MsgExit3 label near mov ds, cs: DGROUP@@@@ call ErrorDisplay CallExit3 label near mov ax, 3 push ax call _exit@@ ; _exit(3); EndProc@@ abort, __CDECL__ ; The DGROUP@@ variable is used to reload DS with DGROUP PubSym@@ DGROUP@@, , __PASCAL__ _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 ; The CopyRight string must NOT be moved or changed without ; changing the null pointer check logic CopyRight db 4 dup(0) db 'Turbo-C - Copyright (c) 1988 Borland Intl.',0 lgth_CopyRight equ $ - CopyRight IF LDATA EQ false IFNDEF __TINY__ CheckSum equ 00D37h NullCheck db 'Null pointer assignment', 13, 10 lgth_NullCheck equ $ - NullCheck ENDIF ENDIF ZeroDivMSG db 'Divide error', 13, 10 lgth_ZeroDivMSG equ $ - ZeroDivMSG abortMSG db 'Abnormal program termination', 13, 10 lgth_abortMSG equ $ - abortMSG ; ; Interrupt vector save areas ; ; Interrupt vectors 0,4,5 & 6 are saved at startup and then restored ; when the program terminates. The signal/raise functions might ; steal these vectors during execution. ; PubSym@@ _Int0Vector
, __CDECL__ PubSym@@ _Int4Vector
, __CDECL__ PubSym@@ _Int5Vector
, __CDECL__ PubSym@@ _Int6Vector
, __CDECL__ ; ; Miscellaneous variables ; PubSym@@ _argc, , __CDECL__ dPtrPub@@ _argv, 0, __CDECL__ dPtrPub@@ environ, 0, __CDECL__ PubSym@@ _envLng, , __CDECL__ PubSym@@ _envseg, , __CDECL__ PubSym@@ _envSize, , __CDECL__ PubSym@@ _psp, , __CDECL__ PubSym@@ _version,
, __CDECL__ PubSym@@ _brklvl,
, __CDECL__ PubSym@@ _heaptop,
, __CDECL__ IF LDATA EQ false IFNDEF __NOFLOAT__ ; Emulator variables INCLUDE emuvars.asi ENDIF ENDIF _DATA ENDS IFNDEF __NOFLOAT__ _EMUSEG SEGMENT __emu1st dw NoEmulator __emuLast dw NoEmulator _EMUSEG ENDS ENDIF IFNDEF __OLDCONIO__ _CRTSEG SEGMENT __crt1st dw NoConsole@@ _CRTSEG ENDS ENDIF _CVTSEG SEGMENT PubSym@@ _RealCvtVector,