|
|
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.