|
|
1.1 ! root 1: page ,132 ! 2: TITLE crt0 - OS/2 C start up routine ! 3: ;*** ! 4: ;5crt0.asm - OS/2 C start up routine ! 5: ; ! 6: ; Copyright (c) 1986-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: ; 5crt0.asm OS/2 specific init/term ! 14: ; 5crt0msg.asm OS/2 error messages ! 15: ; 5crt0dat.asm remainder of shared OS/2 init/term ! 16: ; ! 17: ; ************* IMPORTANT ***************************************** ! 18: ; ! 19: ; If the user reassembles this module, he will need to link using the ! 20: ; /DOSSEG switch or run the the DOSSEG.EXE program on 5crt0.obj, i.e. ! 21: ; ! 22: ; dosseg 5crt0.obj ! 23: ; ! 24: ; See the C documentation for more information about the /DOSSEG switch. ! 25: ; ! 26: ; All assembler modules must be assembled with the /mx switch, i.e. ! 27: ; ! 28: ; masm 5crt0/mx; ! 29: ; ! 30: ;******************************************************************************* ! 31: ! 32: ! 33: ?DF= 1 ; this is special for c startup ! 34: include version.inc ! 35: .xlist ! 36: include cmacros.inc ! 37: include msdos.inc ! 38: include brkctl.inc ! 39: .list ! 40: ! 41: page ! 42: ;=========================================================================== ! 43: ; ! 44: ; Segment definitions ! 45: ; ! 46: ; The segment order is essentially the same as in XENIX. ! 47: ; This module is edited after assembly to contain a dosseg comment ! 48: ; record for the linker. ! 49: ; ! 50: ;=========================================================================== ! 51: ! 52: createSeg _TEXT, code, word, public, CODE, <> ! 53: createSeg C_ETEXT,etext, word, public, ENDCODE,<> ! 54: ! 55: createSeg _DATA, data, word, public, DATA, DGROUP ! 56: createSeg STACK, stack, para, stack, STACK, DGROUP ! 57: ! 58: defGrp DGROUP ; define DGROUP ! 59: ! 60: codeOFFSET equ offset _TEXT: ! 61: dataOFFSET equ offset DGROUP: ! 62: ! 63: page ! 64: ! 65: public __acrtused ; trick to force in startup ! 66: __acrtused = 9876h ; funny value not easily matched in SYMDEB ! 67: ! 68: extrn __acrtmsg:abs ; trick to pull in startup messages ! 69: ! 70: ! 71: sBegin stack ! 72: assumes ds,data ! 73: db 2048 dup (?) ; default stack size ! 74: sEnd ! 75: ! 76: page ! 77: ! 78: sBegin data ! 79: ! 80: extrn _edata:byte ; end of data (start of bss) ! 81: extrn _end:byte ; end of bss (start of stack) ! 82: ! 83: externW __argc ! 84: externDP __argv ! 85: externDP environ ! 86: externB _osfile ! 87: externB _osmajor ; Major and Minor versions of OS/2 ! 88: externB _osmode ; real/protected mode flag ! 89: ! 90: ; these are used by DOS C memory management (not used in Windows) ! 91: ! 92: ;* ! 93: ;* The following (_acmdln and _aenvseg) must be in this order! ! 94: ;* ! 95: globalW _acmdln,0 ; Offset of command line string in env ! 96: globalW _aenvseg,0 ; Selector of Environment segment ! 97: ! 98: globalW _asizds,0 ; DS size (in bytes) ! 99: globalW _atopsp,0 ; top of stack (heap bottom) ! 100: globalW _aexit_rtn,<codeoffset __exit> ; NEAR pointer ! 101: ! 102: labelW <PUBLIC,_abrktb> ; segment table for brkctl ! 103: dw ? ! 104: dw DGROUP ! 105: db (MAXSEG_PM-1) * (size segrec) dup (?) ! 106: ! 107: labelW <PUBLIC,_abrktbe> ! 108: globalW _abrkp,<dataoffset _abrktb> ! 109: ! 110: ! 111: ; special C environment string ! 112: ! 113: labelB <PUBLIC,_acfinfo> ! 114: cfile db '_C_FILE_INFO' ! 115: cfilex db '=',0 ! 116: cfileln = cfilex-cfile+1 ! 117: ! 118: sEnd ! 119: ! 120: page ! 121: ! 122: ! 123: externP _cinit ; run-time initializers ! 124: ! 125: externP _NMSG_WRITE ; pascal - write error message to stdout ! 126: externP _FF_MSGBANNER ; pascal - C/FORTRAN error message banner ! 127: ! 128: externP _setargv ; process command line arguments ! 129: externP _setenvp ; process environment ! 130: externP _nullcheck ; check for null assignment ! 131: ! 132: externP main ; C main program ! 133: externP exit ; exit ( code ) ! 134: ! 135: if sizeC ! 136: extrn __exit:far ; _exit ( code) (cmacros name conflict) ! 137: else ! 138: extrn __exit:near ! 139: endif ! 140: ! 141: extrn DOSGETVERSION:far ! 142: extrn DOSGETMACHINEMODE:far ! 143: ! 144: sBegin code ! 145: assumes cs,code ! 146: ! 147: page ! 148: ;*** ! 149: ;_astart - start of all C programs ! 150: ; ! 151: ;Purpose: ! 152: ; Startup routine to initialize C run-time environment. ! 153: ; ! 154: ;Entry: ! 155: ; OS/2 Start-Up Conditions: ! 156: ; ! 157: ; DS = Automatic Data Segment ! 158: ; SS:SP = Stack Segment and Initial Stack Pointer ! 159: ; ES = 0000 ! 160: ; AX = Selector of Environment Segment ! 161: ; BX = Offset of Command Line in Environment Segment ! 162: ; CX = Size of Automatic Data Segment (CX=0 means 65536 bytes) ! 163: ; BP = 0000 ! 164: ; ! 165: ;Exit: ! 166: ; Exits to OS/2 via exit(). ! 167: ; ! 168: ;Uses: ! 169: ; ! 170: ;Exceptions: ! 171: ; ! 172: ;******************************************************************************* ! 173: ! 174: labelNP <PUBLIC,_astart> ; start address of all "C" programs ! 175: ; ! 176: ; ! 177: cld ; set direction flag (up) ! 178: mov [_atopsp],sp ; Top of Stack Region ! 179: mov [_abrktb].sz,sp ; top DS free location ! 180: mov [_abrktb].sg,ds ; DGROUP segment ! 181: dec cx ! 182: mov [_asizds],cx ; Size of Global Data Segment ! 183: mov [_aenvseg],ax ; Handle of Environment Segment ! 184: mov [_acmdln],bx ; Offset of Command Line String ! 185: ; ! 186: ; get OS/2 version ! 187: ; ! 188: push ax ! 189: mov ax,sp ! 190: ! 191: push ss ! 192: push ax ; address for version ! 193: call DOSGETVERSION ! 194: pop ax ! 195: xchg ah,al ; swap bytes ! 196: mov word ptr [_osmajor],ax ! 197: ; ! 198: ; Get real/protected mode flag ! 199: ; ! 200: mov ax,dataOFFSET _osmode ! 201: push ds ! 202: push ax ! 203: call DOSGETMACHINEMODE ! 204: ! 205: ifdef IBMC20 ! 206: ; ! 207: ; zero data areas (_BSS and c_common) ! 208: ; ! 209: push ss ! 210: pop es ! 211: assumes es,data ! 212: mov di,dataOFFSET _edata ; beginning of bss area ! 213: mov cx,dataOFFSET _end ; end of bss area ! 214: sub cx,di ! 215: xor ax,ax ! 216: rep stosb ; zero bss ! 217: endif ! 218: ! 219: ;**** ! 220: ;* C_FILE_INFO must be processed before _cinit() is called ! 221: ;* because _cinit() checks handles 0-2 for device/pipe. ! 222: ;**** ! 223: ! 224: ; fix up files inherited from child using _C_FILE_INFO ! 225: ! 226: call inherit ! 227: ! 228: ; do necessary initialization BEFORE command line processing! ! 229: ! 230: call _cinit ; shared by OS/2 and Windows ! 231: ! 232: ; process command line and environment ! 233: ! 234: call _setargv ; crack command line ! 235: call _setenvp ; crack environment ! 236: ! 237: ; call main and exit ! 238: ! 239: if sizeD ! 240: push word ptr [environ+2] ; the environment is not always in DS ! 241: endif ! 242: push word ptr [environ] ! 243: ! 244: if sizeD ! 245: push word ptr [__argv+2] ; the arguments are not always in DS ! 246: endif ! 247: push word ptr [__argv] ! 248: ! 249: push [__argc] ; argument count ! 250: ! 251: call main ; main ( argc , argv , envp ) ! 252: ! 253: ; use whatever is in ax after returning here from the main program ! 254: ! 255: push ax ! 256: call exit ; exit (AX) ! 257: ; _exit will call terminators ! 258: ! 259: page ! 260: ;*** ! 261: ;_amsg_exit, _cintDIV - Fast exit fatal errors ! 262: ; ! 263: ;Purpose: ! 264: ; Exit the program with error code of 255 and appropriate error ! 265: ; message. cintDIV is used for integer divide by zero, amsg_exit ! 266: ; is for other run time errors. ! 267: ; ! 268: ;Entry: ! 269: ; AX = error message number (amsg_exit only). ! 270: ; ! 271: ;Exit: ! 272: ; calls exit() [cintDIV] or indirect through _aexit_rtn [amsg_exit]. ! 273: ; ! 274: ;Uses: ! 275: ; ! 276: ;Exceptions: ! 277: ; ! 278: ;******************************************************************************* ! 279: ! 280: labelNP <PUBLIC,_cintDIV> ! 281: ! 282: ifndef IBMC20 ! 283: assumes ds,nothing ! 284: assumes ss,data ! 285: endif ; IBMC20 ! 286: ! 287: ; _NMSG_WRITE will reestablish ds = DGROUP ! 288: ! 289: mov ax,3 ; Integer divide by zero interrupt ! 290: mov [_aexit_rtn],codeoffset _exit ; call high-level exit() ! 291: ; to cause file buffer flushing ! 292: ! 293: labelNP <PUBLIC,_amsg_exit> ! 294: push ax ; message number for _NMSG_WRITE ! 295: call _FF_MSGBANNER ; run-time error message banner ! 296: call _NMSG_WRITE ; write error message to stdout ! 297: ! 298: assumes ds,data ! 299: ! 300: mov ax,255 ! 301: push ax ! 302: call word ptr [_aexit_rtn] ; _exit(255) ordinarily ! 303: ; (or exit(255) for div by 0) ! 304: ; NEAR routine pointer ! 305: ! 306: page ! 307: ;*** ! 308: ;inherit - process C_FILE_INFO variable from the environment ! 309: ; ! 310: ;Purpose: ! 311: ; locates and interprets the "C_FILE_INFO" environment variable. ! 312: ; The value of this variable is written into the "_osfile" array. ! 313: ; This routine recognizes both DOS and OS/2 formats: ! 314: ; ! 315: ; DOS: ";C_FILE_INFO" + count byte "N" + "N" data bytes + "\0" ! 316: ; ! 317: ; where each data byte is written directly into _osfile ! 318: ; except that 0xFF represents 0 ! 319: ; ! 320: ; OS/2: "_C_FILE_INFO=<AA><BB><CC><DD>" + "\0" ! 321: ; ! 322: ; In this case the variable is a null-terminated string ! 323: ; (a well-formed environment variable) where each pair ! 324: ; of successive letters form one byte in _osfile. ! 325: ; The letters are in the range "A" through "P", representing ! 326: ; 0 through 15. The first letter of each pair is the more ! 327: ; significant 4 bits of the result. ! 328: ; ! 329: ;Entry: ! 330: ; ! 331: ;Exit: ! 332: ; ! 333: ;Uses: ! 334: ; AX, BX, CX, DX, SI, DI, ES ! 335: ; ! 336: ;Exceptions: ! 337: ; ! 338: ;******************************************************************************* ! 339: ! 340: inherit proc near ! 341: mov bx,cfileln ! 342: cmp [_osmode],0 ! 343: jne not_fapi ! 344: ; ! 345: ; Set up real-mode version of ;C_FILE_INFO ! 346: ; ! 347: mov [cfile],';' ; change _C_FILE_INFO= to ;C_FILE_INFO ! 348: mov [cfilex],0 ! 349: dec bx ; length is one less ! 350: not_fapi: ! 351: xor di,di ! 352: mov es,[_aenvseg] ; ES:DI points to environment strings ! 353: mov cx,07FFFh ; environment max = 32K ! 354: cmp byte ptr es:[di],0 ! 355: jne cfilp ! 356: inc di ; first environment string is null ! 357: cfilp: ! 358: cmp byte ptr es:[di],0 ; check for end of environment ! 359: je nocfi ; yes - not found ! 360: mov si,dataOFFSET cfile ! 361: mov dx,cx ; DX has count of bytes left in environment ! 362: mov cx,bx ; BX=cfileln ! 363: repe cmpsb ; compare for '_C_FILE_INFO='/';C_FILE_INFO' ! 364: mov cx,dx ; environment max = 32K ! 365: je gotcfi ; yes - now do something with it ! 366: xor ax,ax ! 367: repne scasb ; search for end of current string ! 368: je cfilp ; keep searching ! 369: ; ! 370: jmp short nocfi ; no 00 !!! - assume end of env. ! 371: ; ! 372: ; found _C_FILE_INFO, so transfer handle info into _osfile ! 373: ; ! 374: gotcfi: ! 375: push es ! 376: push ds ! 377: ! 378: pop es ; es = DGROUP ! 379: mov si,di ; si = startup of _osfile info ! 380: pop ds ; ds = env. segment ! 381: assumes es,data ! 382: assumes ds,nothing ! 383: ! 384: mov di,dataOFFSET _osfile ; di = _osfile block ! 385: ! 386: cmp bx,cfileln ! 387: jne real_cfi ! 388: ; ! 389: ; Prot-mode _C_FILE_INFO: ! 390: ; Read in pairs of characters, expected to be ['A'..'P']. ! 391: ; Each pair represents one byte in the _osfile array. ! 392: ; A null is the normal terminator for the string. ! 393: ; ! 394: mov cl,4 ! 395: ! 396: osfile_lp: ! 397: lodsb ; get next byte (more significant 4 bits) ! 398: sub al,'A' ! 399: jb nocfi ; string should terminate with a null ! 400: shl al,cl ! 401: xchg dx,ax ; save in DL ! 402: ! 403: lodsb ; get next byte (less significant 4 bits) ! 404: sub al,'A' ! 405: jb nocfi ! 406: or al,dl ; this assumes that AL is in range ! 407: stosb ! 408: jmp short osfile_lp ! 409: ; ! 410: ; Real-mode C_FILE_INFO ! 411: ; ! 412: real_cfi: ! 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: ;------ ! 427: ! 428: nocfi: ! 429: push ss ! 430: pop ds ; ds = DGROUP ! 431: assumes ds,data ! 432: ! 433: ret ! 434: inherit endp ! 435: ! 436: sEnd ! 437: end _astart ; start address
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.