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