|
|
1.1 ! root 1: page ,132 ! 2: TITLE crt0dat - DOS and Windows shared startup and termination ! 3: ;*** ! 4: ;crt0dat.asm - DOS and Windows shared startup and termination ! 5: ; ! 6: ; Copyright (c) 1985-1987, Microsoft Corporation. All rights reserved. ! 7: ; ! 8: ;Purpose: ! 9: ; Shared startup and termination. ! 10: ; ! 11: ;******************************************************************************* ! 12: ! 13: _NFILE_ = 20 ; Maximum number of file handles ! 14: ! 15: ?DF = 1 ;; tell cmacros.inc we want to define our own segments ! 16: ! 17: include version.inc ! 18: .xlist ! 19: ifdef _QC ;[8] Move these includes out of version.inc ! 20: include \sl\qc\src\include\kernel.inc ;[8] ! 21: include \sl\qc\src\include\kmac.inc ;[8] ! 22: endif ;_QC ;[8] ! 23: ! 24: include cmacros.inc ! 25: include msdos.inc ! 26: .list ! 27: ! 28: ifdef _QC ! 29: BEGINT equ 34h ;First EM.LIB interrupt vector. ! 30: NUMVEC equ 11 ;Uses 11 actual vectors. ! 31: endif ;_QC ! 32: ! 33: createSeg _TEXT, code, word, public, CODE, <> ! 34: createSeg CDATA, cdata, word, common, DATA, DGROUP ! 35: createSeg _DATA, data, word, public, DATA, DGROUP ! 36: ! 37: ifndef IBMC20 ! 38: createSeg XIFB, xifbseg, word, public, DATA, DGROUP ! 39: createSeg XIF, xifseg, word, public, DATA, DGROUP ; far init's ! 40: createSeg XIFE, xifeseg, word, public, DATA, DGROUP ! 41: endif ;IBMC20 ! 42: ! 43: createSeg XIB, xibseg, word, public, DATA, DGROUP ! 44: createSeg XI, xiseg, word, public, DATA, DGROUP ; init's ! 45: createSeg XIE, xieseg, word, public, DATA, DGROUP ! 46: ! 47: createSeg XOB, xobseg, word, public, BSS, DGROUP ! 48: createSeg XO, xoseg, word, public, BSS, DGROUP ; onexit table ! 49: createSeg XOE, xoeseg, word, public, BSS, DGROUP ! 50: ! 51: createSeg XPB, xpbseg, word, public, DATA, DGROUP ! 52: createSeg XP, xpseg, word, public, DATA, DGROUP ; preterm's ! 53: createSeg XPE, xpeseg, word, public, DATA, DGROUP ! 54: ! 55: createSeg XCB, xcbseg, word, public, DATA, DGROUP ! 56: createSeg XC, xcseg, word, public, DATA, DGROUP ; term's ! 57: createSeg XCE, xceseg, word, public, DATA, DGROUP ! 58: ! 59: ifndef IBMC20 ! 60: createSeg XCFB, xcfbseg, word, public, DATA, DGROUP ! 61: createSeg XCF, xcfseg, word, public, DATA, DGROUP ; far term's ! 62: createSeg XCFE, xcfeseg, word, public, DATA, DGROUP ! 63: endif ;IBMC20 ! 64: ! 65: defGrp DGROUP ;; define DGROUP ! 66: ! 67: codeOFFSET equ offset _TEXT: ! 68: dataOFFSET equ offset DGROUP: ! 69: ! 70: page ! 71: ifndef IBMC20 ! 72: sBegin xifbseg ! 73: xifbegin label byte ! 74: sEnd xifbseg ! 75: ! 76: sBegin xifeseg ! 77: xifend label byte ! 78: sEnd xifeseg ! 79: endif ;IBMC20 ! 80: ! 81: sBegin xibseg ! 82: xibegin label byte ! 83: sEnd xibseg ! 84: ! 85: sBegin xieseg ! 86: xiend label byte ! 87: sEnd xieseg ! 88: ! 89: sBegin xobseg ! 90: xontab label byte ; start of onexit table ! 91: sEnd xobseg ! 92: ! 93: sBegin xoeseg ! 94: xonend label byte ! 95: sEnd xoeseg ! 96: ! 97: sBegin xpbseg ! 98: xpbegin label byte ; end of onexit table ! 99: sEnd xpbseg ! 100: ! 101: sBegin xpeseg ! 102: xpend label byte ! 103: sEnd xpeseg ! 104: ! 105: sBegin xcbseg ! 106: xcbegin label byte ! 107: sEnd xcbseg ! 108: ! 109: sBegin xceseg ! 110: xcend label byte ! 111: sEnd xceseg ! 112: ! 113: ifndef IBMC20 ! 114: sBegin xcfbseg ! 115: xcfbegin label byte ! 116: sEnd xifbseg ! 117: ! 118: sBegin xcfeseg ! 119: xcfend label byte ! 120: sEnd xcfeseg ! 121: endif ;IBMC20 ! 122: ! 123: ifdef _QC ! 124: extrn $Exec_Shell:FAR ! 125: extrn $Terminate_QC:FAR ;[5] exit point for shell exits ! 126: extrn __fpsignal:FAR ! 127: extrn $EmulInit:FAR ;[6] ! 128: extrn $EmulTerm:FAR ;[6] ! 129: endif ;_QC ! 130: ! 131: sBegin cdata ; floating point setup segment ! 132: assumes ds,data ! 133: ! 134: dw 0 ; force segment to be at least 0's ! 135: labelD <PUBLIC,_fpinit> ; public for signal ! 136: fpmath dd 1 dup (?) ; linking trick for fp ! 137: fpdata dd 1 dup (?) ! 138: ifdef _QC ! 139: fpsignal dd __fpsignal ; fp signal message ! 140: else ;_QC ! 141: fpsignal dd 1 dup (?) ; fp signal message ! 142: endif ;_QC ! 143: ! 144: ifdef _QC ;[5] ! 145: staticB shellexit,0 ;[5] marker for special exit for shell ! 146: endif ;_QC ;[5] ! 147: ! 148: sEnd ! 149: ! 150: ifdef _QC ! 151: externP _Break_error ! 152: endif ;_QC ! 153: ! 154: sBegin data ! 155: assumes ds,data ! 156: ! 157: ; special C environment string ! 158: ! 159: labelB <PUBLIC,_acfinfo> ! 160: cfile db ';C_FILE_INFO' ! 161: cfilex db 0 ! 162: cfileln = cfilex-cfile ! 163: ! 164: ifdef _QC ! 165: globalD _abrkvec,0 ;[4]break interrupt vector ! 166: endif ;_QC ! 167: ! 168: globalD _aintdiv,0 ; divide error interrupt vector save ! 169: ! 170: globalQ _fac,0 ; floating accumulator ! 171: globalW errno,0 ; initial error code ! 172: globalW _umaskval,0 ; initial umask value ! 173: ! 174: ;=============== following must be in this order ! 175: ! 176: globalW _pspadr,0 ; psp:0 (far * to PSP segment) ! 177: globalW _psp,0 ; psp:0 (paragraph #) ! 178: ! 179: ;=============== above must be in this order ! 180: ! 181: ;=============== following must be in this order ! 182: ! 183: labelW <PUBLIC,_osversion> ! 184: labelB <PUBLIC,_dosvermajor> ! 185: globalB _osmajor,0 ! 186: labelB <PUBLIC,_dosverminor> ! 187: globalB _osminor,0 ! 188: ! 189: ;=============== above must be in this order ! 190: ! 191: ! 192: globalB _osmode,0 ; 0 = real mode ! 193: ! 194: labelW <PUBLIC,_oserr> ! 195: globalW _doserrno,0 ; initial DOS error code ! 196: ! 197: globalW _nfile,_NFILE_ ; maximum number of file handles ! 198: ! 199: labelB <PUBLIC,_osfile> ! 200: db 3 dup (FOPEN+FTEXT) ; stdin, stdout, stderr ! 201: db 2 dup (FOPEN) ; stdaux, stdprn ! 202: db _NFILE_-5 dup (0) ; the other 15 handles ! 203: ! 204: ! 205: globalW __argc,0 ! 206: globalDP __argv,0 ! 207: globalDP environ,0 ; environment pointer ! 208: ! 209: labelD <PUBLIC,_pgmptr> ; pointer to program name ! 210: dw dataOFFSET dos2nam,DGROUP ! 211: dos2nam db 'C',0 ; dummy argv[0] for DOS 2.X ! 212: ! 213: ! 214: ; signal related common data ! 215: ! 216: globalW _child,0 ; flag used to handle signals from child process ! 217: ! 218: ifndef _QC ;[XX] we don't do overlays ! 219: ifndef IBMC20 ! 220: ;Overlay related data ! 221: ! 222: globalB _ovlflag,0 ;Overlay flag (0 = no overlays) ! 223: globalB _intno,0 ;Overlay interrupt value (e.g., 3F) ! 224: globalD _ovlvec,0 ;Address of original overlay handler ! 225: endif ! 226: endif ;_QC ;[XX] we don't do overlays ! 227: ! 228: ifdef _QC ! 229: con db 'CON',0 ! 230: _fpsave dd NUMVEC dup (0) ! 231: endif ;_QC ! 232: ! 233: ifdef _QC ;[1] ! 234: ; DWORD pointer for runtime errors. Routines calling amsg_exit set this ! 235: ; to their 'best guess' for the CS:IP where the error occurred. amsg_exit ! 236: ; then uses this information to set up information for return to the shell. ! 237: ; [1] ! 238: ! 239: globalD _QCrtcsip, 0 ;[1] ! 240: endif ;_QC ;[1] ! 241: ! 242: sEnd data ! 243: ! 244: page ! 245: sBegin code ! 246: assumes cs,code ! 247: ! 248: if sizeC ! 249: global proc far ! 250: endif ! 251: ! 252: ifndef _QC ;[X] fptrap has vanished ! 253: externNP _fptrap ! 254: endif ;_QC ;[X] ! 255: externP _cintDIV ! 256: externP _nullcheck ! 257: ! 258: ifdef _QC ;[10] ! 259: extrn $F_PSP:WORD ;[10] ! 260: endif ;ifdef _QC ;[10] ! 261: ! 262: page ! 263: ;*** ! 264: ;_cinit - C initialization ! 265: ; ! 266: ;Purpose: ! 267: ; This routine performs the shared DOS and Windows initialization. ! 268: ; The following order of initialization must be preserved - ! 269: ; ! 270: ; 1. Integer divide interrupt vector setup ! 271: ; 2. Floating point initialization ! 272: ; 3. Copy ;C_FILE_INFO into _osfile ! 273: ; 4. Check for devices for file handles 0 - 4 ! 274: ; 5. General C initializer routines ! 275: ; ! 276: ;Entry: ! 277: ; ! 278: ;Exit: ! 279: ; ! 280: ;Uses: ! 281: ; ! 282: ;Exceptions: ! 283: ; ! 284: ;******************************************************************************* ! 285: ! 286: cProc _cinit,<PUBLIC>,<> ! 287: ! 288: cBegin nogen ; no local frame to set up ! 289: assumes ds,data ! 290: assumes ss,data ! 291: ! 292: ; Store DOS major/minor version number ! 293: ; This is done in crt0dat.asm rather than in crt0.asm for Windows' sake. ! 294: ; ! 295: ! 296: callos VERSION ! 297: mov [_osversion],ax ! 298: ! 299: ; 1. Integer divide interrupt vector setup ! 300: ! 301: mov ax,DOS_getvector shl 8 + 0 ! 302: callos ; save divide error interrupt ! 303: mov word ptr [_aintdiv],bx ! 304: mov word ptr [_aintdiv+2],es ! 305: ! 306: push cs ! 307: pop ds ! 308: assumes ds,nothing ! 309: mov ax,DOS_setvector shl 8 + 0 ! 310: mov dx,codeOFFSET _cintDIV ! 311: callos ; set divide error interrupt ! 312: push ss ! 313: pop ds ! 314: assumes ds,data ! 315: ! 316: ! 317: ifdef _QC ! 318: ; 1a. BREAK interrupt vector setup. ! 319: ! 320: INT21 3523h ;[4]Get vector via MSDOS. ! 321: ! 322: mov Word Ptr [__abrkvec],bx ;[4]save vector offset ! 323: mov Word Ptr [__abrkvec+2],es ;[4]save vector segment ! 324: ! 325: push cs ;[4] ! 326: pop ds ;[4] ! 327: mov es,$F_PSP ;[10]get QC PSP for flags ! 328: test es:[PSP_KERNEL_FLGS],PSP_KF_SHELL ;[10]test if in SHELL ! 329: mov dx,codeOFFSET intret ;[10]set DS:DX to int-return pointer ! 330: JNZ cinit_shell ;[10]if SHELL, then jump ! 331: mov dx,codeOFFSET __Break_error ;[4] ! 332: cinit_shell: ;[10] ! 333: INT21 2523h ;[4]Set up new break vector ! 334: ! 335: push ss ;[4] ! 336: pop ds ;[4] ! 337: endif ;_QC ! 338: ! 339: ; 2. Floating point initialization ! 340: ! 341: ifndef _QC ! 342: mov cx,word ptr [fpmath+2] ! 343: jcxz nofloat_i ! 344: ! 345: mov es,[_psp] ; psp segment ! 346: mov si,es:[DOS_ENVP] ; environment segment ! 347: lds ax,[fpdata] ; get task data area ! 348: assumes ds,nothing ! 349: mov dx,ds ; into dx:ax ! 350: xor bx,bx ; (si) = environment segment ! 351: call [fpmath] ; fpmath(0) - init ! 352: jnc fpok ! 353: ! 354: push ss ; restore ds from ss ! 355: pop ds ! 356: jmp _fptrap ; issue "Floating point not loaded" ! 357: ; error and abort ! 358: ! 359: fpok: ! 360: lds ax,[fpsignal] ; get signal address ! 361: assumes ds,nothing ! 362: mov dx,ds ! 363: mov bx,3 ! 364: call [fpmath] ; fpmath(3) - set signal address ! 365: push ss ! 366: pop ds ! 367: assumes ds,data ! 368: ! 369: nofloat_i: ! 370: else ;_QC ! 371: ; cCall $EmulInit,<addr of __fpinit> ;[9] ! 372: push ds ;[9] ! 373: mov ax,dataOffset _fpinit ;[9] ! 374: push ax ;[9] ! 375: call $EmulInit ;[6] ! 376: endif ;_QC ! 377: ! 378: ; 3. Copy ;C_FILE_INFO into _osfile ! 379: ! 380: ; fix up files inherited from child using ;C_FILE_INFO ! 381: ! 382: mov es,[_psp] ; es = PSP ! 383: mov cx,word ptr es:[DOS_envp] ; es = user's environment ! 384: jcxz nocfi ; no environment !!! ! 385: mov es,cx ! 386: xor di,di ; start at 0 ! 387: ! 388: cfilp: ! 389: cmp byte ptr es:[di],0 ; check for end of environment ! 390: je nocfi ; yes - not found ! 391: mov cx,cfileln ! 392: mov si,dataOFFSET cfile ! 393: repe cmpsb ; compare for ';C_FILE_INFO' ! 394: je gotcfi ; yes - now do something with it ! 395: mov cx,07FFFh ; environment max = 32K ! 396: xor ax,ax ! 397: repne scasb ; search for end of current string ! 398: jne nocfi ; no 00 !!! - assume end of env. ! 399: jmp cfilp ; keep searching ! 400: ! 401: ; found ;C_FILE_INFO and transfer info into _osfile ! 402: ! 403: gotcfi: ! 404: push es ! 405: push ds ! 406: pop es ; es = DGROUP ! 407: pop ds ; ds = env. segment ! 408: assumes ds,nothing ! 409: assumes es,data ! 410: mov si,di ; si = startup of _osfile info ! 411: mov di,dataOFFSET _osfile ; di = _osfile block ! 412: ! 413: lodsb ; must be less than 20 ! 414: cbw ! 415: xchg cx,ax ; cx = number of entries ! 416: ! 417: osflp: ! 418: lodsb ; get next byte ! 419: inc al ! 420: jz saveit ; was FF - save as 00 ! 421: dec ax ; restore al ! 422: saveit: ! 423: stosb ! 424: loop osflp ; transfer next character ! 425: ! 426: push ss ! 427: pop ds ; ds = DGROUP ! 428: assumes ds,data ! 429: nocfi: ! 430: ! 431: ! 432: ; 4. Check for devices for file handles 0 - 4 ! 433: ; ! 434: ; Clear the FDEV bit (which might be inherited from C_FILE_INFO) ! 435: ; and then call DOS to see if it really is a device or not ! 436: ; ! 437: mov bx,4 ! 438: ! 439: devloop: ! 440: and _osfile[bx],not FDEV ; clear FDEV bit on principal ! 441: ! 442: mov ax,DOS_ioctl shl 8 + 0 ; issue ioctl(0) to get dev info ! 443: callos ! 444: jc notdev ! 445: ! 446: test dl,80h ; is it a device ? ! 447: jz notdev ; no ! 448: or _osfile[bx],FDEV ; yes - set FDEV bit ! 449: ! 450: notdev: ! 451: dec bx ! 452: jns devloop ! 453: ! 454: ; 5. General C initializer routines ! 455: ! 456: ifndef IBMC20 ! 457: mov si,dataOFFSET xifbegin ! 458: mov di,dataOFFSET xifend ! 459: if sizeC ! 460: call initterm ; call the far initializers ! 461: else ! 462: call farinitterm ; call the far initializers ! 463: endif ! 464: ! 465: ifdef _QC ;[2] ! 466: mov bx,24 ;[2] offset in table ! 467: mov si,PSP_UL_TERM_OFF ;[7] QLB initializers ! 468: call ulibinitterm ;[2] execute far C initializers ! 469: ! 470: mov bx,24 ;[7] offset in table ! 471: mov si,PSP_EXE_TRM_OFF ;[7] .exe initializers ! 472: call ulibinitterm ;[7] execute far C initializers ! 473: endif ;_QC ;[2] ! 474: endif ;IBMC20 ! 475: ! 476: mov si,dataOFFSET xibegin ! 477: mov di,dataOFFSET xiend ! 478: call initterm ; call the initializers ! 479: ! 480: ifdef _QC ;[2] ! 481: mov bx,0 ;[2] offset in table ! 482: mov si,PSP_UL_TERM_OFF ;[7] User Lib initializers ! 483: call ulibinitterm ;[2] execute C initializers ! 484: ! 485: mov bx,0 ;[7] offset in table ! 486: mov si,PSP_EXE_TRM_OFF ;[7] .exe initializers ! 487: call ulibinitterm ;[7] execute far C initializers ! 488: endif ;_QC ;[2] ! 489: ! 490: ret ! 491: cEnd nogen ! 492: ! 493: page ! 494: ;*** ! 495: ;exit(status), _exit(status) - C termination ! 496: ; ! 497: ;Purpose: ! 498: ; The termination sequence is more complicated due to the multiple ! 499: ; entry points - exit(code) and _exit(code). The _exit() routine ! 500: ; is a quick exit routine that does not do certain C exit functions ! 501: ; like stdio buffer flushing and onexit processing. ! 502: ; ! 503: ; exit (status): ! 504: ; ! 505: ; 1. call runtime preterminators ! 506: ; ! 507: ; _exit (status): ! 508: ; ! 509: ; 2. perform C terminators ! 510: ; 3. perform _nullcheck() for null pointer assignment ! 511: ; 4. close all open files ! 512: ; 5. terminate floating point ! 513: ; 6. reset divide by zero interrupt vector ! 514: ; 7. restore int 3F handler ! 515: ; 8. terminate with return code to DOS ! 516: ; ! 517: ;Entry: ! 518: ; int status - exit status ! 519: ; ! 520: ;Exit: ! 521: ; returns to DOS. ! 522: ; ! 523: ;Uses: ! 524: ; ! 525: ;Exceptions: ! 526: ; ! 527: ;******************************************************************************* ! 528: ! 529: public _exit ! 530: _exit: ! 531: cProc dummy1,<>,<> ! 532: ! 533: parmw status ! 534: ! 535: cBegin ! 536: assumes ds,data ! 537: assumes ss,data ! 538: ! 539: ; 1. call runtime preterminators ! 540: ; - onexit processing ! 541: ; - flushall ! 542: ; - rmtmp ! 543: ! 544: mov si,dataOFFSET xontab ; beginning of onexit table ! 545: mov di,dataOFFSET xonend ; end of onexit table ! 546: call initterm ! 547: ! 548: mov si,dataOFFSET xpbegin ; beginning of pre-terminators ! 549: mov di,dataOFFSET xpend ; end of pre-terminators ! 550: call initterm ! 551: ! 552: ifdef _QC ;[2] ! 553: ; [2] call the preterminators for the user library. ! 554: ! 555: mov bx,8 ;[2] offset in table ! 556: mov si,PSP_UL_TERM_OFF ;[7] User Lib initializers ! 557: call ulibinitterm ;[2] execute C terminators ! 558: ! 559: mov bx,8 ;[7] offset in table ! 560: mov si,PSP_EXE_TRM_OFF ;[7] .exe initializers ! 561: call ulibinitterm ;[7] execute far C initializers ! 562: endif ;_QC ;[2] ! 563: ! 564: jmp short exiting ; jump into _exit ! 565: ! 566: cend nogen ! 567: ! 568: ifdef _QC ;[5] ! 569: ! 570: public __shell_exit ;[5] ! 571: __shell_exit: ;[5] ! 572: ! 573: cProc dummy3,<>,<> ;[5] ! 574: parmw status ;[5] ! 575: ! 576: cBegin ;[5] ! 577: mov [shellexit],1 ;[5] mark as a shell exit ! 578: jmp short exiting ;[5] jump into _exit ! 579: cEnd nogen ;[5] ! 580: ! 581: public __qcexit ;[11] ! 582: __qcexit: ;[11] ! 583: ! 584: cproc dummy4,<>,<> ;[11] ! 585: parmw status ;[11] ! 586: ! 587: cBegin ;[11] ! 588: jmp short startclose ;[11] ! 589: cEnd nogen ;[11] ! 590: endif ;_QC ;[5] ! 591: ! 592: public __exit ! 593: __exit: ! 594: cProc dummy2,<>,<> ! 595: ! 596: parmw status ! 597: ! 598: cBegin ! 599: assumes ds,data ! 600: assumes ss,data ! 601: ! 602: exiting: ! 603: ! 604: ; 2. perform C terminators ! 605: ! 606: mov si,dataOFFSET xcbegin ! 607: mov di,dataOFFSET xcend ! 608: call initterm ; call the terminators ! 609: ! 610: ifdef _QC ;[2] ! 611: ; [2] call the terminators for the user library. ! 612: ! 613: mov bx,16 ;[2] offset in table ! 614: mov si,PSP_UL_TERM_OFF ;[7] User Lib initializers ! 615: call ulibinitterm ;[2] execute C terminators ! 616: ! 617: mov bx,16 ;[7] offset in table ! 618: mov si,PSP_EXE_TRM_OFF ;[7] .exe initializers ! 619: call ulibinitterm ;[7] execute far C initializers ! 620: endif ;_QC ;[2] ! 621: ! 622: ifndef IBMC20 ! 623: mov si,dataOFFSET xcfbegin ! 624: mov di,dataOFFSET xcfend ! 625: if sizeC ! 626: call initterm ; call the far terminators ! 627: else ! 628: call farinitterm ; call the far terminators ! 629: endif ! 630: ! 631: ifdef _QC ;[2] ! 632: ; [2] call the terminators for the user library. ! 633: ! 634: mov bx,32 ;[2] offset in table ! 635: mov si,PSP_UL_TERM_OFF ;[7] User Lib initializers ! 636: call ulibinitterm ;[2] execute far terminators ! 637: ! 638: mov bx,32 ;[7] offset in table ! 639: mov si,PSP_EXE_TRM_OFF ;[7] .exe initializers ! 640: call ulibinitterm ;[7] execute far C initializers ! 641: endif ;_QC ;[2] ! 642: ! 643: endif ;IBMC20 ! 644: ! 645: ; 3. perform _nullcheck() for null pointer assignment ! 646: ! 647: call _nullcheck ; check data in NULL data segment at DS:0 ! 648: or ax,ax ; zero if no null ptr assignment detected ! 649: jz startclose ! 650: cmp status,0 ; zero if no other error has occurred ! 651: jnz startclose ! 652: mov status,255 ; nonzero status to indicate an ! 653: ; null-pointer-assignment error ! 654: startclose: ! 655: ! 656: ; 4. close all files (except pre-opened handles 0-4) ! 657: ! 658: ifdef _QC ! 659: ! 660: ; ! 661: ; M00BUG -- Can't assume that devices 0, 1, 2, 3, and 4 are DEVICE only. ! 662: ; ! 663: ! 664: mov cx,_NFILE ;[ 1] ! 665: xor bx,bx ;[ 1] ! 666: ;[ 1] ! 667: closeloop: ;[ 1] ! 668: cmp bx,5 ;[ 1] ! 669: jae closeit ;Unless > 4, which must close. ;[ 1] ! 670: ;[ 1] ! 671: test [__osfile+bx],FDEV ;[ 1] ! 672: jz openit ;Must open devices 0 -> 4. ;[ 1] ! 673: ;[ 1] ! 674: test [__osfile+bx],FOPEN ;[ 1] ! 675: jnz cycle_files ;DEVICE's should stay open. ;[ 1] ! 676: ;[ 1] ! 677: openit: ;[ 1] ! 678: mov dx,dataOFFSET con ;Ugly brute force method. ;[ 1] ! 679: mov ax,3D02h ;[ 1] ! 680: int 21h ;[ 1] ! 681: ;[ 1] ! 682: jmp short cycle_files ;[ 1] ! 683: ;[ 1] ! 684: closeit: ;[ 1] ! 685: test [__osfile+bx],FOPEN ;[ 1] ! 686: jz cycle_files ;[ 1] ! 687: ;[ 1] ! 688: INT21 3Eh ;MSDOS close file. ;[ 1] ! 689: ;[ 1] ! 690: cycle_files: ;[ 1] ! 691: inc bx ! 692: loop closeloop ! 693: ! 694: else ;_QC ! 695: mov cx,_NFILE_-5 ! 696: mov bx,5 ; close handles that are not pre-opened ! 697: ! 698: closeloop: ! 699: test _osfile[bx],FOPEN ! 700: jz notopen ! 701: ! 702: callos close ! 703: ! 704: notopen: ! 705: inc bx ! 706: loop closeloop ! 707: endif ;_QC ! 708: ! 709: ; 5. terminate floating point ! 710: ; 6. reset divide by zero interrupt vector ! 711: ; 7. restore int 3F handler ! 712: ! 713: call _ctermsub ; fast cleanup ! 714: ! 715: ifdef _QC ! 716: ; 8. return to SHELL. ! 717: ! 718: cmp [shellexit],1 ! 719: je exit_sh1 ! 720: ! 721: mov ax,[status] ! 722: jmp Far Ptr $Exec_Shell ! 723: ! 724: exit_sh1: ! 725: mov ax,[status] ! 726: jmp Far Ptr $Terminate_QC ! 727: ! 728: ;[10] Interrupt return for control-break routine while in SHELL. ! 729: ! 730: intret: ;[10] ! 731: IRET ;[10]immediate return while in termination ! 732: ! 733: else ;_QC ! 734: ; 8. return to the DOS ! 735: ! 736: mov ax,status ; get return value ! 737: callos terminate ; exit with al = return code ! 738: endif ;_QC ! 739: ! 740: cEnd nogen ! 741: ! 742: if sizeC ! 743: global endp ! 744: endif ! 745: ! 746: page ! 747: ;*** ! 748: ;_ctermsub - more C termination code ! 749: ; ! 750: ;Purpose: ! 751: ; This routine ! 752: ; (1) performs floating-point termination ! 753: ; (2) resets the divide by zero interrupt vector ! 754: ; (3) restore int 3F handler ! 755: ; ! 756: ;Entry: ! 757: ; ! 758: ;Exit: ! 759: ; ! 760: ;Uses: ! 761: ; AX,BX,CX,DX. ! 762: ; ! 763: ;Exceptions: ! 764: ; ! 765: ;******************************************************************************* ! 766: ! 767: labelNP <PUBLIC,_ctermsub> ! 768: ! 769: ; 5. terminate floating point ! 770: ifndef _QC ! 771: mov cx,word ptr [fpmath+2] ; test for floating point ! 772: jcxz nofloat_t ; no ! 773: ! 774: mov bx,2 ; yes - cleanup ! 775: call [fpmath] ! 776: ! 777: nofloat_t: ! 778: else ;_QC ;[6] ! 779: call $EmulTerm ;[6] clean up floating point ! 780: endif ;_QC ;[6] ! 781: ! 782: ; 6. reset divide by zero interrupt vector ! 783: ! 784: push ds ! 785: lds dx,[_aintdiv] ; ds:dx = restore vector ! 786: mov ax,DOS_setvector shl 8 + 0 ! 787: callos ; set divide error interrupt ! 788: pop ds ! 789: ! 790: ifdef _QC ! 791: ; 6a. reset Control break interrupt vector ! 792: ! 793: push ds ;[4] ! 794: lds dx,[__abrkvec] ;[4]Original BREAK vector. ! 795: INT21 2523h ;[4] ! 796: pop ds ;[4] ! 797: endif ;_QC ! 798: ! 799: ifndef _QC ;[XX] We don't have overlays ! 800: ifndef IBMC20 ! 801: ; 7. restore overlay interrupt vector ! 802: ! 803: cmp byte ptr [_ovlflag],0 ; Overlays in use ?? ! 804: jz done_ovlvec ; if 0, don't restore overlay vector ! 805: push ds ; save ds ! 806: mov al,byte ptr [_intno] ; overlay interrupt number ! 807: lds dx,dword ptr [_ovlvec] ; original ovl interrupt vector ! 808: callos setvector ; restore the overlay vector ! 809: pop ds ; restore ds ! 810: done_ovlvec: ! 811: endif ! 812: endif ; _QC ;[XX] ! 813: ret ! 814: ! 815: ! 816: page ! 817: ;*** ! 818: ;initterm - do a set of initializers or terminators ! 819: ; ! 820: ;Purpose: ! 821: ; The initializors and terminators may be written in C ! 822: ; so we are assuming C conventions (DS=SS, CLD, SI and DI preserved) ! 823: ; We go through them in reverse order for onexit. ! 824: ; ! 825: ;Entry: ! 826: ; SI = start of procedure list ! 827: ; DI = end of procedure list ! 828: ; ! 829: ;Exit: ! 830: ; ! 831: ;Uses: ! 832: ; ! 833: ;Exceptions: ! 834: ; ! 835: ;******************************************************************************* ! 836: ! 837: initterm: ! 838: cmp si,di ; are we done? ! 839: jae itdone ; yes - no more ! 840: ! 841: if sizeC ! 842: sub di,4 ! 843: mov ax,[di] ! 844: or ax,[di+2] ! 845: jz initterm ; skip null procedures ! 846: call dword ptr [di] ! 847: else ! 848: dec di ! 849: dec di ! 850: mov cx,[di] ! 851: jcxz initterm ; skip null procedures ! 852: call cx ! 853: endif ! 854: jmp initterm ; keep looping ! 855: ! 856: itdone: ! 857: ret ! 858: ! 859: page ! 860: ifndef IBMC20 ! 861: ife sizeC ; S/C models only ! 862: ;*** ! 863: ;farinitterm - do a set of far initializers or terminators ! 864: ; ! 865: ;Purpose: ! 866: ; The initializors and terminators may be written in C ! 867: ; so we are assuming C conventions (DS=SS, CLD, SI and DI preserved) ! 868: ; We go through them in reverse order for onexit. ! 869: ; ! 870: ;Entry: ! 871: ; SI = start of procedure list ! 872: ; DI = end of procedure list ! 873: ; ! 874: ;Exit: ! 875: ; ! 876: ;Uses: ! 877: ; ! 878: ;Exceptions: ! 879: ; ! 880: ;******************************************************************************* ! 881: ! 882: farinitterm: ! 883: cmp si,di ; are we done? ! 884: jae faritdone ; yes - no more ! 885: ! 886: sub di,4 ! 887: mov ax,[di] ! 888: or ax,[di+2] ! 889: jz farinitterm ; skip null procedures ! 890: call dword ptr [di] ! 891: jmp farinitterm ; keep looping ! 892: ! 893: faritdone: ! 894: ret ! 895: endif ;sizeC ! 896: endif ;IBMC20 ! 897: ! 898: ! 899: ifdef _QC ;[2] ! 900: ;*** ! 901: ; ulibinitterm - do a set of far initializers or terminators ! 902: ; ! 903: ;Purpose: ! 904: ; The initializors and terminators may be written in C ! 905: ; so we are assuming C conventions (DS=SS, CLD, SI and DI preserved) ! 906: ; We go through them in reverse order for onexit. ! 907: ; ! 908: ;Entry: ! 909: ; BX = Offset in User Library Init table to use ! 910: ; ! 911: ;Exit: ! 912: ; ! 913: ;Uses: ! 914: ; SI, DI, CX, AX, ES ! 915: ; ! 916: ;Exceptions: ! 917: ; ! 918: ;******************************************************************************* ! 919: ! 920: ulibinitterm: ;[2] ! 921: push ds ;[2] save DGROUP ! 922: cmp [shellexit],1 ;[7] ! 923: je skipfarterm ;[7] shell does not do this initializations ! 924: ! 925: mov ds,[_psp] ;[2] get pointer to PSP ! 926: lds si,dword ptr ds:[si] ;[7] load user library far terminator table address ! 927: mov cx,ds ;[2] verify that the table exists ! 928: or cx,si ;[2] ! 929: jz skipfarterm ;[2] NO? then skip over initialization code ! 930: les di,ds:[si+bx]+4 ;[2] Get end of far terminator list ! 931: ;[2] Compute offset of list from DGROUP ! 932: mov ax,es ;[2] ax = list segment ! 933: pop cx ;[2] cx = DGROUP segment ! 934: push cx ;[2] ! 935: sub ax,cx ;[2] difference ! 936: mov cl,4 ;[2] ! 937: shl ax,cl ;[2] shift up ! 938: add di,ax ;[2] ! 939: les si,ds:[si+bx] ;[2] Get end of far terminator list ! 940: ;[2] Compute offset of list from DGROUP ! 941: mov ax,es ;[2] ax = list segment ! 942: pop cx ;[2] cx = DGROUP segment ! 943: push cx ;[2] ! 944: sub ax,cx ;[2] difference ! 945: mov cl,4 ;[2] ! 946: shl ax,cl ;[2] shift up ! 947: add si,ax ;[2] ! 948: pop ds ;[2] Restore DGROUP ! 949: push ds ;[2] ! 950: call initterm ;[2] Execute the list of far terminators ! 951: ! 952: skipfarterm: ;[2] ! 953: pop ds ;[2] restore dgroup ! 954: ret ;[2] ! 955: endif ;_QC ;[2] ! 956: ! 957: sEnd ! 958: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.