1 | ;
|
---|
2 | ; EMXL.ASM -- emx loader (emxl.exe)
|
---|
3 | ;
|
---|
4 | ; Copyright (c) 1991-1996 by Eberhard Mattes
|
---|
5 | ;
|
---|
6 | ; This file is part of emx.
|
---|
7 | ;
|
---|
8 | ; emx is free software; you can redistribute it and/or modify it
|
---|
9 | ; under the terms of the GNU General Public License as published by
|
---|
10 | ; the Free Software Foundation; either version 2, or (at your option)
|
---|
11 | ; any later version.
|
---|
12 | ;
|
---|
13 | ; emx is distributed in the hope that it will be useful,
|
---|
14 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
15 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
16 | ; GNU General Public License for more details.
|
---|
17 | ;
|
---|
18 | ; You should have received a copy of the GNU General Public License
|
---|
19 | ; along with emx; see the file COPYING. If not, write to
|
---|
20 | ; the Free Software Foundation, 59 Temple Place - Suite 330,
|
---|
21 | ; Boston, MA 02111-1307, USA.
|
---|
22 | ;
|
---|
23 | ; <START_OF_EXCEPTION>
|
---|
24 | ; As a special exception, if you bind emxl.exe to an executable file
|
---|
25 | ; (using emxbind), this does not cause the resulting executable file
|
---|
26 | ; to be covered by the GNU General Public License. This exception
|
---|
27 | ; does not however invalidate any other reasons why the executable
|
---|
28 | ; file might be covered by the GNU General Public License. However,
|
---|
29 | ; if you bind a modified copy of emxl.exe to an executable file, you
|
---|
30 | ; have to include source code for emxl.exe. When distributing
|
---|
31 | ; emxl.exe as separate file, the GPL applies without exceptions to
|
---|
32 | ; emxl.exe.
|
---|
33 | ;
|
---|
34 | ; If you modify this file, you have to replace the text between
|
---|
35 | ; the outer <START_OF_EXCEPTION> and <END_OF_EXCEPTION> markers with
|
---|
36 | ; the following paragraph (which currently does not apply as you have
|
---|
37 | ; not modified this file):
|
---|
38 | ;
|
---|
39 | ; As a special exception, if you bind emxl.exe to an executable file
|
---|
40 | ; (using emxbind), this does not cause the resulting executable file
|
---|
41 | ; to be covered by the GNU General Public License. The source code
|
---|
42 | ; for emxl.exe must be distributed with the executable file. This
|
---|
43 | ; exception does not however invalidate any other reasons why the
|
---|
44 | ; executable file might be covered by the GNU General Public License.
|
---|
45 | ; <END_OF_EXCEPTION>
|
---|
46 | ;
|
---|
47 |
|
---|
48 | INCLUDE EMX.INC
|
---|
49 | INCLUDE HEADERS.INC
|
---|
50 | INCLUDE VERSION.INC
|
---|
51 |
|
---|
52 | .8086
|
---|
53 |
|
---|
54 | ;
|
---|
55 | ; Data (the name SV_DATA stems from emx, we're using EMX.INC!)
|
---|
56 | ;
|
---|
57 | SV_DATA SEGMENT
|
---|
58 |
|
---|
59 | PSP_SEG WORD ? ; Program prefix segment
|
---|
60 | ENV_SEG WORD ? ; Environment segment
|
---|
61 | NAME_OFF WORD ? ; Offset of prog name (ENV_SEG)
|
---|
62 | NAME_LEN WORD ? ; Length of prog name
|
---|
63 |
|
---|
64 | ;
|
---|
65 | ; Parameter block for INT 21H, AX=4B00H
|
---|
66 | ;
|
---|
67 | PAR_BLOCK WORD 0 ; Copy parent's environment
|
---|
68 | WORD OFFSET CMD_LINE ; Command line
|
---|
69 | WORD SEG CMD_LINE
|
---|
70 | WORD 5CH ; FCB1
|
---|
71 | PB_SEG1 WORD ?
|
---|
72 | WORD 6CH ; FCB2
|
---|
73 | PB_SEG2 WORD ?
|
---|
74 |
|
---|
75 | ;
|
---|
76 | ; DPMI_FLAG is non-zero if a DPMI server has been found, but no
|
---|
77 | ; VCPI server
|
---|
78 | ;
|
---|
79 | DPMI_FLAG BYTE FALSE ; Initially FALSE
|
---|
80 |
|
---|
81 | ;
|
---|
82 | ; Messages
|
---|
83 | ;
|
---|
84 | $EMX_NOT_FOUND BYTE "emx not found", CR, LF, "$"
|
---|
85 | $RSX_NOT_FOUND BYTE "rsx not found, DPMI not supported by emx", CR, LF, "$"
|
---|
86 | $USE_EMXBIND BYTE "Use emxbind", CR, LF, "$"
|
---|
87 | $BAD_ENV BYTE "Bad environment", CR, LF, "$"
|
---|
88 |
|
---|
89 | ;
|
---|
90 | ; Names of devices implemented by expanded memory managers
|
---|
91 | ;
|
---|
92 | EMS_FNAME BYTE "EMMXXXX0", 0 ; EMS enabled
|
---|
93 | NOEMS_FNAME1 BYTE "EMMQXXX0", 0 ; EMS disabled
|
---|
94 | NOEMS_FNAME2 BYTE "$MMXXXX0",0 ; EMS disabled
|
---|
95 |
|
---|
96 | ;
|
---|
97 | ; Names of environment variables
|
---|
98 | ;
|
---|
99 | $EMX BYTE "EMX", 0
|
---|
100 | $PATH BYTE "PATH", 0
|
---|
101 |
|
---|
102 | ;
|
---|
103 | ; Name of emx.exe for searching in the current working directory and PATH
|
---|
104 | ;
|
---|
105 | $EMX_EXE BYTE "emx.exe", 0
|
---|
106 | EMX_EXE_LEN = THIS BYTE - $EMX_EXE ; Length of name, with 0
|
---|
107 |
|
---|
108 | ;
|
---|
109 | ; This command line is passed to emx.exe
|
---|
110 | ;
|
---|
111 | CMD_LINE BYTE 7 ; 7 bytes
|
---|
112 | BYTE "-/" ; Special marker
|
---|
113 | CMD_LINE_PSP BYTE "0000" ; PSP_SEG, hexadecimal
|
---|
114 | BYTE "/" ; Another special marker
|
---|
115 | BYTE CR ; End of command line
|
---|
116 |
|
---|
117 | ;
|
---|
118 | ; Build path name here when using directory from PATH environment variable
|
---|
119 | ;
|
---|
120 | PGM_NAME BYTE 128 DUP (?)
|
---|
121 | PGM_NAME_END LABEL BYTE
|
---|
122 |
|
---|
123 | SV_DATA ENDS
|
---|
124 |
|
---|
125 |
|
---|
126 | ;
|
---|
127 | ; This area will be patched by emxbind
|
---|
128 | ;
|
---|
129 | HDR_SEG SEGMENT
|
---|
130 | PATCH LABEL BIND_HEADER
|
---|
131 | BYTE "emx ", VERSION, 0
|
---|
132 | BYTE (SIZE BIND_HEADER - HDR_VERSION_LEN) DUP (0)
|
---|
133 | HDR_SEG ENDS
|
---|
134 |
|
---|
135 | ;
|
---|
136 | ; Code
|
---|
137 | ;
|
---|
138 | INIT_CODE SEGMENT
|
---|
139 |
|
---|
140 | ASSUME CS:INIT_CODE
|
---|
141 | ASSUME DS:NOTHING, ES:NOTHING
|
---|
142 |
|
---|
143 | ;
|
---|
144 | ; Setup data segment. Note: This macro modifies AX.
|
---|
145 | ;
|
---|
146 | SET_DS MACRO
|
---|
147 | MOV AX, SV_DATA
|
---|
148 | MOV DS, AX
|
---|
149 | ASSUME DS:SV_DATA
|
---|
150 | ENDM
|
---|
151 |
|
---|
152 | ;
|
---|
153 | ; The program starts here
|
---|
154 | ;
|
---|
155 | ENTRY: SET_DS ; Setup data segment
|
---|
156 | MOV PSP_SEG, ES ; Save program prefix segment
|
---|
157 | CALL INIT ; Initialize
|
---|
158 | CALL CHECK_DPMI ; Check for DPMI
|
---|
159 | CALL GET_NAME ; Get program name
|
---|
160 | CALL BIND_HDR ; Check patch area
|
---|
161 | CALL TRY_EMX_ENV ; Use EMX environment variable
|
---|
162 | CALL TRY_CWD ; Search current directory
|
---|
163 | CALL TRY_PATH ; Use PATH environment variable
|
---|
164 | LEA DX, $EMX_NOT_FOUND ; Give up
|
---|
165 | CMP DPMI_FLAG, FALSE
|
---|
166 | JE FAIL
|
---|
167 | LEA DX, $RSX_NOT_FOUND
|
---|
168 | FAIL: JMP ABORT
|
---|
169 |
|
---|
170 | ;
|
---|
171 | ; Initialization
|
---|
172 | ;
|
---|
173 | INIT PROC NEAR
|
---|
174 | MOV AX, PSP_SEG
|
---|
175 | MOV PB_SEG1, AX ; Fill in parameter block
|
---|
176 | MOV PB_SEG2, AX ; for DOS function 4BH (EXEC)
|
---|
177 | MOV ES, AX
|
---|
178 | MOV AX, ES:[2CH] ; Get environment segment
|
---|
179 | MOV ENV_SEG, AX
|
---|
180 | LEA BX, CMD_LINE_PSP ; Insert PSP_SEG, hexadecimal
|
---|
181 | MOV CX, 0404H ; 4 digits, shift by 4 bits
|
---|
182 | MOV DX, PSP_SEG
|
---|
183 | INIT_1: ROL DX, CL
|
---|
184 | MOV AL, DL
|
---|
185 | AND AL, 0FH
|
---|
186 | ADD AL, "0"
|
---|
187 | CMP AL, "9"
|
---|
188 | JBE INIT_2
|
---|
189 | ADD AL, "A" - ("0" + 10)
|
---|
190 | INIT_2: MOV [BX], AL
|
---|
191 | INC BX
|
---|
192 | DEC CH
|
---|
193 | JNZ INIT_1
|
---|
194 | RET
|
---|
195 | INIT ENDP
|
---|
196 |
|
---|
197 |
|
---|
198 | ;
|
---|
199 | ; Check for DPMI server
|
---|
200 | ;
|
---|
201 | CHECK_DPMI PROC NEAR
|
---|
202 | MOV AX, 1687H ; Check for DPMI server
|
---|
203 | INT 2FH
|
---|
204 | OR AX, AX ; Server present?
|
---|
205 | JNZ DPMI_RET ; No -> call emx.exe
|
---|
206 | TEST BX, 1 ; 32-bit programs supported?
|
---|
207 | JZ DPMI_RET ; No -> hope we can get VCPI
|
---|
208 | ;
|
---|
209 | ; Now we have detected a DPMI server. Run rsx if we don't find a
|
---|
210 | ; VCPI server. First we have to check for an EMM.
|
---|
211 | ;
|
---|
212 | ; First, check the EMS interrupt vector
|
---|
213 | ;
|
---|
214 | MOV AX, 3567H ; Get interrupt vector 67H
|
---|
215 | INT 21H
|
---|
216 | MOV AX, ES
|
---|
217 | OR AX, BX ; Is the vector 0:0 ?
|
---|
218 | JZ NO_VCPI ; Yes -> no VCPI
|
---|
219 | ;
|
---|
220 | ; Check for an EMM with EMS enabled
|
---|
221 | ;
|
---|
222 | LEA DX, EMS_FNAME
|
---|
223 | CALL CHECK_EMM ; EMS present?
|
---|
224 | JC EMM_DISABLED ; No -> try disabled EMS
|
---|
225 | ;
|
---|
226 | ; Check EMM status
|
---|
227 | ;
|
---|
228 | MOV AH, 40H ; Get EMM status
|
---|
229 | INT 67H
|
---|
230 | CMP AH, 0 ; Successful?
|
---|
231 | JE EMM_OK ; Yes -> check VCPI
|
---|
232 | JMP NO_VCPI ; No VCPI
|
---|
233 |
|
---|
234 | ;
|
---|
235 | ; Check for an EMM with EMS disabled (using undocumented "features")
|
---|
236 | ;
|
---|
237 | EMM_DISABLED: LEA DX, NOEMS_FNAME1
|
---|
238 | CALL CHECK_EMM
|
---|
239 | JNC EMM_OK ; EMM present
|
---|
240 | LEA DX, NOEMS_FNAME2
|
---|
241 | CALL CHECK_EMM
|
---|
242 | JC NO_VCPI ; No EMM present -> no VCPI
|
---|
243 | ;
|
---|
244 | ; There is an EMM with EMS enabled or disabled. Check for VCPI
|
---|
245 | ;
|
---|
246 | EMM_OK: MOV AX, 0DE00H ; VCPI presence detection
|
---|
247 | INT 67H
|
---|
248 | CMP AH, 0 ; VCPI present?
|
---|
249 | JE DPMI_RET ; Yes -> use emx
|
---|
250 | ;
|
---|
251 | ; Now we have found a DPMI server, but no VCPI server. We
|
---|
252 | ; should use rsx instead of emx
|
---|
253 | ;
|
---|
254 | NO_VCPI: MOV DPMI_FLAG, NOT FALSE ; Set flag
|
---|
255 | MOV AX, "SR" ; First 2 letters of "RSX"
|
---|
256 | MOV WORD PTR $EMX, AX ; Patch name of env. variable
|
---|
257 | MOV AX, "sr" ; First 2 letters of "rsx.exe"
|
---|
258 | MOV WORD PTR $EMX_EXE, AX ; Patch name of executable
|
---|
259 | DPMI_RET: RET
|
---|
260 | CHECK_DPMI ENDP
|
---|
261 |
|
---|
262 |
|
---|
263 | ;
|
---|
264 | ; Check for the presence of an expanded memory manager (emx.exe
|
---|
265 | ; will perform more complete checks)
|
---|
266 | ;
|
---|
267 | ; In: DX Pointer to device name
|
---|
268 | ;
|
---|
269 | ; Out: NC EMM present
|
---|
270 | ;
|
---|
271 | CHECK_EMM PROC NEAR
|
---|
272 | MOV AX, 3D00H ; Open
|
---|
273 | INT 21H
|
---|
274 | JC CE_RET
|
---|
275 | ;
|
---|
276 | ; A file or device with that name exists. Check for a device
|
---|
277 | ;
|
---|
278 | MOV BX, AX ; Handle
|
---|
279 | MOV AX, 4400H ; IOCTL: get device data
|
---|
280 | INT 21H
|
---|
281 | JC CE_FAIL ; Failure -> no EMM
|
---|
282 | TEST DL, 80H ; Device?
|
---|
283 | JZ CE_FAIL ; No -> no EMM
|
---|
284 | MOV AX, 4407H ; IOCTL: check output status
|
---|
285 | INT 21H
|
---|
286 | JC CE_FAIL ; Failure -> no EMM
|
---|
287 | CMP AL, 0FFH ; Ready?
|
---|
288 | JNE CE_FAIL ; No -> no EMM
|
---|
289 | MOV AH, 3EH ; Close
|
---|
290 | INT 21H
|
---|
291 | CLC
|
---|
292 | CE_RET: RET
|
---|
293 |
|
---|
294 | CE_FAIL: MOV AH, 3EH ; Close
|
---|
295 | INT 21H
|
---|
296 | STC
|
---|
297 | RET
|
---|
298 | CHECK_EMM ENDP
|
---|
299 |
|
---|
300 |
|
---|
301 | ;
|
---|
302 | ; Find program name
|
---|
303 | ;
|
---|
304 | GET_NAME PROC NEAR
|
---|
305 | MOV ES, ENV_SEG ; Scan environment
|
---|
306 | XOR DI, DI ; starting at offset 0
|
---|
307 | MOV CX, 8000H ; Maximum environment size
|
---|
308 | XOR AL, AL ; Search for bytes of zeros
|
---|
309 | CLD ; Incrementing
|
---|
310 | GET_NAME_1: REPNE SCAS BYTE PTR ES:[DI] ; Skip string
|
---|
311 | JNE GET_NAME_ERR ; Count exhausted -> error
|
---|
312 | SCAS BYTE PTR ES:[DI] ; End of environment?
|
---|
313 | JE GET_NAME_9 ; Yes -> program name found
|
---|
314 | LOOP GET_NAME_1 ; Next string, 1st char skipped
|
---|
315 | GET_NAME_ERR: LEA DX, $BAD_ENV ; Bad environment
|
---|
316 | JMP ABORT
|
---|
317 |
|
---|
318 | GET_NAME_9: ADD DI, 2 ; Skip count
|
---|
319 | MOV NAME_OFF, DI ; Offset of program name
|
---|
320 | CALL STRLEN ; Compute length
|
---|
321 | MOV NAME_LEN, CX
|
---|
322 | RET
|
---|
323 | GET_NAME ENDP
|
---|
324 |
|
---|
325 |
|
---|
326 | ;
|
---|
327 | ; Check emxbind patch area
|
---|
328 | ;
|
---|
329 | BIND_HDR PROC NEAR
|
---|
330 | MOV AX, HDR_SEG
|
---|
331 | MOV ES, AX ; Access emxbind patch area
|
---|
332 | ASSUME ES:HDR_SEG
|
---|
333 | CMP PATCH.BND_BIND_FLAG, FALSE ; Bound?
|
---|
334 | JNE BIND_HDR_1 ; Yes -> continue
|
---|
335 | LEA DX, $USE_EMXBIND ; Must be bound to a.out
|
---|
336 | JMP ABORT
|
---|
337 | BIND_HDR_1: RET
|
---|
338 | BIND_HDR ENDP
|
---|
339 |
|
---|
340 | ASSUME ES:NOTHING
|
---|
341 |
|
---|
342 | ;
|
---|
343 | ; Display error message and abort program
|
---|
344 | ;
|
---|
345 | ; In: DX Offset of dollar-delimited error message in SV_DATA
|
---|
346 | ;
|
---|
347 | ABORT: SET_DS ; This can't hurt
|
---|
348 | MOV AH, 09H ; Display string
|
---|
349 | INT 21H
|
---|
350 | MOV AX, 4C01H ; Terminate process, rc=1
|
---|
351 | INT 21H
|
---|
352 |
|
---|
353 | ;
|
---|
354 | ; Try to find emx.exe using EMX environment variable
|
---|
355 | ;
|
---|
356 | TRY_EMX_ENV PROC NEAR
|
---|
357 | LEA BX, $EMX
|
---|
358 | CALL GETENV
|
---|
359 | JC TRY_EMX_ENV_RET
|
---|
360 | MOV DX, DI
|
---|
361 | MOV_DS_ES
|
---|
362 | ASSUME DS:NOTHING
|
---|
363 | CALL SPAWN
|
---|
364 | ASSUME DS:SV_DATA
|
---|
365 | TRY_EMX_ENV_RET:RET
|
---|
366 | TRY_EMX_ENV ENDP
|
---|
367 |
|
---|
368 | ;
|
---|
369 | ; Try to find emx.exe in current working directory
|
---|
370 | ;
|
---|
371 | TRY_CWD PROC NEAR
|
---|
372 | LEA DX, $EMX_EXE
|
---|
373 | CALL SPAWN
|
---|
374 | RET
|
---|
375 | TRY_CWD ENDP
|
---|
376 |
|
---|
377 | ;
|
---|
378 | ; Try to find emx.exe in the directories listed in the PATH environment
|
---|
379 | ; variable
|
---|
380 | ;
|
---|
381 | TRY_PATH PROC NEAR
|
---|
382 | LEA BX, $PATH
|
---|
383 | CALL GETENV
|
---|
384 | JC TRY_PATH_RET
|
---|
385 | MOV SI, DI
|
---|
386 | FIND_2: LEA DI, PGM_NAME
|
---|
387 | FIND_3: MOV AL, ES:[SI]
|
---|
388 | INC SI
|
---|
389 | OR AL, AL
|
---|
390 | JZ TRY_PATH_RET
|
---|
391 | CMP AL, " "
|
---|
392 | JE FIND_3
|
---|
393 | CMP AL, TAB
|
---|
394 | JE FIND_3
|
---|
395 | CMP AL, ";"
|
---|
396 | JE FIND_3
|
---|
397 | FIND_4: CMP DI, OFFSET PGM_NAME_END
|
---|
398 | JAE FIND_5
|
---|
399 | MOV [DI], AL
|
---|
400 | MOV AH, AL
|
---|
401 | INC DI
|
---|
402 | FIND_5: MOV AL, ES:[SI]
|
---|
403 | INC SI
|
---|
404 | OR AL, AL
|
---|
405 | JZ FIND_6
|
---|
406 | CMP AL, " "
|
---|
407 | JE FIND_5
|
---|
408 | CMP AL, TAB
|
---|
409 | JE FIND_5
|
---|
410 | CMP AL, ";"
|
---|
411 | JNE FIND_4
|
---|
412 | FIND_6: DEC SI
|
---|
413 | CMP DI, OFFSET PGM_NAME_END - EMX_EXE_LEN
|
---|
414 | JAE FIND_2
|
---|
415 | ;
|
---|
416 | ; We don't support DBCS in emxl.exe: PATH should not contain directories
|
---|
417 | ; whose name ends with a DBCS characters whose 2nd byte is 2F, 3AH, or 5CH.
|
---|
418 | ;
|
---|
419 | CMP AH, "\"
|
---|
420 | JE FIND_7
|
---|
421 | CMP AH, "/"
|
---|
422 | JE FIND_7
|
---|
423 | CMP AH, ":"
|
---|
424 | JE FIND_7
|
---|
425 | CMP DI, OFFSET PGM_NAME_END
|
---|
426 | JAE FIND_7
|
---|
427 | MOV BYTE PTR DS:[DI], "\"
|
---|
428 | INC DI
|
---|
429 | FIND_7: PUSH ES
|
---|
430 | PUSH SI
|
---|
431 | LEA SI, $EMX_EXE
|
---|
432 | MOV CX, EMX_EXE_LEN
|
---|
433 | FIND_8: LODSB
|
---|
434 | MOV [DI], AL
|
---|
435 | INC DI
|
---|
436 | LOOP FIND_8
|
---|
437 | LEA DX, PGM_NAME
|
---|
438 | CALL SPAWN
|
---|
439 | POP SI
|
---|
440 | POP ES
|
---|
441 | JMP FIND_2
|
---|
442 |
|
---|
443 | TRY_PATH_RET: RET
|
---|
444 |
|
---|
445 | TRY_PATH ENDP
|
---|
446 |
|
---|
447 |
|
---|
448 |
|
---|
449 | ;
|
---|
450 | ; Find environment entry
|
---|
451 | ;
|
---|
452 | ; In: BX Points to zero-terminated name of environment variable
|
---|
453 | ;
|
---|
454 | ; Out: CY Not found
|
---|
455 | ; NC Found
|
---|
456 | ; DI Points to value of environment variable
|
---|
457 | ;
|
---|
458 |
|
---|
459 | ASSUME DS:SV_DATA
|
---|
460 |
|
---|
461 | GETENV PROC NEAR
|
---|
462 | MOV ES, ENV_SEG
|
---|
463 | XOR DI, DI
|
---|
464 | CLD
|
---|
465 | GETENV_NEXT: CMP BYTE PTR ES:[DI], 0 ; Empty environment?
|
---|
466 | JE GETENV_FAILURE ; Yes -> not found
|
---|
467 | PUSH BX ; Save pointer to name
|
---|
468 | GETENV_COMPARE: MOV AL, [BX]
|
---|
469 | CMP AL, ES:[DI] ; Compare names
|
---|
470 | JNE GETENV_DIFF ; Mismatch -> try next one
|
---|
471 | OR AL, AL ; Shouldn't happen (`='!)
|
---|
472 | JZ GETENV_DIFF ; (name matches completely)
|
---|
473 | INC BX
|
---|
474 | INC DI
|
---|
475 | JMP GETENV_COMPARE ; Compare next character
|
---|
476 | GETENV_DIFF: POP BX ; Restore pointer to name
|
---|
477 | OR AL, AL ; End of name reached?
|
---|
478 | JE GETENV_EQUAL ; Yes -> candidate found
|
---|
479 | GETENV_SKIP: XOR AL, AL
|
---|
480 | MOV CX, 32767 ; Search for next entry
|
---|
481 | REPNE SCAS BYTE PTR ES:[DI]
|
---|
482 | JMP GETENV_NEXT ; Check that entry
|
---|
483 |
|
---|
484 | GETENV_EQUAL: CMP BYTE PTR ES:[DI], "=" ; Exact match?
|
---|
485 | JNE GETENV_SKIP ; No -> go to next entry
|
---|
486 | INC DI ; Skip `='
|
---|
487 | CLC
|
---|
488 | JMP GETENV_RET ; Return pointer to value
|
---|
489 |
|
---|
490 | GETENV_FAILURE: STC ; Not found
|
---|
491 | GETENV_RET: RET
|
---|
492 |
|
---|
493 | GETENV ENDP
|
---|
494 |
|
---|
495 | ;
|
---|
496 | ; Compute the length of a zero-terminated string
|
---|
497 | ;
|
---|
498 | ; In: ES:SI Points to string
|
---|
499 | ;
|
---|
500 | ; Out: CX Length
|
---|
501 | ;
|
---|
502 | STRLEN PROC NEAR
|
---|
503 | XOR CX, CX
|
---|
504 | XOR AL, AL
|
---|
505 | STRLEN_1: SCASB
|
---|
506 | JE STRLEN_2
|
---|
507 | INC CX
|
---|
508 | JMP STRLEN_1
|
---|
509 | STRLEN_2: RET
|
---|
510 | STRLEN ENDP
|
---|
511 |
|
---|
512 | ;
|
---|
513 | ; Try to run a program. Exit if successful, return if failed.
|
---|
514 | ;
|
---|
515 | ; In: DS:DX Points to path name of program
|
---|
516 | ;
|
---|
517 | ; Out: DS SV_DATA
|
---|
518 | ;
|
---|
519 |
|
---|
520 | ASSUME DS:NOTHING
|
---|
521 |
|
---|
522 | SPAWN PROC NEAR
|
---|
523 | MOV AX, SV_DATA
|
---|
524 | MOV ES, AX
|
---|
525 | ASSUME ES:SV_DATA
|
---|
526 | LEA BX, PAR_BLOCK ; ES:BX -> parameter block
|
---|
527 | MOV AX, 4B00H ; Load and execute program
|
---|
528 | INT 21H
|
---|
529 | SET_DS ; Restore data segment
|
---|
530 | JNC DONE ; Success -> terminate
|
---|
531 | RET
|
---|
532 |
|
---|
533 | DONE: MOV AH, 4DH ; Get return code of child
|
---|
534 | INT 21H ; process
|
---|
535 | MOV AH, 4CH ; terminate process
|
---|
536 | INT 21H
|
---|
537 |
|
---|
538 | SPAWN ENDP
|
---|
539 |
|
---|
540 | ASSUME ES:NOTHING
|
---|
541 |
|
---|
542 |
|
---|
543 | INIT_CODE ENDS
|
---|
544 |
|
---|
545 |
|
---|
546 | RM_STACK SEGMENT
|
---|
547 | WORD 256 DUP (?)
|
---|
548 | RM_STACK ENDS
|
---|
549 |
|
---|
550 | END ENTRY
|
---|