home *** CD-ROM | disk | FTP | other *** search
- 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 ; Der Emulator simuliert nicht
- ; alle Details des 8087
-
- ; Segment- und Group-Deklarationen
-
- _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
-
- ; Extern-Bezüge
-
- 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
- ;/* */
- ;/*-----------------------------------------------------*/
- ;/* */
- ;/* Startcode */
- ;/* --------- */
- ;/* */
- ;/*-----------------------------------------------------*/
- ;/* */
- PSPHigh equ 00002h
- PSPEnv equ 0002ch
- PSPCmd equ 00080h
-
- IFDEF __NOFLOAT__
- MINSTACK equ 128 ; Minimal-Stackgröße 0x100 Bytes
- ELSE
- MINSTACK equ 256 ; Minimal-Stackgröße 0x200 Bytes
- ENDIF
- ;
- ; Beim Start des Programms zeigen ES und DS auf das PSP.
- ; SS zeigt auf das Stacksegment (außer im Modell TINY - dort
- ; sind Stack- und Codesegment identisch)
- ;
- _TEXT SEGMENT
- IFDEF __TINY__
- ORG 100h
- ENDIF
- STARTX PROC NEAR
- ; Sichern allgemeiner Informationen, wie:
- ; DGROUP-Segmentadresse
- ; DOS-Versionsnummer
- ; Programmsegment-Präfix
- ; Environment-Startadresse
- ; Obergrenze des Speichers
-
- IFDEF __TINY__
- mov dx, cs ; DX = GROUP-Segmentadresse
- ELSE
- mov dx, DGROUP ; DX = GROUP-Segmentadresse
- ENDIF
- mov cs:DGROUP@@, dx
-
- mov ah, 30h ; "Get Version Number"
- int 21h
- mov bp, ds:[PSPHigh]; RamTop -> BP
- mov bx, ds:[PSPEnv] ; Environment-Segmentadresse -> BX
- mov ds, dx ; DS auf _DATA (bzw. CS für TINY)
-
- mov _version@, ax ; DOS-Version -> globale Variable
- mov _psp@, es ; Programmsegment-Präfix
- mov _envseg@, bx ; Environment-Segmentadresse
- mov word ptr _heaptop@ + 2, bp
- mov _8087@, -1
- ;
- ; Speichern diverser Interrupt-Vektoren (incl. Division durch 0)
- ;
- call SaveVectors ; INT-Vektoren 0, 4..6
-
- ; Suche nach einer Environment-Variablen '87'. In dieser Schleife
- ; wird gleichzeitig die Anzahl der Einträge und der gesamte Platz-
- ; bedarf des Environments bestimmt-
- ; Jeder Eintrag wird mit einem NUL-Zeichen beendet; ein Eintrag
- ; der Länge 0 markiert das Tabellenende. Die gesamte Tabelle kann
- ; NICHT größer als 32 KByte sein.
-
- les di, dword ptr _envLng@ ; _envseg:0000
- mov ax, di ; = 00
- mov bx, ax ; Eintragszähler = 0
- mov cx, 07FFFh ; Maximalgröße: 32767 Bytes
- IsIt87Var label near
- cmp word ptr es:[di], '78' ; umgedreht: "87"
- jne GetVarLng ; -> nächste Variable
- mov dx, es:[di+2] ; "87" gefunden. Nächstes Zeichen '='?
- cmp dl, '='
- jne GetVarLng
- and dh, not ' ' ; ja! -> Großbuchstaben
- inc _8087@ ; _8087 = 0
- cmp dh, 'Y' ; folgt ein 'Y'?
- jne GetVarLng
- inc _8087@ ; ja - _8087 = 1
- GetVarLng label near
- repnz scasb ; Suche nach NUL-Zeichen
- jcxz InitFailed ; Environment > 32 KByte -> Abbruch
- inc bx ; Eintragzähler ++
- cmp es:[di], al ; zweites NUL-Zeichen?
- jne IsIt87Var ; nein, nächster Eintrag
-
- or ch, 10000000b ; = 32768 - CX
- neg cx
- mov _envLng@, cx ; Environment-Länge
- mov cx, dPtrSize / 2 ; Berechnung der Array-Größe:
- shl bx, cl ; Eintragszahl * Zeigergröße
- add bx, dPtrSize * 4 ; < Aufrundung >
- and bx, not ((dPtrSize * 4) - 1)
- mov _envSize@, bx ; Anzahl Env.-Einträge
-
- ; Wieviel Paragraphs braucht das Programm tatsächlich von DOS?
-
- IF LDATA ; eigenes Stacksegment?
- mov dx, ss ; ja: RamTop - Stacksegment
- sub bp, dx ; = freier Platz
- IFDEF __HUGE__
- mov di, seg _stklen@
- mov es, di
- mov di, es:_stklen@ ; _stklen -> DI
- ELSE
- mov di, _stklen@ ; dito für COMPACT & LARGE
- ENDIF
- ;
- ; LDATA: Stackgröße nach unten auf MINSTACK begrenzen
- ;
- cmp di, 2*MINSTACK ; _stklen >= MINSTACK (0x200 Bytes)?
- jae AskedStackOK
- mov di, 2*MINSTACK ; nein, 0x0200 Bytes einsetzen
- IFDEF __HUGE__
- mov es:_stklen@, di ; und _stklen neu setzen
- ELSE
- mov _stklen@, di ; dito für COMPACT & LARGE
- ENDIF
- AskedStackOK label near
- mov cl, 4
- shr di, cl ; Stackgröße -> Paragraphs
- inc di ; (Aufrundung)
- cmp bp, di ; freier Platz > Stackgröße?
- jnb ExcessOfMemory ; ja
-
- ELSE ; kein eigenes Stacksegment
- mov dx, ds
- sub bp, dx ; RamTop - DS -> freier Platz
- mov di, _stklen@ ; _stklen -> DI
- ;
- ; SMALL DATA: Stackgröße nach unten auf MINSTACK begrenzen
- ;
- cmp di, 2*MINSTACK ; _stklen >= MINSTACK (0x0200 Bytes)?
- jae AskedStackOK
- mov di, 2*MINSTACK ; nein, 0x0200 Bytes einsetzen
- mov _stklen@, di ; und neuer Wert für _stklen
-
- AskedStackOK label near
- add di, offset DGROUP: edata@ ; DS-Ende (= _BSSEND)
- jb InitFailed ; Oha! DSeg > 64 KBytes
- add di, _heaplen@ ; + Heapgröße
- jb InitFailed ; -> 64 KBytes
- mov cl, 4
- shr di, cl ; Umrechnung in Paragraphs
- inc di ; (Aufrundung)
- cmp bp, di
- jb InitFailed ; Nicht genug Speicher!
-
- cmp _stklen@, 0 ; (?? ("never"))
- je ExpandDS
- cmp _heaplen@, 0 ; Standardvorgabe für _heaplen?
- jne ExcessOfMemory ; nein - berechnete Größe setzen
-
- ExpandDS label near
- mov di, 1000h ; Vergrößerung DS auf 64 KByte
- cmp bp, di ; immer noch genug Platz?
- ja ExcessOfMemory ; -> ja
- mov di, bp ; nein, Begrenzung
- jmp short ExcessOfMemory
- ENDIF
-
- ; Alle Initialisierungsfehler führen zu einem Sprung hierher
-
- InitFailed label near
- jmp near ptr abort@
-
- ; Rückgabe der nicht benötigten Segmente an DOS
- ; Setzen des "Far Heap"-Beginns
-
- ExcessOfMemory label near
- mov bx, di ; Größe von Daten- bzw. Stacksegment
- add bx, dx ; + Datensegment bzw. Stacksegment
- mov word ptr _heapbase@ + 2, bx ; => Beginn des FAR HEAP
- mov word ptr _brklvl@ + 2, bx ; => 1. freie Speicherzelle
- mov ax, _psp@ ; Programmstart
- sub bx, ax ; Prog-Endadresse - PSP = Prog-Größe
- mov es, ax ; PSP -> ES (Beginn des Speicherblocks)
- mov ah, 04Ah ; "Modify allocated memory"
- push di ;
- int 021h ; this call clobbers SI,DI,BP !!!!!!
- pop di
- ;
- ; Setzen des Programmstacks. Falls wir hier in der Mitte unterbrochen
- ; würden, wären die Ergebnisse katastrophal - deshalb werden Interrupts
- ; zeitweilig unterdrückt.
- ;
- shl di, cl ; CL enthält immer noch den Wert 4
-
- cli
- mov ss, dx ; IF LDATA: DX=_STACK ELSE DX=_DATA
- mov sp, di ; DI = Stack-Ende
- sti
-
- IFNDEF __HUGE__
-
- ; Uninitialisierte Daten ("_BSS") auf 0
-
- xor ax, ax
- mov es, cs:DGROUP@@ ; Ziel-Segment: _DATA
- mov di, offset DGROUP: bdata@ ; Start: _BSS
- mov cx, offset DGROUP: edata@ ; Ende: _BSSEND
- sub cx, di
- rep stosb ; _BSS-Inhalt auf 0
- ENDIF
-
- IFNDEF __NOFLOAT__
-
- ; Initialisierung des Emulators
-
- push cs ; Routine _emu1st endet mit RETF
- call ds:[__emu1st]
- ENDIF
-
- ; Vorbereitung der Argumente von main()
-
- call _setargv@ ; PSP.CmdLine -> argv[]
- call _setenvp@ ; Environment -> envp[]
-
- mov ah, 0
- int 1ah ; "BIOS-Ticks"
- mov word ptr _StartTime@,dx ; speichern für clock()
- mov word ptr _StartTime@+2,cx
-
- IFNDEF __OLDCONIO__
- IF LPROG
- push cs ; in den Modellen MEDIUM, LARGE und
- ; HUGE endet _c0crtinit mit RETF
- ENDIF
- call ds:[__crt1st] ; Initialisierung von conio
- ENDIF
-
- ; ExitCode = main(argc,argv,envp);
-
- IF LDATA
- push word ptr environ@+2 ; envp und argv als FAR-Zeiger
- push word ptr environ@
- push word ptr _argv@+2 ; auf den Stack
- push word ptr _argv@
- ELSE
- push word ptr environ@ ; sonst als NEAR-Zeiger
- push word ptr _argv@
- ENDIF
- push _argc@ ; argc als letztes
- call main@
-
- ; Programmende
-
- push ax ; Ergebnis von main()
- call exit@ ; "Aufruf" von exit()
-
- ;---------------------------------------------------------------------------
- ; _exit()
- ;
- ; Zurücksetzen der INT-Vektoren 0, 4..6 (von signal())
- ;
- ; Prüfung auf NULL-Zeiger
- ;
- ; Rücksprung zu DOS
- ;
- ;HINWEIS: exit() schließt keine offenen Dateien!
- ;---------------------------------------------------------------------------
- PubProc@ _exit, __CDECL__
- mov ds, cs:DGROUP@@
-
- IF LPROG
- call far ptr _restorezero@ ; INT-Vektoren zurück
- ELSE
- call near ptr _restorezero@ ; dito für kleine Codemodelle
- ENDIF
-
- IFNDEF __NOFLOAT__
-
- ; Emulator-Vektoren zurück
-
- push cs ; _emuLast endet immer mit RETF
- call ds:[__emuLast]
- ENDIF
-
- IF LDATA EQ false
- IFNDEF __TINY__
-
- ; Prüfung auf NULL-Zeiger
-
- xor ax, ax
- mov si, ax
- mov cx, lgth_CopyRight
- cld
- ComputeChecksum label near ; Aufaddieren von
- add al, [si] ; "Turbo-C Copyright Borland..."
- adc ah, 0
- inc si
- loop ComputeChecksum
- sub ax, CheckSum
- jz ExitToDOS ; Copyright unverändert
- mov cx, lgth_NullCheck
- mov dx, offset DGROUP: NullCheck
- call ErrorDisplay ; "Null pointer assignment"
- ENDIF
- ENDIF
-
- ; Rücksprung zu DOS
-
- ExitToDOS label near
- mov bp,sp
- mov ah,4Ch ; DOS-Funktionsnummer: Terminate
- mov al,[bp+cPtrSize] ; <- Ergebnis von main()
- int 21h ; "Terminate Process"
- EndProc@ _exit, __CDECL__
- STARTX ENDP
-
- SUBTTL Vector save/restore & default Zero divide routines
- PAGE
- ;[]------------------------------------------------------------[]
- ;| |
- ;| Speichern/Zurücksetzen von Interrupt-vektoren und die |
- ;| Standard-Behandlungsroutine für Divisionen durch Null |
- ;| |
- ;[]------------------------------------------------------------[]
-
- ZeroDivision PROC FAR
- mov cx, lgth_ZeroDivMSG
- mov dx, offset DGROUP: ZeroDivMSG
- jmp MsgExit3
- ZeroDivision ENDP
-
- ;--------------------------------------------------------------------------
- ; savevectors()
- ;
- ; Speichert die Vektoren 0, 4, 5 und 6 für die erweiterten Versionen
- ; signal() und raise(), die diese Vektoren zur Laufzeit belegen können.
- ;--------------------------------------------------------------------------
- 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
- ;
- ; Installation der Standardroutine für Divisionen durch Null
- ;
- mov ax, 2500h
- mov dx, cs
- mov ds, dx
- mov dx, offset ZeroDivision
- int 21h
-
- pop ds
- ret
- SaveVectors ENDP
-
- ;--------------------------------------------------------------------------
- ; restorezero() setzt alle Interruptvektoren auf die Originale zurück
- ;
- ;HINWEIS: TSR-Programme müssen die Vektoren 4..6 selbst speichern, wenn
- ; sie signal()/raise() verwenden wollen - die entsprechenden
- ; Vektoren werden von exit bzw. keep zurückgesetzt!
- ;--------------------------------------------------------------------------
- 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
- ;[]------------------------------------------------------------[]
- ;| |
- ;| Diverses |
- ;| |
- ;[]------------------------------------------------------------[]
-
- 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__
-
- ; Die Variable DGROUP@ wird ausschließlich zum Setzen von DS
- ; auf das Datensegment des Programms verwendet
-
- PubSym@ DGROUP@, <dw ?>, __PASCAL__
- _TEXT ENDS
-
- SUBTTL Start Up Data Area
- PAGE
- ;[]------------------------------------------------------------[]
- ;| Datendefinitionen des Startcodes |
- ;| |
- ;| WARNUNG Veränderungen und sogar Umstellungen |
- ;| der Deklarations-Reihenfolge können |
- ;| hier merkwürdige Effekte zeitigen |
- ;| |
- ;[]------------------------------------------------------------[]
-
- _DATA SEGMENT
-
- ; CopyRight *muß* an dieser Stelle definiert sein und darf
- ; nicht verändert werden - sonst klappt die Prüfung via
- ; exit() nicht mehr.
-
- 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
-
- ;
- ; Speicherbereiche für Interrupt-Vektoren
- ;
- ; Die Vektoren 0,4,5 & 6 werden beim Programmstart hier gespeichert,
- ; zur Laufzeit von signal()/raise() verändert bzw. benutzt und und
- ; via exit() wieder gesetzt.
- ;
- PubSym@ _Int0Vector <dd 0>, __CDECL__
- PubSym@ _Int4Vector <dd 0>, __CDECL__
- PubSym@ _Int5Vector <dd 0>, __CDECL__
- PubSym@ _Int6Vector <dd 0>, __CDECL__
- ;
- ; Diverse Variablen
- ;
- PubSym@ _argc, <dw 0>, __CDECL__
- dPtrPub@ _argv, 0, __CDECL__
- dPtrPub@ environ, 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@ _8087, <dw 0>, __CDECL__
- PubSym@ _StartTime, <dw 0,0>, __CDECL__
-
-
- ; Speicherlayout und -verwaltung
-
- IF LDATA EQ false
- PubSym@ __heapbase, <dw DGROUP:edata@>, __CDECL__
- PubSym@ __brklvl, <dw DGROUP:edata@>, __CDECL__
- PubSym@ __heaptop, <dw DGROUP:edata@>, __CDECL__
- ENDIF
- PubSym@ _heapbase, <dd 0>, __CDECL__
- PubSym@ _brklvl, <dd 0>, __CDECL__
- PubSym@ _heaptop, <dd 0>, __CDECL__
-
- IF LDATA EQ false
- IFNDEF __NOFLOAT__
- ; Emulator-Variablen
- 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, <label word>, __CDECL__
- _CVTSEG ENDS
-
- _SCNSEG SEGMENT
- PubSym@ _ScanTodVector, <label word>, __CDECL__
- _SCNSEG ENDS
-
- IFNDEF __HUGE__
- _BSS SEGMENT
- bdata@ label byte
- _BSS ENDS
-
- _BSSEND SEGMENT
- edata@ label byte
- _BSSEND ENDS
- ENDIF
-
- IFNDEF __TINY__
- _STACK SEGMENT
- dw 64 dup (?)
- IF LDATA
- org 0
- IFNDEF __NOFLOAT__
- ; Emulator-Variablen
- INCLUDE emuvars.asi
- even
- ENDIF
- PUBLIC emuTop@ ; für Stack-Unterlauf-Prüfung
- emuTop@ label byte
- ENDIF
- _STACK ENDS
- ENDIF
- END STARTX