]> wirehaze git hosting - MS-DOS.git/blob - v2.0/source/EXEC.ASM

wirehaze git hosting

MS-DOS v2.0 Release
[MS-DOS.git] / v2.0 / source / EXEC.ASM
1 SUBTTL $exec - load/go a program
2 PAGE
3 ;
4 ; Assembler usage:
5 ; LDS DX, name
6 ; LES BX, blk
7 ; MOV AH, Exec
8 ; MOV AL, func
9 ; INT int_command
10 ;
11 ; AL Function
12 ; -- --------
13 ; 0 Load and execute the program.
14 ; 1 Load, create the program header but do not
15 ; begin execution.
16 ; 3 Load overlay. No header created.
17 ;
18 ; AL = 0 -> load/execute program
19 ;
20 ; +---------------------------+
21 ; | WORD segment address of |
22 ; | environment. |
23 ; +---------------------------+
24 ; | DWORD pointer to ASCIZ |
25 ; | command line at 80h |
26 ; +---------------------------+
27 ; | DWORD pointer to default |
28 ; | FCB to be passed at 5Ch |
29 ; +---------------------------+
30 ; | DWORD pointer to default |
31 ; | FCB to be passed at 6Ch |
32 ; +---------------------------+
33 ;
34 ; AL = 1 -> load program
35 ;
36 ; +---------------------------+
37 ; | WORD segment address of |
38 ; | environment. |
39 ; +---------------------------+
40 ; | DWORD pointer to ASCIZ |
41 ; | command line at 80h |
42 ; +---------------------------+
43 ; | DWORD pointer to default |
44 ; | FCB to be passed at 5Ch |
45 ; +---------------------------+
46 ; | DWORD pointer to default |
47 ; | FCB to be passed at 6Ch |
48 ; +---------------------------+
49 ; | DWORD returned value of |
50 ; | CS:IP |
51 ; +---------------------------+
52 ; | DWORD returned value of |
53 ; | SS:IP |
54 ; +---------------------------+
55 ;
56 ; AL = 3 -> load overlay
57 ;
58 ; +---------------------------+
59 ; | WORD segment address where|
60 ; | file will be loaded. |
61 ; +---------------------------+
62 ; | WORD relocation factor to |
63 ; | be applied to the image. |
64 ; +---------------------------+
65 ;
66 ; Returns:
67 ; AX = exec_invalid_function
68 ; = exec_bad_format
69 ; = exec_bad_environment
70 ; = exec_not_enough_memory
71 ; = exec_file_not_found
72 ;
73
74 IF IBM
75 ZEXEC_DATA SEGMENT PUBLIC BYTE
76 ZERO = $
77 ENDIF
78
79 exec_blk DD ?
80 exec_func DB ?
81 exec_fh DW ?
82 exec_rel_fac DW ?
83 exec_res_len_para DW ?
84 exec_init_IP DW ?
85 exec_init_CS DW ?
86 exec_init_SP DW ?
87 exec_init_SS DW ?
88 exec_environ DW ?
89 exec_size DW ?
90 exec_load_block DW ?
91
92 exec_load_high DB ?
93
94 exec_internal_buffer EQU $
95 exec_signature DW ? ; must contain 4D5A (yay zibo!)
96 exec_len_mod_512 DW ? ; low 9 bits of length
97 exec_pages DW ? ; number of 512b pages in file
98 exec_rle_count DW ? ; count of reloc entries
99 exec_par_dir DW ? ; number of paragraphs before image
100 exec_min_BSS DW ? ; minimum number of para of BSS
101 exec_max_BSS DW ? ; max number of para of BSS
102 exec_SS DW ? ; stack of image
103 exec_SP DW ? ; SP of image
104 exec_chksum DW ? ; checksum of file (ignored)
105 exec_IP DW ? ; IP of entry
106 exec_CS DW ? ; CS of entry
107 exec_rle_table DW ? ; byte offset of reloc table
108 exec_iov DW ? ; overlay number (0 for root)
109 exec_dma DW ?
110 exec_internal_buffer_size EQU $-exec_internal_buffer
111
112 IF IBM
113 exec_ctrlc DB ? ; state of users ctrlc flag
114 Exec_low_seg DW ?
115 CurrentPDB DW ?
116 NUMIO DB ?
117 ZEXECDATASIZ = $-ZERO
118 ZEXECDATAEND LABEL BYTE
119 PUBLIC ZEXECDATAEND
120 ZEXEC_DATA ENDS
121 ZEXEC_CODE SEGMENT PUBLIC PARA
122 PUBLIC $EXEC
123 ZERO = $
124 procedure $EXEC,FAR
125 ASSUME CS:EGROUP,SS:RESGROUP,ES:NOTHING,DS:NOTHING
126 ENDIF
127 IF NOT IBM
128 procedure $Exec,NEAR
129 ASSUME DS:NOTHING, ES:NOTHING
130 ENDIF
131 ;
132 ; validate function
133 ;
134
135 IF IBM
136 PUSH CS
137 POP DS
138 ASSUME DS:EGROUP
139
140 MOV AX,(Set_Ctrl_C_Trapping SHL 8) + 0 ; Save current ctrl-c
141 INT int_command
142 MOV exec_ctrlc,DL
143 XOR DX,DX
144 MOV AX,(Set_Ctrl_C_Trapping SHL 8) + 1 ; Turn it off!
145 INT int_command
146
147 MOV AH,Get_current_PDB
148 INT int_command
149 MOV [CurrentPDB],BX
150 ;
151 ; set up user return stack info
152 ;
153 MOV ES,BX
154 LES BX,DWORD PTR [user_sp]
155 MOV WORD PTR ES:[PDB_user_stack+2],ES
156 MOV WORD PTR ES:[PDB_user_stack],BX
157
158 MOV AH,Get_Default_Drive
159 INT int_command
160 MOV DL,AL
161 MOV AH,Set_default_drive
162 INT int_command
163 MOV [NUMIO],AL
164 ;
165 ; determine lowest seg address for overwrite problem (round DOWN)
166 ;
167 MOV CL,4
168 MOV AX,OFFSET ZEXEC_CODE:exec_check
169 SHR AX,CL
170 PUSH CS
171 POP BX
172 ADD AX,BX
173 MOV [exec_low_seg],AX
174
175 CALL get_user_stack
176 ASSUME DS:NOTHING
177 MOV AX,[SI.user_AX]
178 MOV BX,[SI.user_BX]
179 MOV DX,[SI.user_DX]
180 MOV ES,[SI.user_ES]
181 MOV DS,[SI.user_DS]
182 ENDIF
183
184 CMP AL,3 ; only 0, 1 or 3 are allowed
185 JNA exec_check_2
186
187 exec_bad_fun:
188 error error_invalid_function
189
190 exec_ret_err:
191 transfer SYS_RET_ERR
192
193 exec_check_2:
194 CMP AL,2
195 JZ exec_bad_fun
196
197 MOV WORD PTR [exec_blk],BX ; stash args
198 MOV WORD PTR [exec_blk+2],ES
199 MOV BYTE PTR [exec_func],AL
200 MOV BYTE PTR [exec_load_high],0
201 IF IBM
202 MOV AX,(OPEN SHL 8) + 0
203 INT int_command
204 ENDIF
205 IF NOT IBM
206 XOR AL,AL ; open for reading
207 invoke $OPEN ; is the file there?
208 ENDIF
209 JC exec_ret_err
210 MOV [exec_fh],AX
211 MOV BX,AX
212 IF IBM
213 MOV AX,(ioctl SHL 8) ; get device information
214 INT int_command
215 ENDIF
216 IF NOT IBM
217 XOR AL,AL
218 invoke $IOCTL
219 ENDIF
220 TEST DL,devid_ISDEV
221 JZ exec_check_environ
222 MOV AL,exec_file_not_found
223 transfer SYS_RET_ERR
224
225 exec_check_environ:
226 MOV [exec_load_block],0
227
228 TEST BYTE PTR [exec_func],exec_func_overlay ; overlays... no environment
229 JNZ exec_read_header
230 LDS SI,DWORD PTR [exec_blk] ; get block
231 MOV AX,[SI].Exec1_environ ; address of environ
232 OR AX,AX
233 JNZ exec_scan_env
234 MOV DS,[CurrentPDB]
235 MOV AX,DS:[PDB_environ]
236 MOV [exec_environ],AX
237 OR AX,AX
238 JZ exec_read_header
239
240 exec_scan_env:
241 CLD
242 MOV ES,AX
243 XOR DI,DI
244 MOV CX,07FFFh ; at most 32k of environment
245 XOR AL,AL
246
247 exec_get_environ_len:
248 REPNZ SCASB ; find that nul byte
249 JZ exec_check ; CX is out... bad environment
250 MOV AL,exec_bad_environment
251 JMP exec_bomb
252
253 exec_check:
254 SCASB ; is there another nul byte?
255 JNZ exec_get_environ_len ; no, scan some more
256 PUSH DI
257 MOV BX,DI ; AX <- length of environment
258 ADD BX,0Fh
259 MOV CL,4
260 SHR BX,CL ; number of paragraphs needed
261 PUSH ES
262 IF IBM
263 MOV AH,ALLOC
264 INT int_command
265 ENDIF
266 IF NOT IBM
267 invoke $ALLOC ; can we get the space?
268 ENDIF
269 POP DS
270 POP CX
271 JNC exec_save_environ
272 JMP exec_no_mem ; nope... cry and sob
273
274 exec_save_environ:
275 MOV ES,AX
276 MOV [exec_environ],AX ; save him for a rainy day
277 IF IBM
278 PUSH CX
279 MOV CX,ES
280 ADD CX,BX
281 CMP BX,[exec_low_seg]
282 POP CX
283 JA exec_no_mem
284 ENDIF
285 XOR SI,SI
286 XOR DI,DI
287 REP MOVSB ; copy the environment
288
289 exec_read_header:
290 ;
291 ; We read in the program header into the above data area and determine
292 ; where in this memory the image will be located.
293 ;
294 IF IBM
295 PUSH CS
296 POP DS ; and put it in DS:DX
297 ASSUME DS:EGROUP
298 ENDIF
299 IF NOT IBM
300 PUSH SS
301 POP DS ; and put it in DS:DX
302 ASSUME DS:DOSGROUP
303 ENDIF
304 MOV CX,exec_internal_buffer_size; header size
305 MOV BX,[exec_fh] ; from the handle
306 IF IBM
307 MOV DX,OFFSET EGROUP:exec_signature
308 ENDIF
309 IF NOT IBM
310 MOV DX,OFFSET DOSGROUP:exec_signature
311 ENDIF
312 PUSH ES
313 PUSH DS
314 CALL exec_dealloc
315 IF IBM
316 MOV AH,READ
317 INT int_command
318 ENDIF
319 IF NOT IBM
320 invoke $READ
321 ENDIF
322 CALL exec_alloc
323 POP DS
324 POP ES
325 JC exec_bad_file
326 CMP AX,exec_internal_buffer_size; did we read the right number?
327 JNZ exec_com_filej ; yep... continue
328 CMP [exec_max_BSS],0
329 JNZ exec_check_sig
330 MOV [exec_load_high],-1
331 exec_check_sig:
332 MOV AX,[exec_signature]
333 CMP AX,exe_valid_signature ; zibo arises!
334 JZ exec_save_start ; assume com file if no signature
335 CMP AX,exe_valid_old_signature ; zibo arises!
336 JZ exec_save_start ; assume com file if no signature
337
338 exec_com_filej:
339 JMP exec_com_file
340
341 ;
342 ; We have the program header... determine memory requirements
343 ;
344 exec_save_start:
345 MOV AX,[exec_pages] ; get 512-byte pages
346 MOV CL,5 ; convert to paragraphs
347 SHL AX,CL
348 SUB AX,[exec_par_dir] ; AX = size in paragraphs
349 MOV [exec_res_len_para],AX
350
351 ;
352 ; Do we need to allocate memory? Yes if function is not load-overlay
353 ;
354 TEST BYTE PTR [exec_func],exec_func_overlay
355 JZ exec_allocate ; allocation of space
356 ;
357 ; get load address from block
358 ;
359 LES DI,DWORD PTR [exec_blk]
360 MOV AX,ES:[DI].exec3_load_addr
361 MOV [exec_dma],AX
362 MOV AX,ES:[DI].exec3_reloc_fac
363 MOV [exec_rel_fac],AX
364 IF IBM
365 JMP exec_find_res
366 ENDIF
367 IF NOT IBM
368 JMP SHORT exec_find_res
369 ENDIF
370
371 exec_no_mem:
372 MOV AL,exec_not_enough_memory
373 JMP SHORT exec_bomb ; AX should be set by $ALLOC
374
375 exec_bad_file:
376 MOV AL,exec_bad_format
377
378 exec_bomb:
379 ASSUME DS:NOTHING,ES:NOTHING
380 PUSH AX
381 MOV BX,[exec_fh]
382 CALL exec_dealloc
383 IF IBM
384 MOV AH,CLOSE
385 INT int_command
386 ENDIF
387 IF NOT IBM
388 invoke $CLOSE
389 ENDIF
390 POP AX
391 transfer SYS_RET_ERR
392
393 exec_allocate:
394 IF IBM
395 ASSUME DS:EGROUP
396 ENDIF
397 IF NOT IBM
398 ASSUME DS:DOSGROUP
399 ENDIF
400 PUSH AX
401 MOV BX,0FFFFh ; see how much room in arena
402 PUSH DS
403 IF IBM
404 MOV AH,ALLOC
405 INT int_command
406 ENDIF
407 IF NOT IBM
408 invoke $ALLOC ; should have carry set and BX has max
409 ENDIF
410 POP DS
411 POP AX
412 ADD AX,10h ; room for header
413 CMP BX,11h ; enough room for a header
414 JB exec_no_mem
415 CMP AX,BX ; is there enough for bare image?
416 JA exec_no_mem
417 CMP [exec_load_high],0 ; if load high, use max
418 JNZ exec_BX_max ; use max
419 ADD AX,[exec_min_BSS] ; go for min allocation
420 JC exec_no_mem ; oops! carry
421 CMP AX,BX ; enough space?
422 JA exec_no_mem ; nope...
423 SUB AX,[exec_min_BSS]
424 ADD AX,[exec_max_BSS] ; go for the MAX
425 JC exec_BX_max
426 CMP AX,BX
427 JBE exec_got_block
428
429 exec_BX_max:
430 MOV AX,BX
431
432 exec_got_block:
433 PUSH DS
434 MOV BX,AX
435 MOV [exec_size],BX
436 IF IBM
437 MOV AH,ALLOC
438 INT int_command
439 ENDIF
440 IF NOT IBM
441 invoke $ALLOC ; get the space
442 ENDIF
443 POP DS
444 JC exec_no_mem
445 MOV [exec_load_block],AX
446 ADD AX,10h
447 CMP [exec_load_high],0
448 JZ exec_use_ax ; use ax for load info
449 ADD AX,[exec_size] ; go to end
450 SUB AX,[exec_res_len_para] ; drop off header
451 SUB AX,10h ; drop off pdb
452 exec_use_ax:
453 MOV [exec_rel_fac],AX ; new segment
454 MOV [exec_dma],AX ; beginning of dma
455 IF IBM
456 CMP AX,[exec_low_seg] ; below loader
457 JA exec_no_mem_try
458 ADD AX,[exec_res_len_para] ; go to end
459 CMP Ax,[exec_low_seg] ; above loader
460 JBE exec_find_res
461 exec_try_high:
462 CMP [exec_load_high],0
463 JZ exec_no_memj1
464 exec_try_just_below:
465 MOV DX,AX
466 SUB DX,[exec_size] ; get beginning
467 ADD DX,[exec_res_len_para] ; no space
468 CMP DX,[exec_low_seg] ; room there?
469 JA exec_no_memj1
470 MOV AX,[exec_low_seg]
471 SUB AX,[exec_res_len_para]
472 JMP exec_use_ax
473 exec_no_mem_try:
474 MOV DX,CS
475 ADD DX,(zexecdatasiz+zexeccodesize+15)/16
476 CMP AX,DX
477 JAE exec_try_high
478 JMP exec_try_just_below
479 exec_no_memj1:
480 JMP exec_no_mem
481 ENDIF
482
483 ;
484 ; Determine the location in the file of the beginning of the resident
485 ;
486 exec_find_res:
487 MOV DX,[exec_par_dir]
488 PUSH DX
489 MOV CL,4
490 SHL DX,CL ; low word of location
491 POP AX
492 MOV CL,12
493 SHR AX,CL ; high word of location
494 MOV CX,AX ; CX <- high
495
496 ;
497 ; Read in the resident image (first, seek to it)
498 ;
499 MOV BX,[exec_fh]
500 PUSH DS
501 IF IBM
502 MOV AX,(LSEEK SHL 8) + 0
503 INT int_command
504 ENDIF
505 IF NOT IBM
506 XOR AL,AL
507 invoke $LSEEK ; seek to resident
508 ENDIF
509 POP DS
510
511 exec_big_read: ; Read resident into memory
512 MOV BX,[exec_res_len_para]
513 CMP BX,1000h ; too many bytes to read?
514 JB exec_read_ok
515 MOV BX,0FE0h ; max in one chunk FE00 bytes
516
517 exec_read_ok:
518 SUB [exec_res_len_para],BX ; we read (soon) this many
519 PUSH BX
520 MOV CL,4
521 SHL BX,CL ; get count in bytes from paras
522 MOV CX,BX ; count in correct register
523 MOV BX,[exec_fh] ; handle in correct register
524 PUSH DS
525 MOV DS,[exec_dma] ; Set up read buffer
526 ASSUME DS:NOTHING
527 XOR DX,DX
528 PUSH CX ; save our count
529 CALL exec_dealloc
530 IF IBM
531 MOV AH,READ
532 INT int_command
533 ENDIF
534 IF NOT IBM
535 invoke $READ ; WOMP!
536 ENDIF
537 CALL exec_alloc
538 POP CX ; get old count to verify
539 POP DS
540 IF IBM
541 ASSUME DS:EGROUP
542 ENDIF
543 IF NOT IBM
544 ASSUME DS:DOSGROUP
545 ENDIF
546 CMP CX,AX ; did we read enough?
547 POP BX ; get paragraph count back
548 JNZ exec_do_reloc ; and do reloc if no more to read
549 ;
550 ; We've read in CX bytes... bump DTA location
551 ;
552
553 ADD [exec_dma],BX ; bump dma address
554 CMP [exec_res_len_para],0
555 JNZ exec_big_read
556
557 ;
558 ; The image has now been read in. We must perform relocation to
559 ; the current location.
560 ;
561
562 exec_do_reloc:
563 MOV CX,[exec_rel_fac]
564 MOV AX,[exec_SS] ; get initial SS
565 ADD AX,CX ; and relocate him
566 MOV [exec_init_SS],AX
567
568 MOV AX,[exec_SP] ; initial SP
569 MOV [exec_init_SP],AX
570
571 LES AX,DWORD PTR [exec_IP]
572 MOV [exec_init_IP],AX
573 MOV AX,ES
574 ADD AX,CX ; relocated...
575 MOV [exec_init_CS],AX
576
577 XOR CX,CX
578 MOV DX,[exec_rle_table]
579 MOV BX,[exec_fh]
580 PUSH DS
581 IF IBM
582 MOV AX,(LSEEK SHL 8) + 0
583 INT int_command
584 ENDIF
585 IF NOT IBM
586 XOR AX,AX
587 invoke $LSEEK
588 ENDIF
589 POP DS
590
591 JNC exec_get_entries
592 exec_bad_filej:
593 JMP exec_bad_file
594
595 exec_get_entries:
596 MOV DX,[exec_rle_count] ; Number of entries left
597
598 exec_read_reloc:
599 ASSUME DS:NOTHING
600 PUSH DX
601 IF IBM
602 MOV DX,OFFSET EGROUP:exec_signature
603 ENDIF
604 IF NOT IBM
605 MOV DX,OFFSET DOSGROUP:exec_signature
606 ENDIF
607 MOV CX,((exec_internal_buffer_size)/4)*4
608 MOV BX,[exec_fh]
609 PUSH DS
610 CALL exec_dealloc
611 IF IBM
612 MOV AH,READ
613 INT int_command
614 ENDIF
615 IF NOT IBM
616 invoke $READ
617 ENDIF
618 CALL exec_alloc
619 POP ES
620 POP DX
621 JC exec_bad_filej
622 MOV CX,(exec_internal_buffer_size)/4
623 IF IBM
624 MOV DI,OFFSET EGROUP:exec_signature ; Pointer to byte location in header
625 ENDIF
626 IF NOT IBM
627 MOV DI,OFFSET DOSGROUP:exec_signature ; Pointer to byte location in header
628 ENDIF
629 ;
630 ; Relocate a single address
631 ;
632 MOV SI,[exec_rel_fac]
633
634 exec_reloc_one:
635 CMP DX,0 ; Any more entries?
636 JNE exec_get_addr
637 JMP Exec_set_PDB
638
639 exec_get_addr:
640 LDS BX,DWORD PTR ES:[DI] ; Get ra/sa of entry
641 MOV AX,DS ; Relocate address of item
642 ADD AX,SI
643 MOV DS,AX
644 MOV AX,WORD PTR DS:[BX] ; Relocate item
645 ADD AX,SI
646 MOV WORD PTR DS:[BX],AX
647 ADD DI,4
648 DEC DX
649 LOOP exec_reloc_one ; End of internal buffer?
650
651 ;
652 ; We've exhausted a single buffer's worth. Read in the next piece
653 ; of the relocation table.
654 ;
655
656 PUSH ES
657 POP DS
658 JMP exec_read_reloc
659
660 exec_no_memj:
661 JMP exec_no_mem
662
663 ;
664 ; we have a .COM file. First, determine if we are merely loading an overlay.
665 ;
666 exec_com_file:
667 TEST BYTE PTR [exec_func],exec_func_overlay
668 JZ exec_alloc_com_file
669 LDS SI,DWORD PTR [exec_blk] ; get arg block
670 LODSW ; get load address
671 MOV [exec_dma],AX
672 JMP SHORT exec_64k ; read it all!
673
674 ; We must allocate the max possible size block (ick!) and set up
675 ; CS=DS=ES=SS=PDB pointer, IP=100, SP=max size of block.
676 ;
677 exec_alloc_com_file:
678 MOV BX,0FFFFh
679 IF IBM
680 MOV AH,ALLOC
681 INT int_command
682 ENDIF
683 IF NOT IBM
684 invoke $ALLOC ; largest piece available as error
685 ENDIF
686 OR BX,BX
687 JZ exec_no_memj
688 MOV [exec_size],BX ; save size of allocation block
689 IF IBM
690 MOV AH,ALLOC
691 INT int_command
692 ENDIF
693 IF NOT IBM
694 PUSH BX
695 invoke $ALLOC ; largest piece available as error
696 POP BX ; get size of block...
697 ENDIF
698 MOV [exec_load_block],AX
699 ADD AX,10h ; increment for header
700 MOV [exec_dma],AX
701 SUB BX,10h ; remember header
702 IF IBM
703 ;
704 ; need to read up to exec_low_seg (at most)
705 ;
706 MOV CX,[exec_low_seg]
707 CMP AX,CX ; is base of allocation above spot
708 JA exec_check_64k
709 SUB CX,AX
710 CMP CX,BX
711 JA exec_check_64k
712 MOV BX,CX
713
714 exec_check_64k:
715 ENDIF
716 CMP BX,1000h ; 64k or more?
717 JAE exec_64k ; yes, read only 64k
718 MOV AX,BX ; convert size to bytes
719 MOV CL,4
720 SHL AX,CL
721 JMP SHORT exec_read_com
722
723 exec_64k:
724 MOV AX,0FFFFh ; 64k-1 bytes
725
726 exec_read_com:
727 PUSH AX ; save number to read
728 MOV BX,[exec_fh] ; of com file
729 XOR CX,CX ; but seek to 0:0
730 MOV DX,CX
731 IF IBM
732 MOV AX,(LSEEK SHL 8) + 0
733 INT int_command
734 ENDIF
735 IF NOT IBM
736 XOR AX,AX ; seek relative to beginning
737 invoke $LSEEK ; back to beginning of file
738 ENDIF
739 MOV BX,[exec_fh]
740 POP CX ; number to read
741 MOV DS,[exec_dma]
742 XOR DX,DX
743 PUSH CX
744 CALL exec_dealloc
745 IF IBM
746 MOV AH,READ
747 INT int_command
748 ENDIF
749 IF NOT IBM
750 invoke $READ ; read in com file
751 ENDIF
752 CALL exec_alloc
753 POP SI ; get number of bytes to read
754 CMP AX,SI ; did we read them all?
755 IF IBM
756 JNZ exec_skip ; exactly the wrong number... no memory
757 JMP exec_no_mem
758 exec_skip:
759 ENDIF
760 IF NOT IBM
761 JZ exec_no_memj ; exactly the wrong number... no memory
762 ENDIF
763 TEST BYTE PTR [exec_func],exec_func_overlay
764 JNZ exec_set_PDB ; no starto, chumo!
765 MOV AX,[exec_DMA]
766 SUB AX,10h
767 MOV [exec_init_CS],AX
768 MOV [exec_init_IP],100h ; initial IP is 100
769 ; SI is at most FFFFh
770 DEC SI ; make room for stack
771 ; SI is at most FFFEh, room for a 0!
772 MOV [exec_init_SP],SI ; max value for read is also SP!
773 MOV [exec_init_SS],AX
774 MOV DS,AX
775 MOV WORD PTR DS:[SI],0 ; 0 for return
776
777 exec_set_PDB:
778 MOV BX,[exec_fh] ; we are finished with the file.
779 CALL exec_dealloc
780 IF IBM
781 MOV AH,CLOSE
782 INT int_command
783 ENDIF
784 IF NOT IBM
785 invoke $CLOSE ; release the jfn
786 ENDIF
787 CALL exec_alloc
788 TEST BYTE PTR [exec_func],exec_func_overlay
789 JZ exec_build_header
790 transfer SYS_RET_OK ; overlay load -> done
791
792 exec_build_header:
793 MOV DX,[exec_load_block]
794 ;
795 ; assign the space to the process
796 ;
797
798 MOV SI,arena_owner ; pointer to owner field
799
800 MOV AX,[exec_environ] ; get environ pointer
801 OR AX,AX
802 JZ NO_OWNER ; no environment
803 DEC AX ; point to header
804 MOV DS,AX
805 MOV DS:[SI],DX ; assign ownership
806 NO_OWNER:
807 MOV AX,[exec_load_block] ; get load block pointer
808 DEC AX
809 MOV DS,AX ; point to header
810 MOV DS:[SI],DX ; assign ownership
811
812 PUSH DX
813 IF IBM
814 MOV AH,DUP_PDB
815 INT int_command
816 MOV ES,DX
817 MOV [CurrentPDB],DX
818 ENDIF
819 IF NOT IBM
820 MOV BYTE PTR [CreatePDB], 0FFH ; indicate a new process
821 invoke $Dup_PDB ; ES is now PDB
822 ENDIF
823 POP DX
824 PUSH [exec_environ]
825 POP ES:[PDB_environ]
826 MOV SI,[exec_size]
827 ADD SI,DX
828 MOV ES:[PDB_block_len],SI
829 ;
830 ; set up proper command line stuff
831 ;
832 LDS SI,DWORD PTR [exec_blk] ; get the block
833 PUSH DS ; save its location
834 PUSH SI
835 LDS SI,DS:[SI.exec0_5C_FCB] ; get the 5c fcb
836 MOV CX,12 ; copy drive, name and ext
837 PUSH CX
838 MOV DI,5Ch
839 MOV BL,DS:[SI]
840 REP MOVSB
841 XOR AX,AX ; zero extent, etc for CPM
842 STOSW
843 STOSW
844 POP CX
845 POP SI ; get block
846 POP DS
847 PUSH DS ; save (again)
848 PUSH SI
849 LDS SI,DS:[SI.exec0_6C_FCB] ; get 6C FCB
850 MOV DI,6Ch ; do same as above
851 MOV BH,DS:[SI]
852 REP MOVSB
853 STOSW
854 STOSW
855 POP SI ; get block (last time)
856 POP DS
857 LDS SI,DS:[SI.exec0_com_line] ; command line
858 MOV CX,80h
859 MOV DI,CX
860 REP MOVSB ; Wham!
861
862 ;
863 ; Process BX into default AX (validity of drive specs on args)
864 ;
865 DEC CL ; get 0FFh in CX
866 CMP BH,[NUMIO]
867 JBE exec_BH_good
868 MOV BH,CL
869 JMP SHORT exec_BL
870 exec_BH_good:
871 XOR BH,BH
872 exec_BL:
873 CMP BL,[NUMIO]
874 JBE exec_BL_good
875 MOV BL,CL
876 JMP SHORT exec_set_return
877 exec_BL_good:
878 XOR BL,BL
879 exec_set_return:
880 invoke get_user_stack ; get his return address
881 PUSH [SI.user_CS] ; suck out the CS and IP
882 PUSH [SI.user_IP]
883 PUSH [SI.user_CS] ; suck out the CS and IP
884 PUSH [SI.user_IP]
885 POP WORD PTR ES:[PDB_Exit]
886 POP WORD PTR ES:[PDB_Exit+2]
887 XOR AX,AX
888 MOV DS,AX
889 POP DS:[addr_int_terminate] ; save them where we can get them later
890 POP DS:[addr_int_terminate+2] ; when the child exits.
891 IF NOT IBM
892 MOV WORD PTR [DMAADD],80h
893 MOV DS,[CurrentPDB]
894 MOV WORD PTR [DMAADD+2],DS
895 ENDIF
896 IF IBM
897 PUSH DX
898 PUSH DS
899 MOV DS,[CurrentPDB]
900 MOV DX,80h
901 MOV AH,SET_DMA
902 INT int_command
903 POP DS
904 POP DX
905 ENDIF
906 TEST BYTE PTR [exec_func],exec_func_no_execute
907 JZ exec_go
908
909 LDS SI,DWORD PTR [exec_init_SP] ; get stack
910 LES DI,DWORD PTR [exec_blk] ; and block for return
911 MOV ES:[DI].exec1_SS,DS ; return SS
912
913 DEC SI ; 'push' default AX
914 DEC SI
915 MOV DS:[SI],BX ; save default AX reg
916 MOV ES:[DI].exec1_SP,SI ; return 'SP'
917
918 LDS AX,DWORD PTR [exec_init_IP]
919 MOV ES:[DI].exec1_CS,DS ; initial entry stuff
920
921 MOV ES:[DI].exec1_IP,AX
922 transfer SYS_RET_OK
923
924 exec_go:
925 IF IBM
926 CALL restore_ctrlc ; restore value of ctrl-c checker
927 ENDIF
928 LDS SI,DWORD PTR [exec_init_IP] ; get entry point
929 CLI
930 IF NOT IBM
931 MOV BYTE PTR INDOS,0
932 ENDIF
933 MOV SS,[exec_init_SS] ; set up user's stack
934 ASSUME SS:NOTHING
935 MOV SP,[exec_init_SP] ; and SP
936 STI
937 PUSH DS ; fake long call to entry
938 PUSH SI
939 MOV ES,DX ; set up proper seg registers
940 MOV DS,DX
941 MOV AX,BX ; set up proper AX
942 procedure exec_long_ret,FAR
943 RET
944 exec_long_ret ENDP
945
946 $Exec ENDP
947
948 procedure exec_dealloc,near
949 ASSUME DS:NOTHING,ES:NOTHING
950 PUSH BX
951 MOV BX,arena_owner_system
952 CALL exec_do_change_owner
953 POP BX
954 return
955 exec_dealloc ENDP
956
957 procedure exec_alloc,near
958 PUSH BX
959 MOV BX,[CurrentPDB]
960 CALL exec_do_change_owner
961 POP BX
962 return
963 exec_alloc ENDP
964
965 procedure exec_do_change_owner,NEAR
966 PUSH DS
967 PUSH AX
968 MOV AX,[exec_environ]
969 OR AX,AX
970 JZ exec_alloc_try_load
971 DEC AX
972 MOV DS,AX
973 MOV DS:[arena_owner],BX
974 exec_alloc_try_load:
975 MOV AX,[exec_load_block]
976 OR AX,AX
977 JZ exec_alloc_done
978 DEC AX
979 MOV DS,AX
980 MOV DS:[arena_owner],BX
981 exec_alloc_done:
982 POP AX
983 POP DS
984 RET
985 exec_do_change_owner ENDP
986
987 IF IBM
988 SYS_RET_ERR:
989 CALL get_user_stack
990 PUSH [SI.user_f]
991 XOR AH,AH
992 MOV [SI.user_AX],AX
993 POPF
994 STC
995 JMP SYS_RET
996 SYS_RET_OK:
997 CALL get_user_stack
998 PUSH [SI.user_f]
999 POPF
1000 CLC
1001 SYS_RET:
1002 PUSHF
1003 CALL restore_ctrlc
1004 POP [SI.user_f]
1005 JMP exec_long_ret
1006
1007 ;
1008 ; get_user_stack returns the user's stack (and hence registers) in DS:SI
1009 ;
1010 procedure get_user_stack,NEAR
1011 PUSH SS
1012 POP DS
1013 ASSUME DS:RESGROUP
1014 LDS SI,DWORD PTR [user_SP]
1015 RET
1016 get_user_stack ENDP
1017 ;
1018 ; restore value of the ctrl-c checker
1019 ;
1020 procedure restore_ctrlc
1021 PUSH AX
1022 PUSH DX
1023 MOV DL,CS:[exec_ctrlc]
1024 MOV AX,(Set_Ctrl_C_Trapping SHL 8) + 1 ; Put it back
1025 INT int_command
1026 POP DX
1027 POP AX
1028 RET
1029 restore_ctrlc ENDP
1030
1031 ZEXECCODESIZE EQU $-ZERO
1032 ZEXECCODEEND LABEL BYTE
1033 PUBLIC ZEXECCODEEND
1034 ZEXEC_CODE ENDS
1035 ENDIF