-
Notifications
You must be signed in to change notification settings - Fork 0
/
C0.ASM
841 lines (724 loc) · 27.2 KB
/
C0.ASM
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
NAME c0
PAGE 60,132
LOCALS
;[]------------------------------------------------------------[]
;| C0.ASM -- Start Up Code |
;| |
;| Turbo C++ Run Time Library |
;| |
;| Copyright (c) 1987, 1991 by Borland International Inc. |
;| All Rights Reserved. |
;[]------------------------------------------------------------[]
__C0__ = 1
INCLUDE RULES.ASI
; Segment and Group declarations
_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 _exit:DIST
extrn __exit:DIST
extrn __nfile:word
extrn __setupio:near ;required!
extrn __stklen:word
IF LDATA EQ false
extrn __heaplen:word
ENDIF
SUBTTL Start Up Code
PAGE
;/* */
;/*-----------------------------------------------------*/
;/* */
;/* Start Up Code */
;/* ------------- */
;/* */
;/*-----------------------------------------------------*/
;/* */
PSPHigh equ 00002h
PSPEnv equ 0002ch
PSPCmd equ 00080h
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__
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
IFNDEF __BOSS__
mov cs:DGROUP@@, dx ; __BOSS__
ENDIF
mov ah, 30h
int 21h ; get DOS version number
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
;
; Save several vectors and install default divide by zero handler.
;
call SaveVectors
;===================
;
; IDsoft - Check to make sure that we're running on a 286 or better
pushf ; Save original flags
xor ax,ax ; Clear AX
push ax
popf ; Try to pop the 0
pushf
pop ax ; Get results of popping 0 into flags
popf ; Restore original flags
or ax,ax
jns @@Have286 ; If no sign bit, have a 286
mov cx, lgth_no286MSG
mov dx, offset DGROUP: no286MSG
jmp MsgExit3
@@Have286:
; IDsoft - End of modifications (there's also a code segment string)
;
;===================
IFDEF __BOSS__
; Determine if in real mode
mov ax,0FB42h ; find out if DPMI loader is here
mov bx,1 ; get info function
int 2fh ;
push ax ;
mov ax, cs ; now, save DGROUP
add ax, cx ;
mov es, ax ;
mov dx, ds ;
mov es:DGROUP@@, dx ;
mov es:CSalias@@, ax ;
pop ax ;
; cmp ax,0001h ; if not "TRUE"
; JNE InRealMode
; 8 is the value of the alias selector
; in this system
MOV _protected@, cx
MOV _hugeincval@, cx
clc
mov ax, cx
xor cx, cx
or ax, ax
je @@gotshift
@@shiftcnt:
rcr ax,1
jc @@gotshift
inc cx
jmp @@shiftcnt
@@gotshift:
mov _shiftcount@,cx
; used by emulator
; PUSH DS
; MOV AX, 0E502H ; prot kernel function, get LDT alias
; INT 21H
; POP DS
; MOV _LDT@, AX
; cmp _protected@,0001h ; if not "TRUE"
; JNE InRealMode
.286P
IFE LDATA
mov dx, ds ;
; LSL AX, DX ;
; DEC AX ;
MOV AX, 0FFFEh ;
MOV SP, AX ;
MOV SS, DX ;
ENDIF
.8086
; JMP BossSkip
InRealMode label near
ENDIF
; Count the number of environment variables and compute the 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
cld
@@EnvLoop:
repnz scasb
jcxz InitFailed ; Bad environment !!!
IFDEF __BOSS__
jmp InitOK
InitFailed: jmp near ptr _abort
InitOK:
ENDIF
inc bx ; BX = Nb environment variables
cmp es:[di], al
jne @@EnvLoop ; 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.
IFNDEF __BOSS__
; Determine the amount of memory that we need to keep
IFDEF _DSSTACK_
mov dx, ds
ELSE
mov dx, ss
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
; 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
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
IFNDEF _DSSTACK_
mov ax, seg __stklen
mov es, ax
mov es:__stklen, di ; If separate stack segment, save size
ENDIF
ENDIF ; __BOSS__
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
; If default number of file handles have changed then tell DOS
cmp __nfile, 20
jbe @@NoChange
cmp _osmajor@, 3 ; Check for >= DOS 3.3
jb @@NoChange
ja @@DoChange
cmp _osminor@, 1Eh
jb @@NoChange
@@DoChange:
mov ax, 5801h ; Set last fit allocation
mov bx, 2
int 21h
jc @@BadInit
mov ah, 67h ; Expand handle table
mov bx, __nfile
int 21h
jc @@BadInit
mov ah, 48h ; Allocate 16 bytes to find new
mov bx, 1 ; top of memory address
int 21h
jc @@BadInit
inc ax ; Adjust address to point after block
mov word ptr _heaptop@ + 2, ax
dec ax ; Change back and release block
mov es, ax
mov ah, 49h
int 21h
jc @@BadInit
mov ax, 5801h ; Set first fit allocation
mov bx, 0
int 21h
jnc @@NoChange
@@BadInit: jmp near ptr _abort
@@NoChange:
; Prepare main arguments
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
or al,al ; was midnight flag set?
jz @@NotMidnight
mov ax,40h ; set BIOS midnight flag
mov es,ax ; at 40:70
mov bx,70h
mov byte ptr es:[bx],1
@@NotMidnight:
xor bp,bp ; set BP to 0 for overlay mgr
mov es, cs:DGROUP@@
mov si,offset DGROUP:InitStart ;si = start of table
mov di,offset DGROUP:InitEnd ;di = end of table
call StartExit
; ExitCode = main(argc,argv,envp);
IF LDATA
push word ptr __C0environ+2
push word ptr __C0environ
push word ptr __C0argv+2
push word ptr __C0argv
ELSE
push word ptr __C0environ
push word ptr __C0argv
ENDIF
push __C0argc
call _main
; Flush and close streams and files
push ax
call _exit
;---------------------------------------------------------------------------
; _cleanup() call all #pragma exit cleanup routines.
; _checknull() check for null pointer zapping copyright message
; _terminate(int) exit program with error code
;
; These functions are called by exit(), _exit(), _cexit(),
; and _c_exit().
;---------------------------------------------------------------------------
; Call cleanup routines
__cleanup PROC DIST
PUBLIC __cleanup
mov es, cs:DGROUP@@
push si
push di
mov si,offset DGROUP:ExitStart
mov di,offset DGROUP:ExitEnd
call StartExit
pop di
pop si
ret
__cleanup ENDP
; Check for null pointers before exit
__checknull PROC DIST
PUBLIC __checknull
IF LDATA EQ false
IFNDEF __TINY__
push si
push di
mov es, cs:DGROUP@@
xor ax, ax
mov si, ax
mov cx, lgth_CopyRight
ComputeChecksum label near
add al, es:[si]
adc ah, 0
inc si
loop ComputeChecksum
sub ax, CheckSum
jz @@SumOk
mov cx, lgth_NullCheck
mov dx, offset DGROUP: NullCheck
call ErrorDisplay
@@SumOK: pop di
pop si
ENDIF
ENDIF
ret
__checknull ENDP
; Exit to DOS
__terminate PROC DIST
PUBLIC __terminate
mov bp,sp
mov ah,4Ch
mov al,[bp+cPtrSize]
int 21h ; Exit to DOS
__terminate 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
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.
;--------------------------------------------------------------------------
__restorezero PROC DIST
PUBLIC __restorezero
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
ENDP
;------------------------------------------------------------------
; Loop through a startup/exit (SE) table,
; calling functions in order of priority.
; ES:SI is assumed to point to the beginning of the SE table
; ES: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: cmp si,offset DGROUP:InitStart ; startup or exit?
je @@StartLow ; it's startup
xor ah,ah ; start with high priority
jmp short @@SaveEnd
@@StartLow: mov ah,0ffh ;start with lowest priority
@@SaveEnd: 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 es:[bx.calltype],NOTUSED;check the call type
je @@Next
cmp si,offset DGROUP:InitStart ; startup or exit?
je @@CompareHigh ; it's startup
cmp ah,es:[bx.priority] ; it's exit
jmp short @@CheckPrior ; if priority too low, skip
@@CompareHigh: cmp es:[bx.priority],ah ;check the priority
@@CheckPrior: ja @@Next ;too high? skip
mov ah,es:[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
cmp es:[bx.calltype],PNEAR ;is it near or far?
mov es:[bx.calltype],NOTUSED;wipe the call type
push es ;save es
je @@NearCall
@@FarCall: call DWORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@NearCall: call WORD PTR es:[bx.addrlow]
pop es ;restore es
jmp short @@Start
@@Done: ret
endp
;------------------------------------------------------------------
ErrorDisplay PROC NEAR
mov ah, 040h
mov bx, 2
int 021h
ret
ErrorDisplay ENDP
_abort PROC DIST
PUBLIC _abort
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);
ENDP
; The DGROUP@ variable is used to reload DS with DGROUP
PubSym@ DGROUP@, <dw ?>, __PASCAL__
IFDEF __BOSS__
PubSym@ CSalias@,<dw ?>, __PASCAL__
ENDIF
; __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
; The CopyRight string must NOT be moved or changed without
; changing the null pointer check logic
CopyRight db 4 dup(0)
db 'Borland C++ - Copyright 1991 Borland Intl.',0
lgth_CopyRight equ $ - CopyRight
IF LDATA EQ false
IFNDEF __TINY__
CheckSum equ 00D5Ch
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
; JAB - Added string for no 286
no286MSG db 'Sorry, this program requires a 286 or better.', 13, 10
lgth_no286MSG equ $ - no286MSG
; JAB - End of modifications
;
; 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.
;
; Note: These vectors save area must not be altered
; without changing the save/restore logic.
;
PubSym@ _Int0Vector <dd 0>, __CDECL__
PubSym@ _Int4Vector <dd 0>, __CDECL__
PubSym@ _Int5Vector <dd 0>, __CDECL__
PubSym@ _Int6Vector <dd 0>, __CDECL__
;
; 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@ _osversion, <label word>, __CDECL__
PubSym@ _osmajor, <db 0>, __CDECL__
PubSym@ _osminor, <db 0>, __CDECL__
PubSym@ errno, <dw 0>, __CDECL__
PubSym@ _StartTime, <dw 0,0>, __CDECL__
IFDEF __BOSS__
PubSym@ _protected <dw 0>, __CDECL__
PubSym@ _shiftcount, <dw 12>, __CDECL__
PubSym@ _hugeincval, <dw 1000h>, __CDECL__
ENDIF
; Memory management variables
IF LDATA EQ false
PubSym@ __heapbase, <dw DGROUP:edata@>, __CDECL__
ENDIF
IFNDEF __HUGE__
PubSym@ __brklvl, <dw DGROUP:edata@>, __CDECL__
ENDIF
PubSym@ _heapbase, <dd 0>, __CDECL__
PubSym@ _brklvl, <dd 0>, __CDECL__
PubSym@ _heaptop, <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
IFDEF __BOSS__
IF LDATA
db 1400h dup(?)
ENDIF
ELSE
db 128 dup(?) ;minimum stack size
ENDIF ; __BOSS__
ENDS
ENDIF ; __TINY__
END STARTX