Annotation of os2sdk/startup/dos/crt0.asm, revision 1.1.1.1

1.1       root        1:        page    ,132
                      2:        TITLE   crt0 - C start up routine
                      3: ;***
                      4: ;crt0.asm - C start up routine
                      5: ;
                      6: ;      Copyright (c) 1985-1987, Microsoft Corporation.  All rights reserved.
                      7: ;
                      8: ;Purpose:
                      9: ;      How startup works in a few words -
                     10: ;
                     11: ;      The startup and termination is performed by a few modules
                     12: ;
                     13: ;              crt0.asm        DOS 2.x/3.x specific init/term
                     14: ;              crt0msg.asm     DOS 2.x/3.x error messages
                     15: ;              (winstart.asm)  Windows specific init/term (not included)
                     16: ;
                     17: ;              crt0dat.asm     remainder of shared DOS 3.x init/term
                     18: ;
                     19: ;      *************  IMPORTANT  *****************************************
                     20: ;
                     21: ;      If the user reassembles this module, he will need to link using the
                     22: ;      /DOSSEG switch or run the the DOSSEG.EXE program on crt0.obj, i.e.
                     23: ;
                     24: ;              dosseg crt0.obj
                     25: ;
                     26: ;      See the C documentation for more information about the /DOSSEG switch.
                     27: ;
                     28: ;      All assembler modules must be assembled with the /mx switch, i.e.
                     29: ;
                     30: ;              masm crt0/mx;
                     31: ;
                     32: ;*******************************************************************************
                     33: 
                     34: 
                     35: ?DF=   1                       ; this is special for c startup
                     36: include        version.inc
                     37: .xlist
                     38: ifdef  _QC                     ;[5] move includes out of version
                     39: include        \sl\qc\src\include\kernel.inc   ;[5]
                     40: include        \sl\qc\src\include\kmac.inc     ;[5]
                     41: CEDEF  macro   name, num, msg          ;;[8]
                     42: name   equ     num                     ;;[8]
                     43: endm                                   ;;[8]
                     44: include \sl\qc\src\include\criterr.inc ;[8]
                     45: endif  ;_QC                    ;[5] 
                     46: 
                     47: include        cmacros.inc
                     48: include        msdos.inc
                     49: include        brkctl.inc
                     50: .list
                     51: 
                     52: ifdef  _QC                     ;[2]
                     53: extrn  $Exec_Shell:FAR         ;[9]
                     54: extrn  $GlobalAlloc:FAR        ;[2]
                     55: extrn  $GlobalLock:FAR         ;[2]
                     56: extrn  $GlobalUnlock:FAR       ;[2]
                     57: extrn  _AddString:FAR          ;[2]
                     58: endif  ;_QC                    ;[2]
                     59: 
                     60:        page
                     61: ;===========================================================================
                     62: ;
                     63: ;      Segment definitions
                     64: ;
                     65: ;      The segment order is essentially the same as in XENIX.
                     66: ;      This module is edited after assembly to contain a dosseg comment
                     67: ;      record for the linker.
                     68: ;
                     69: ;===========================================================================
                     70: 
                     71: createSeg _TEXT, code, word,   public, CODE,   <>
                     72: createSeg C_ETEXT,etext, word, public, ENDCODE,<>
                     73: 
                     74: createSeg _DATA, data, word,   public, DATA,   DGROUP
                     75: createSeg STACK, stack,        para,   stack,  STACK,  DGROUP
                     76: 
                     77: defGrp DGROUP                  ; define DGROUP
                     78: 
                     79: codeOFFSET equ offset _TEXT:
                     80: dataOFFSET equ offset DGROUP:
                     81: 
                     82: page
                     83: 
                     84: public __acrtused              ; trick to force in startup
                     85:        __acrtused = 9876h      ; funny value not easily matched in SYMDEB
                     86: 
                     87: extrn  __acrtmsg:abs           ; trick to pull in startup messages
                     88: 
                     89: 
                     90: ifndef _QC
                     91: sBegin stack
                     92: assumes        ds,data
                     93:        db      2048 dup (?)    ; default stack size
                     94: sEnd
                     95: endif  ;_QC
                     96: 
                     97: page
                     98: 
                     99: ifndef _QC
                    100: externP        main                    ; C main program
                    101: endif  ;_QC
                    102: 
                    103: externP        exit                    ; exit ( code )
                    104: 
                    105: if     sizeC
                    106: extrn  __exit:far              ; _exit ( code) (cmacros name conflict)
                    107: else
                    108: extrn  __exit:near
                    109: endif
                    110: 
                    111: sBegin data
                    112: 
                    113: extrn  _edata:byte             ; end of data (start of bss)
                    114: extrn  _end:byte               ; end of bss (start of stack)
                    115: 
                    116: externW        _psp                    ; psp:0 (paragraph #)
                    117: externW        __argc
                    118: externDP __argv
                    119: externDP environ
                    120: 
                    121: ifdef _QC
                    122: externW        _QChdata                ; High water mark of data space
                    123: globalW        _QCldata,0              ; begining of DGroup (low water mark)
                    124: 
                    125: extrn  STKHQQ:WORD
                    126: 
                    127: extrn  __QCrtcsip:DWORD        ;[2]
                    128: endif  ;_QC
                    129: 
                    130: ;      these are used by DOS C memory management (not used in Windows)
                    131: 
                    132: globalW        _asizds,0               ; DS size (in bytes)
                    133: globalW        _atopsp,0               ; top of stack (heap bottom)
                    134: globalW        _aexit_rtn,<codeoffset __exit> ; NEAR pointer
                    135: 
                    136: labelW <PUBLIC,_abrktb>        ; segment table for brkctl
                    137:        dw      ?
                    138:        dw      DGROUP
                    139:        db      (MAXSEG-1) * (size segrec) dup (?)
                    140: 
                    141: labelW <PUBLIC,_abrktbe>
                    142: globalW        _abrkp,<dataoffset _abrktb>
                    143: 
                    144: sEnd
                    145: 
                    146:        page
                    147: 
                    148: 
                    149: externP        _cinit                  ; run-time initializers
                    150: 
                    151: ifdef _QC
                    152: externP _NMSG_TEXT             ; pascal - find error message text
                    153: endif
                    154: externP _NMSG_WRITE            ; pascal - write error message to stdout
                    155: externP        _FF_MSGBANNER           ; pascal - error message banner
                    156:                                ; (includes FORTRAN $DEBUG info)
                    157: 
                    158: externP        _setargv                ; process command line arguments
                    159: externP        _setenvp                ; process environment
                    160: externP        _nullcheck              ; check for null assignment
                    161: 
                    162: 
                    163: sBegin code
                    164: assumes        cs,code
                    165: 
                    166: ifdef  _QC
                    167: 
                    168:        public  $F_PSP          ; Segment of the fake PSP for QC
                    169: $F_PSP dw      0               ; Must be in CODE segment for recovery.
                    170: FirstTime db   1;              ;[10] Flag to catch when the shell startup
                    171:                                ;[10]   code is executed.
                    172: 
                    173: assumes        ds,DGROUP               ; DGROUP is setup and set by QC kernel
                    174: assumes        es,nothing
                    175: else   ;_QC
                    176: assumes        ds,nothing
                    177: endif  ;_QC
                    178: 
                    179: page
                    180: ;***
                    181: ;_astart - start of all C programs
                    182: ;
                    183: ;Purpose:
                    184: ;      Startup routine to initialize C run-time environment
                    185: ;
                    186: ;Entry:
                    187: ;
                    188: ;Exit:
                    189: ;      Exits to DOS via exit().
                    190: ;
                    191: ;Uses:
                    192: ;
                    193: ;Exceptions:
                    194: ;
                    195: ;*******************************************************************************
                    196: 
                    197: labelNP        <PUBLIC,_astart>        ; start address of all "C" programs
                    198: 
                    199: ifndef _QC
                    200: ;      check MS-DOS version for 2.0 or later
                    201: 
                    202:        callos  VERSION         ; AX must be preserved until later
                    203:        cmp     al,2            ; check for version 2 or later
                    204:        jae     setup           ;   yes - continue with setup
                    205:        int     20h             ; DOS 1.0 exit program  
                    206: 
                    207: setup:
                    208: endif  ;_QC
                    209: 
                    210: ifdef  _QC
                    211:        mov     cs:[$F_PSP],es  ; Save segment of fake PSP
                    212: 
                    213:        mov     di,ds           ; di = DGROUP
                    214:        mov     si,es:[PSP_EOM_SEG] ; get max. paragraph
                    215: else   ;_QC
                    216:        mov     di,DGROUP
                    217:        mov     si,ds:[DOS_MAXPARA] ; get max. paragraph
                    218: endif  ;_QC
                    219: 
                    220:        sub     si,di           ; si = # para in data area
                    221:        cmp     si,1000h        ; if more than 64K
                    222:        jb      setSP
                    223: 
                    224:        mov     si,1000H        ; use full 64K (-16)
                    225: 
                    226: setSP:
                    227: 
                    228:        cli                     ; turn off interrupts
                    229:        mov     ss,di           ; SS = DGROUP
                    230:        add     sp,dataoffset _end-2 ; 2 for _asizds limit
                    231:        sti                     ; turn interrupts back on
                    232:        jnc     SPok
                    233: 
                    234: ifndef         IBMC20
                    235:        push    ss              ; establish DS=DGROUP for
                    236:        pop     ds              ; _FF_MSGBANNER -> _NMSG_WRITE -> _NMSG_TEXT
                    237: endif  ; IBMC20
                    238: ifdef  _QC                     ;[6]
                    239:        mov     es,cs:[$F_PSP]  ;[9] find 'fake' PSP
                    240:        mov     es:[PSP_CRITERR], CE_EXEC; [9] Indicate an error to kernel
                    241:        jmp     Far Ptr $Exec_Shell ; [9]
                    242:        
                    243: else   ;_QC                    ;[6]
                    244:        call    _FF_MSGBANNER   ; for "\r\nrun-time error " banner
                    245:        xor     ax,ax           ; stack overflow error message (0)
                    246:        push    ax
                    247:        call    _NMSG_WRITE
                    248:        mov     ax,DOS_terminate shl 8 + 255
                    249:        callos                  ; terminate process with 255
                    250: endif  ;_QC                    ;[6]
                    251: 
                    252: SPok:
                    253:        assumes ss,data
                    254: 
                    255:        and     sp,not 1        ; make even (if not)
                    256:        mov     [_abrktb].sz,sp ; top DS free location
                    257:        mov     [_atopsp],sp    ; save top of stack
                    258: 
                    259: ifdef  _QC
                    260:        mov     bx,sp           ; Setup up a EOS flag on stack.
                    261:        sub     bx,es:[PSP_STK_SIZE]
                    262:        add     bx,2+256        ;[1]add stack "slop" to keep 256 bytes
                    263:        mov     [STKHQQ],bx
                    264:        mov     Word Ptr [bx],5252h
                    265: endif  ;_QC
                    266: 
                    267:        mov     ax,si           ; si = # paragraphs
                    268:        mov     cl,4
                    269:        shl     ax,cl
                    270:        dec     ax
                    271:        mov     [_asizds],ax    ; save DS size - 1 (in bytes)
                    272: 
                    273: ifdef  _QC
                    274:        mov     [__psp],es
                    275: 
                    276:        mov     [__QCldata],di          ; Low end of memory for pointer checking
                    277: 
                    278:        mov     es,di                   ; es = DGROUP
                    279:        push    es                      ;[7] save DGROUP
                    280: 
                    281:        mov     ax,1                    ;[7] Now look for high end
                    282:        call    $GlobalLock             ;[7] handle table
                    283:        mov     es,ax                   ;[7]
                    284:        mov     bx,0                    ;[7]
                    285:        mov     cx,128                  ;[7] 128 entries in table
                    286:        mov     ax,0                    ;[7] current high
                    287:        
                    288: ast1a:                                 ;[7]
                    289:        cmp     ax,es:[bx]              ;[7] is this high
                    290:        jae     ast1b                   ;[7] no
                    291:        mov     ax,es:[bx]              ;[7] yes - new high
                    292: ast1b:
                    293:        add     bx,2                    ;[7] move to next entry
                    294:        loop    ast1a                   ;[7] loop until done
                    295: 
                    296:        mov     [_QChdata],ax           ;[7] save as top of memory.
                    297:        pop     es                      ;[7] restore es=DGROUP
                    298: assumes        es,DGROUP
                    299: 
                    300: else   ;_QC
                    301: 
                    302: ;      release extra space to DOS
                    303: 
                    304:        add     si,di           ; si = DGROUP + # para in DGROUP
                    305:        mov     ds:[DOS_MAXPARA],si ; fix psp:2
                    306:        mov     bx,es           ; bx = PSP base
                    307:        sub     bx,si           ; bx = - # para used
                    308:        neg     bx
                    309:        callos  setmem          ; set memory block size
                    310:        mov     [_psp],ds       ; save psp:0
                    311: 
                    312: ;      zero data areas (_BSS and c_common)
                    313: 
                    314:        push    ss
                    315:        pop     es
                    316:        assumes es,data
                    317: 
                    318:        cld                     ; set direction flag (up)
                    319:        mov     di,dataOFFSET _edata ; beginning of bss area
                    320:        mov     cx,dataOFFSET _end ; end of bss area
                    321:        sub     cx,di
                    322:        xor     ax,ax
                    323:        rep     stosb           ; zero bss
                    324: 
                    325: ;      C segmentation conventions set up here  (DS=SS and CLD)
                    326: 
                    327:        push    ss              ; set up initial DS=ES=SS, CLD
                    328:        pop     ds
                    329:        assumes ds,data
                    330: endif  ;_QC
                    331: 
                    332: ;      do necessary initialization BEFORE command line processing!
                    333: 
                    334:        call    _cinit          ; shared by DOS and Windows
                    335: 
                    336:        push    ss
                    337:        pop     ds              ; ds = DGROUP
                    338:        assumes ds,data
                    339: 
                    340: ;      process command line and environment
                    341: 
                    342: ifdef  _QC                     ;[10]
                    343:        test    [FirstTime],1   ;[10] Is this the first time?
                    344:        jz      setenv2         ;[10] No  -  do the environment
                    345:        mov     es,[_psp]       ;[11] look at fake psp to see if 
                    346:        test    es:[PSP_KERNEL_FLGS],PSP_KF_BATCH;[11] in batch mode?
                    347:        jz      setenv1         ;[11] yes - skip parsing env
                    348: setenv2:
                    349:        call    _setenvp        ;[10] crack enviornment
                    350: setenv1:                       ;[10]
                    351:        mov     [FirstTime],0   ;[10] Never the first time again
                    352: else   ;_QC                    ;[10]
                    353:        call    _setenvp        ; crack environment
                    354: endif  ;_QC                    ;[10]
                    355:        call    _setargv        ; crack command line
                    356: 
                    357: ;      call main and exit
                    358: 
                    359:        xor     bp,bp           ; mark top stack frame for SYMDEB
                    360: 
                    361: if     sizeD
                    362:        push    word ptr [environ+2] ; the environment is not always in DS
                    363: endif
                    364:        push    word ptr [environ]
                    365: 
                    366: if     sizeD
                    367:        push    word ptr [__argv+2] ; the arguments are not always in DS
                    368: endif
                    369:        push    word ptr [__argv]
                    370: 
                    371:        push    [__argc]        ; argument count
                    372: 
                    373: ifdef  _QC
                    374:        mov     es,[__psp]
                    375:        call    Dword Ptr es:[PSP_MAIN_ENTRY]
                    376: else   ;_QC
                    377:        call    main            ; main ( argc , argv , envp )
                    378: endif  ;_QC
                    379: 
                    380: ; use whatever is in ax after returning here from the main program
                    381: 
                    382:        push    ax
                    383:        call    exit            ; exit (AX)
                    384:                                ;   _exit will call terminators
                    385: 
                    386: page
                    387: ifdef  _QC
                    388: labelFP <PUBLIC,_QCnptr_error>
                    389: 
                    390: ; [2]
                    391: ; We know we were called far, so to get the 'best guess' cs:ip, we
                    392: ; just set __QCrtcsip by looking at our return address.
                    393: ; [2]
                    394: 
                    395:        mov     ds,cs:[$F_PSP]          ;[4] get PSP
                    396:        mov     ax,ds:[PSP_DGROUP_SEG]  ;[4] get DGROUP
                    397:        mov     ds, ax                  ;[4] ds = DGROUP
                    398: 
                    399:        pop     word ptr [__QCrtcsip]   ;[2] Get offset
                    400:        pop     word ptr [__QCrtcsip+2] ;[2] Get segment
                    401: 
                    402:        mov     ax,12           ;Illegal Near pointer encountered.
                    403:        jmp     short _amsg_exit
                    404: 
                    405: labelFP <PUBLIC,_QCfptr_error>
                    406: 
                    407: ; [2]
                    408: ; We know we were called far, so to get the 'best guess' cs:ip, we
                    409: ; just set __QCrtcsip by looking at our return address.
                    410: ; [2]
                    411: 
                    412:        mov     ds,cs:[$F_PSP]          ;[4] get PSP
                    413:        mov     ax,ds:[PSP_DGROUP_SEG]  ;[4] get DGROUP
                    414:        mov     ds, ax                  ;[4] ds = DGROUP
                    415: 
                    416:        pop     word ptr [__QCrtcsip]   ;[2] Get offset
                    417:        pop     word ptr [__QCrtcsip+2] ;[2] Get segment
                    418: 
                    419:        mov     ax,13           ;Illegal Far pointer encountered.
                    420:        jmp     short _amsg_exit
                    421: 
                    422: labelFP        <PUBLIC,_Break_error>
                    423: 
                    424: ; [2]
                    425: ; We know we were called far, so to get the 'best guess' cs:ip, we
                    426: ; just set __QCrtcsip by looking at our return address.
                    427: ; [2]
                    428: 
                    429:        mov     ds,cs:[$F_PSP]          ;[4] get PSP
                    430:        mov     ax,ds:[PSP_DGROUP_SEG]  ;[4] get DGROUP
                    431:        mov     ds, ax                  ;[4] ds = DGROUP
                    432: 
                    433:        pop     word ptr [__QCrtcsip]   ;[2] Get offset
                    434:        pop     word ptr [__QCrtcsip+2] ;[2] Get segment
                    435: 
                    436:        mov     ax,14           ;Control BREAK encountered.
                    437:        jmp     short _amsg_exit
                    438: endif  ;_QC
                    439: 
                    440: ;***
                    441: ;_amsg_exit, _cintDIV - Fast exit fatal errors
                    442: ;
                    443: ;Purpose:
                    444: ;      Exit the program with error code of 255 and appropriate error
                    445: ;      message.  cintDIV is used for integer divide by zero, amsg_exit
                    446: ;      is for other run time errors.
                    447: ;
                    448: ;Entry:
                    449: ;      AX      = error message number (amsg_exit only).
                    450: ;
                    451: ;Exit:
                    452: ;      calls exit() [cintDIV] or indirect through _aexit_rtn [amg_exit].
                    453: ;
                    454: ;Uses:
                    455: ;
                    456: ;Exceptions:
                    457: ;
                    458: ;*******************************************************************************
                    459: 
                    460: labelNP        <PUBLIC,_cintDIV>
                    461: 
                    462: ifndef IBMC20
                    463:        assumes ds,nothing
                    464:        assumes ss,data
                    465: 
                    466: endif ; IBMC20
                    467: 
                    468: ifdef  IBMC20
                    469: ;      _NMSG_WRITE will reestablish ds = DGROUP
                    470: else
                    471: ;      _cintDIV establishes ds = DGROUP
                    472: endif ; IBMC20
                    473: 
                    474: ifdef  _QC                             ;[3]
                    475: ; [3]
                    476: ; We got here from an interrupt so the stack looks like:
                    477: ;   flags
                    478: ;   seg
                    479: ;   off
                    480: ; So to get the CS:IP where it occurred, we just pop the seg and off from
                    481: ; the stack (we don't need to get back...)
                    482: ; [3]
                    483: 
                    484:        mov     ds,cs:[$F_PSP]          ;[4] get PSP
                    485:        mov     ax,ds:[PSP_DGROUP_SEG]  ;[4] get DGROUP
                    486:        mov     ds, ax                  ;[4] ds = DGROUP
                    487: 
                    488:        pop     word ptr [__QCrtcsip]   ;[3] Offset
                    489:        pop     word ptr [__QCrtcsip+2] ;[3] Segment
                    490: else
                    491: ifndef IBMC20
                    492:        mov     ax, DGROUP              ; reestablish DS=DGROUP
                    493:        mov     ds, ax  
                    494: endif ; IBMC20
                    495: endif  ;_QC                            ;[3]
                    496: 
                    497:        mov     ax,3            ; Integer divide by zero interrupt
                    498:        mov     [_aexit_rtn],codeoffset _exit ; call high-level exit()
                    499:                                ; to cause file buffer flushing
                    500: 
                    501: labelNP        <PUBLIC,_amsg_exit>
                    502: 
                    503: ifdef  _QC                     ;[2]
                    504:        push    si              ;[2] Is this necessary?
                    505:        push    di              ;[2] Is this necessary?
                    506:        mov     si, ax          ;[2] Save message number
                    507: endif  ;_QC                    ;[2]
                    508: 
                    509:        push    ax              ; message number for _NMSG_WRITE
                    510:        call    _FF_MSGBANNER   ; run-time error message banner
                    511:        call    _NMSG_WRITE     ; write error message to stdout
                    512: 
                    513: ifdef  _QC                                     ;[2]
                    514:        mov     es, cs:[$F_PSP]                 ;[2] Find 'fake' PSP
                    515:        mov     es:[PSP_CRITERR], 255           ;[2] Indicate error to kernel
                    516: 
                    517:        mov     ax, es:[PSP_ERRTAB_HDL]         ;[2] Find error table handle
                    518:        or      ax, ax                          ;[2] Does it exist?
                    519:        jnz     _QC_0                           ;[2] Yes, don't allocate
                    520: 
                    521:        mov     ax, 26 * size error_struct      ;[2]
                    522:        xor     dx, dx                          ;[2]
                    523:        xor     cx, cx                          ;[2]
                    524:        call    $GlobalAlloc                    ;[2]
                    525:        or      ax, ax                          ;[8] Check to see if we got it
                    526:        jz      _QC_Fail                        ;[8] Allocation failed
                    527: 
                    528: _QC_0:
                    529:        mov     di, ax                          ;[2] Save handle
                    530:        call    $GlobalLock                     ;[2] Handle should be in AX
                    531:        mov     es, ax                          ;[2] Get seg of memory block
                    532: 
                    533:        mov     ax, si                          ;[2] Get error number
                    534:        or      ax, 8000h                       ;[2] Set high bit in case 0
                    535:        mov     es:[es_ecode], ax               ;[2]
                    536:        mov     ax, word ptr __QCrtcsip         ;[2]
                    537:        mov     es:[es_oln], ax                 ;[2] Save IP (kludge)
                    538:        mov     ax, word ptr __QCrtcsip + 2     ;[2]
                    539:        mov     es:[es_ob], ax                  ;[2] Save CS (kludge)
                    540: 
                    541:        push    es                              ;[2]
                    542: 
                    543:        mov     ax,255                          ;[2] 'run-time error' msg
                    544:        push    ax                              ;[2]
                    545:        call    _NMSG_TEXT                      ;[2] Fetch msg
                    546:        push    ax                              ;[2]
                    547:        call    _AddString                      ;[2] Add to strings heap
                    548:        add     sp, 2                           ;[2] C-calling convention
                    549:        cmp     ax, 0FFFFh                      ;[8] Error?
                    550:        jnz     _QC_2                           ;[8] No, continue
                    551: 
                    552:        pop     es                              ;[8]
                    553:        jmp     short _QC_Fail                  ;[8]
                    554: 
                    555: _QC_2:                                         ;[8]
                    556:        xchg    si, ax                          ;[2] Save offset in heap
                    557:        push    ax                              ;[2] Retrieve message number
                    558:        call    _NMSG_TEXT                      ;[2] Return AX -> msg
                    559:        push    ax                              ;[2]
                    560:        call    _AddString                      ;[2] Add string to heap
                    561:        add     sp, 2                           ;[2] AddString is C-calling
                    562: 
                    563:        pop     es                              ;[2]
                    564:        cmp     ax, 0FFFFh                      ;[8] Error in AddString?
                    565:        jz      _QC_Fail                        ;[8] Yes, fail
                    566:        mov     es:[es_obString], si            ;[2] Save offset of msg
                    567: 
                    568:        mov     es, cs:[$F_PSP]                 ;[2]
                    569:        mov     es:[PSP_ERRTAB_HDL], di         ;[2]
                    570: 
                    571:        mov     ax, di                          ;[2] Retrieve handle
                    572:        call    $GlobalUnlock                   ;[2]
                    573:        jmp     short _QC_1                     ;[8] Exit cleanly
                    574: 
                    575: _QC_Fail:                                      ;[8] Failure code
                    576:        mov     es, cs:[$F_PSP]                 ;[8]
                    577:        mov     es:[PSP_CRITERR], CE_NOMEM      ;[8] Note true error
                    578: 
                    579: _QC_1:                                         ;[8] Exit code
                    580:        pop     di                              ;[2] Necessary?
                    581:        pop     si                              ;[2] Necessary?
                    582: endif  ;_QC                                    ;[2]
                    583: 
                    584:        assumes ds,data
                    585: 
                    586:        mov     ax,255
                    587:        push    ax
                    588: if     sizeC
                    589:        push    cs                              ; _exit is compiled far
                    590:                                                ;       but called near
                    591: endif
                    592:        call    word ptr [_aexit_rtn] ; _exit(255) ordinarily
                    593:                                ; (or exit(255) for div by 0)
                    594:                                ; NEAR routine pointer
                    595: 
                    596: sEnd
                    597:        end     _astart         ; start address

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.