SUBTTL $exec - load/go a program PAGE ; ; Assembler usage: ; LDS DX, name ; LES BX, blk ; MOV AH, Exec ; MOV AL, func ; INT int_command ; ; AL Function ; -- -------- ; 0 Load and execute the program. ; 1 Load, create the program header but do not ; begin execution. ; 3 Load overlay. No header created. ; ; AL = 0 -> load/execute program ; ; +---------------------------+ ; | WORD segment address of | ; | environment. | ; +---------------------------+ ; | DWORD pointer to ASCIZ | ; | command line at 80h | ; +---------------------------+ ; | DWORD pointer to default | ; | FCB to be passed at 5Ch | ; +---------------------------+ ; | DWORD pointer to default | ; | FCB to be passed at 6Ch | ; +---------------------------+ ; ; AL = 1 -> load program ; ; +---------------------------+ ; | WORD segment address of | ; | environment. | ; +---------------------------+ ; | DWORD pointer to ASCIZ | ; | command line at 80h | ; +---------------------------+ ; | DWORD pointer to default | ; | FCB to be passed at 5Ch | ; +---------------------------+ ; | DWORD pointer to default | ; | FCB to be passed at 6Ch | ; +---------------------------+ ; | DWORD returned value of | ; | CS:IP | ; +---------------------------+ ; | DWORD returned value of | ; | SS:IP | ; +---------------------------+ ; ; AL = 3 -> load overlay ; ; +---------------------------+ ; | WORD segment address where| ; | file will be loaded. | ; +---------------------------+ ; | WORD relocation factor to | ; | be applied to the image. | ; +---------------------------+ ; ; Returns: ; AX = exec_invalid_function ; = exec_bad_format ; = exec_bad_environment ; = exec_not_enough_memory ; = exec_file_not_found ; IF IBM ZEXEC_DATA SEGMENT PUBLIC BYTE ZERO = $ ENDIF exec_blk DD ? exec_func DB ? exec_fh DW ? exec_rel_fac DW ? exec_res_len_para DW ? exec_init_IP DW ? exec_init_CS DW ? exec_init_SP DW ? exec_init_SS DW ? exec_environ DW ? exec_size DW ? exec_load_block DW ? exec_load_high DB ? exec_internal_buffer EQU $ exec_signature DW ? ; must contain 4D5A (yay zibo!) exec_len_mod_512 DW ? ; low 9 bits of length exec_pages DW ? ; number of 512b pages in file exec_rle_count DW ? ; count of reloc entries exec_par_dir DW ? ; number of paragraphs before image exec_min_BSS DW ? ; minimum number of para of BSS exec_max_BSS DW ? ; max number of para of BSS exec_SS DW ? ; stack of image exec_SP DW ? ; SP of image exec_chksum DW ? ; checksum of file (ignored) exec_IP DW ? ; IP of entry exec_CS DW ? ; CS of entry exec_rle_table DW ? ; byte offset of reloc table exec_iov DW ? ; overlay number (0 for root) exec_dma DW ? exec_internal_buffer_size EQU $-exec_internal_buffer IF IBM exec_ctrlc DB ? ; state of users ctrlc flag Exec_low_seg DW ? CurrentPDB DW ? NUMIO DB ? ZEXECDATASIZ = $-ZERO ZEXECDATAEND LABEL BYTE PUBLIC ZEXECDATAEND ZEXEC_DATA ENDS ZEXEC_CODE SEGMENT PUBLIC PARA PUBLIC $EXEC ZERO = $ procedure $EXEC,FAR ASSUME CS:EGROUP,SS:RESGROUP,ES:NOTHING,DS:NOTHING ENDIF IF NOT IBM procedure $Exec,NEAR ASSUME DS:NOTHING, ES:NOTHING ENDIF ; ; validate function ; IF IBM PUSH CS POP DS ASSUME DS:EGROUP MOV AX,(Set_Ctrl_C_Trapping SHL 8) + 0 ; Save current ctrl-c INT int_command MOV exec_ctrlc,DL XOR DX,DX MOV AX,(Set_Ctrl_C_Trapping SHL 8) + 1 ; Turn it off! INT int_command MOV AH,Get_current_PDB INT int_command MOV [CurrentPDB],BX ; ; set up user return stack info ; MOV ES,BX LES BX,DWORD PTR [user_sp] MOV WORD PTR ES:[PDB_user_stack+2],ES MOV WORD PTR ES:[PDB_user_stack],BX MOV AH,Get_Default_Drive INT int_command MOV DL,AL MOV AH,Set_default_drive INT int_command MOV [NUMIO],AL ; ; determine lowest seg address for overwrite problem (round DOWN) ; MOV CL,4 MOV AX,OFFSET ZEXEC_CODE:exec_check SHR AX,CL PUSH CS POP BX ADD AX,BX MOV [exec_low_seg],AX CALL get_user_stack ASSUME DS:NOTHING MOV AX,[SI.user_AX] MOV BX,[SI.user_BX] MOV DX,[SI.user_DX] MOV ES,[SI.user_ES] MOV DS,[SI.user_DS] ENDIF CMP AL,3 ; only 0, 1 or 3 are allowed JNA exec_check_2 exec_bad_fun: error error_invalid_function exec_ret_err: transfer SYS_RET_ERR exec_check_2: CMP AL,2 JZ exec_bad_fun MOV WORD PTR [exec_blk],BX ; stash args MOV WORD PTR [exec_blk+2],ES MOV BYTE PTR [exec_func],AL MOV BYTE PTR [exec_load_high],0 IF IBM MOV AX,(OPEN SHL 8) + 0 INT int_command ENDIF IF NOT IBM XOR AL,AL ; open for reading invoke $OPEN ; is the file there? ENDIF JC exec_ret_err MOV [exec_fh],AX MOV BX,AX IF IBM MOV AX,(ioctl SHL 8) ; get device information INT int_command ENDIF IF NOT IBM XOR AL,AL invoke $IOCTL ENDIF TEST DL,devid_ISDEV JZ exec_check_environ MOV AL,exec_file_not_found transfer SYS_RET_ERR exec_check_environ: MOV [exec_load_block],0 TEST BYTE PTR [exec_func],exec_func_overlay ; overlays... no environment JNZ exec_read_header LDS SI,DWORD PTR [exec_blk] ; get block MOV AX,[SI].Exec1_environ ; address of environ OR AX,AX JNZ exec_scan_env MOV DS,[CurrentPDB] MOV AX,DS:[PDB_environ] MOV [exec_environ],AX OR AX,AX JZ exec_read_header exec_scan_env: CLD MOV ES,AX XOR DI,DI MOV CX,07FFFh ; at most 32k of environment XOR AL,AL exec_get_environ_len: REPNZ SCASB ; find that nul byte JZ exec_check ; CX is out... bad environment MOV AL,exec_bad_environment JMP exec_bomb exec_check: SCASB ; is there another nul byte? JNZ exec_get_environ_len ; no, scan some more PUSH DI MOV BX,DI ; AX <- length of environment ADD BX,0Fh MOV CL,4 SHR BX,CL ; number of paragraphs needed PUSH ES IF IBM MOV AH,ALLOC INT int_command ENDIF IF NOT IBM invoke $ALLOC ; can we get the space? ENDIF POP DS POP CX JNC exec_save_environ JMP exec_no_mem ; nope... cry and sob exec_save_environ: MOV ES,AX MOV [exec_environ],AX ; save him for a rainy day IF IBM PUSH CX MOV CX,ES ADD CX,BX CMP BX,[exec_low_seg] POP CX JA exec_no_mem ENDIF XOR SI,SI XOR DI,DI REP MOVSB ; copy the environment exec_read_header: ; ; We read in the program header into the above data area and determine ; where in this memory the image will be located. ; IF IBM PUSH CS POP DS ; and put it in DS:DX ASSUME DS:EGROUP ENDIF IF NOT IBM PUSH SS POP DS ; and put it in DS:DX ASSUME DS:DOSGROUP ENDIF MOV CX,exec_internal_buffer_size; header size MOV BX,[exec_fh] ; from the handle IF IBM MOV DX,OFFSET EGROUP:exec_signature ENDIF IF NOT IBM MOV DX,OFFSET DOSGROUP:exec_signature ENDIF PUSH ES PUSH DS CALL exec_dealloc IF IBM MOV AH,READ INT int_command ENDIF IF NOT IBM invoke $READ ENDIF CALL exec_alloc POP DS POP ES JC exec_bad_file CMP AX,exec_internal_buffer_size; did we read the right number? JNZ exec_com_filej ; yep... continue CMP [exec_max_BSS],0 JNZ exec_check_sig MOV [exec_load_high],-1 exec_check_sig: MOV AX,[exec_signature] CMP AX,exe_valid_signature ; zibo arises! JZ exec_save_start ; assume com file if no signature CMP AX,exe_valid_old_signature ; zibo arises! JZ exec_save_start ; assume com file if no signature exec_com_filej: JMP exec_com_file ; ; We have the program header... determine memory requirements ; exec_save_start: MOV AX,[exec_pages] ; get 512-byte pages MOV CL,5 ; convert to paragraphs SHL AX,CL SUB AX,[exec_par_dir] ; AX = size in paragraphs MOV [exec_res_len_para],AX ; ; Do we need to allocate memory? Yes if function is not load-overlay ; TEST BYTE PTR [exec_func],exec_func_overlay JZ exec_allocate ; allocation of space ; ; get load address from block ; LES DI,DWORD PTR [exec_blk] MOV AX,ES:[DI].exec3_load_addr MOV [exec_dma],AX MOV AX,ES:[DI].exec3_reloc_fac MOV [exec_rel_fac],AX IF IBM JMP exec_find_res ENDIF IF NOT IBM JMP SHORT exec_find_res ENDIF exec_no_mem: MOV AL,exec_not_enough_memory JMP SHORT exec_bomb ; AX should be set by $ALLOC exec_bad_file: MOV AL,exec_bad_format exec_bomb: ASSUME DS:NOTHING,ES:NOTHING PUSH AX MOV BX,[exec_fh] CALL exec_dealloc IF IBM MOV AH,CLOSE INT int_command ENDIF IF NOT IBM invoke $CLOSE ENDIF POP AX transfer SYS_RET_ERR exec_allocate: IF IBM ASSUME DS:EGROUP ENDIF IF NOT IBM ASSUME DS:DOSGROUP ENDIF PUSH AX MOV BX,0FFFFh ; see how much room in arena PUSH DS IF IBM MOV AH,ALLOC INT int_command ENDIF IF NOT IBM invoke $ALLOC ; should have carry set and BX has max ENDIF POP DS POP AX ADD AX,10h ; room for header CMP BX,11h ; enough room for a header JB exec_no_mem CMP AX,BX ; is there enough for bare image? JA exec_no_mem CMP [exec_load_high],0 ; if load high, use max JNZ exec_BX_max ; use max ADD AX,[exec_min_BSS] ; go for min allocation JC exec_no_mem ; oops! carry CMP AX,BX ; enough space? JA exec_no_mem ; nope... SUB AX,[exec_min_BSS] ADD AX,[exec_max_BSS] ; go for the MAX JC exec_BX_max CMP AX,BX JBE exec_got_block exec_BX_max: MOV AX,BX exec_got_block: PUSH DS MOV BX,AX MOV [exec_size],BX IF IBM MOV AH,ALLOC INT int_command ENDIF IF NOT IBM invoke $ALLOC ; get the space ENDIF POP DS JC exec_no_mem MOV [exec_load_block],AX ADD AX,10h CMP [exec_load_high],0 JZ exec_use_ax ; use ax for load info ADD AX,[exec_size] ; go to end SUB AX,[exec_res_len_para] ; drop off header SUB AX,10h ; drop off pdb exec_use_ax: MOV [exec_rel_fac],AX ; new segment MOV [exec_dma],AX ; beginning of dma IF IBM CMP AX,[exec_low_seg] ; below loader JA exec_no_mem_try ADD AX,[exec_res_len_para] ; go to end CMP Ax,[exec_low_seg] ; above loader JBE exec_find_res exec_try_high: CMP [exec_load_high],0 JZ exec_no_memj1 exec_try_just_below: MOV DX,AX SUB DX,[exec_size] ; get beginning ADD DX,[exec_res_len_para] ; no space CMP DX,[exec_low_seg] ; room there? JA exec_no_memj1 MOV AX,[exec_low_seg] SUB AX,[exec_res_len_para] JMP exec_use_ax exec_no_mem_try: MOV DX,CS ADD DX,(zexecdatasiz+zexeccodesize+15)/16 CMP AX,DX JAE exec_try_high JMP exec_try_just_below exec_no_memj1: JMP exec_no_mem ENDIF ; ; Determine the location in the file of the beginning of the resident ; exec_find_res: MOV DX,[exec_par_dir] PUSH DX MOV CL,4 SHL DX,CL ; low word of location POP AX MOV CL,12 SHR AX,CL ; high word of location MOV CX,AX ; CX <- high ; ; Read in the resident image (first, seek to it) ; MOV BX,[exec_fh] PUSH DS IF IBM MOV AX,(LSEEK SHL 8) + 0 INT int_command ENDIF IF NOT IBM XOR AL,AL invoke $LSEEK ; seek to resident ENDIF POP DS exec_big_read: ; Read resident into memory MOV BX,[exec_res_len_para] CMP BX,1000h ; too many bytes to read? JB exec_read_ok MOV BX,0FE0h ; max in one chunk FE00 bytes exec_read_ok: SUB [exec_res_len_para],BX ; we read (soon) this many PUSH BX MOV CL,4 SHL BX,CL ; get count in bytes from paras MOV CX,BX ; count in correct register MOV BX,[exec_fh] ; handle in correct register PUSH DS MOV DS,[exec_dma] ; Set up read buffer ASSUME DS:NOTHING XOR DX,DX PUSH CX ; save our count CALL exec_dealloc IF IBM MOV AH,READ INT int_command ENDIF IF NOT IBM invoke $READ ; WOMP! ENDIF CALL exec_alloc POP CX ; get old count to verify POP DS IF IBM ASSUME DS:EGROUP ENDIF IF NOT IBM ASSUME DS:DOSGROUP ENDIF CMP CX,AX ; did we read enough? POP BX ; get paragraph count back JNZ exec_do_reloc ; and do reloc if no more to read ; ; We've read in CX bytes... bump DTA location ; ADD [exec_dma],BX ; bump dma address CMP [exec_res_len_para],0 JNZ exec_big_read ; ; The image has now been read in. We must perform relocation to ; the current location. ; exec_do_reloc: MOV CX,[exec_rel_fac] MOV AX,[exec_SS] ; get initial SS ADD AX,CX ; and relocate him MOV [exec_init_SS],AX MOV AX,[exec_SP] ; initial SP MOV [exec_init_SP],AX LES AX,DWORD PTR [exec_IP] MOV [exec_init_IP],AX MOV AX,ES ADD AX,CX ; relocated... MOV [exec_init_CS],AX XOR CX,CX MOV DX,[exec_rle_table] MOV BX,[exec_fh] PUSH DS IF IBM MOV AX,(LSEEK SHL 8) + 0 INT int_command ENDIF IF NOT IBM XOR AX,AX invoke $LSEEK ENDIF POP DS JNC exec_get_entries exec_bad_filej: JMP exec_bad_file exec_get_entries: MOV DX,[exec_rle_count] ; Number of entries left exec_read_reloc: ASSUME DS:NOTHING PUSH DX IF IBM MOV DX,OFFSET EGROUP:exec_signature ENDIF IF NOT IBM MOV DX,OFFSET DOSGROUP:exec_signature ENDIF MOV CX,((exec_internal_buffer_size)/4)*4 MOV BX,[exec_fh] PUSH DS CALL exec_dealloc IF IBM MOV AH,READ INT int_command ENDIF IF NOT IBM invoke $READ ENDIF CALL exec_alloc POP ES POP DX JC exec_bad_filej MOV CX,(exec_internal_buffer_size)/4 IF IBM MOV DI,OFFSET EGROUP:exec_signature ; Pointer to byte location in header ENDIF IF NOT IBM MOV DI,OFFSET DOSGROUP:exec_signature ; Pointer to byte location in header ENDIF ; ; Relocate a single address ; MOV SI,[exec_rel_fac] exec_reloc_one: CMP DX,0 ; Any more entries? JNE exec_get_addr JMP Exec_set_PDB exec_get_addr: LDS BX,DWORD PTR ES:[DI] ; Get ra/sa of entry MOV AX,DS ; Relocate address of item ADD AX,SI MOV DS,AX MOV AX,WORD PTR DS:[BX] ; Relocate item ADD AX,SI MOV WORD PTR DS:[BX],AX ADD DI,4 DEC DX LOOP exec_reloc_one ; End of internal buffer? ; ; We've exhausted a single buffer's worth. Read in the next piece ; of the relocation table. ; PUSH ES POP DS JMP exec_read_reloc exec_no_memj: JMP exec_no_mem ; ; we have a .COM file. First, determine if we are merely loading an overlay. ; exec_com_file: TEST BYTE PTR [exec_func],exec_func_overlay JZ exec_alloc_com_file LDS SI,DWORD PTR [exec_blk] ; get arg block LODSW ; get load address MOV [exec_dma],AX JMP SHORT exec_64k ; read it all! ; We must allocate the max possible size block (ick!) and set up ; CS=DS=ES=SS=PDB pointer, IP=100, SP=max size of block. ; exec_alloc_com_file: MOV BX,0FFFFh IF IBM MOV AH,ALLOC INT int_command ENDIF IF NOT IBM invoke $ALLOC ; largest piece available as error ENDIF OR BX,BX JZ exec_no_memj MOV [exec_size],BX ; save size of allocation block IF IBM MOV AH,ALLOC INT int_command ENDIF IF NOT IBM PUSH BX invoke $ALLOC ; largest piece available as error POP BX ; get size of block... ENDIF MOV [exec_load_block],AX ADD AX,10h ; increment for header MOV [exec_dma],AX SUB BX,10h ; remember header IF IBM ; ; need to read up to exec_low_seg (at most) ; MOV CX,[exec_low_seg] CMP AX,CX ; is base of allocation above spot JA exec_check_64k SUB CX,AX CMP CX,BX JA exec_check_64k MOV BX,CX exec_check_64k: ENDIF CMP BX,1000h ; 64k or more? JAE exec_64k ; yes, read only 64k MOV AX,BX ; convert size to bytes MOV CL,4 SHL AX,CL JMP SHORT exec_read_com exec_64k: MOV AX,0FFFFh ; 64k-1 bytes exec_read_com: PUSH AX ; save number to read MOV BX,[exec_fh] ; of com file XOR CX,CX ; but seek to 0:0 MOV DX,CX IF IBM MOV AX,(LSEEK SHL 8) + 0 INT int_command ENDIF IF NOT IBM XOR AX,AX ; seek relative to beginning invoke $LSEEK ; back to beginning of file ENDIF MOV BX,[exec_fh] POP CX ; number to read MOV DS,[exec_dma] XOR DX,DX PUSH CX CALL exec_dealloc IF IBM MOV AH,READ INT int_command ENDIF IF NOT IBM invoke $READ ; read in com file ENDIF CALL exec_alloc POP SI ; get number of bytes to read CMP AX,SI ; did we read them all? IF IBM JNZ exec_skip ; exactly the wrong number... no memory JMP exec_no_mem exec_skip: ENDIF IF NOT IBM JZ exec_no_memj ; exactly the wrong number... no memory ENDIF TEST BYTE PTR [exec_func],exec_func_overlay JNZ exec_set_PDB ; no starto, chumo! MOV AX,[exec_DMA] SUB AX,10h MOV [exec_init_CS],AX MOV [exec_init_IP],100h ; initial IP is 100 ; SI is at most FFFFh DEC SI ; make room for stack ; SI is at most FFFEh, room for a 0! MOV [exec_init_SP],SI ; max value for read is also SP! MOV [exec_init_SS],AX MOV DS,AX MOV WORD PTR DS:[SI],0 ; 0 for return exec_set_PDB: MOV BX,[exec_fh] ; we are finished with the file. CALL exec_dealloc IF IBM MOV AH,CLOSE INT int_command ENDIF IF NOT IBM invoke $CLOSE ; release the jfn ENDIF CALL exec_alloc TEST BYTE PTR [exec_func],exec_func_overlay JZ exec_build_header transfer SYS_RET_OK ; overlay load -> done exec_build_header: MOV DX,[exec_load_block] ; ; assign the space to the process ; MOV SI,arena_owner ; pointer to owner field MOV AX,[exec_environ] ; get environ pointer OR AX,AX JZ NO_OWNER ; no environment DEC AX ; point to header MOV DS,AX MOV DS:[SI],DX ; assign ownership NO_OWNER: MOV AX,[exec_load_block] ; get load block pointer DEC AX MOV DS,AX ; point to header MOV DS:[SI],DX ; assign ownership PUSH DX IF IBM MOV AH,DUP_PDB INT int_command MOV ES,DX MOV [CurrentPDB],DX ENDIF IF NOT IBM MOV BYTE PTR [CreatePDB], 0FFH ; indicate a new process invoke $Dup_PDB ; ES is now PDB ENDIF POP DX PUSH [exec_environ] POP ES:[PDB_environ] MOV SI,[exec_size] ADD SI,DX MOV ES:[PDB_block_len],SI ; ; set up proper command line stuff ; LDS SI,DWORD PTR [exec_blk] ; get the block PUSH DS ; save its location PUSH SI LDS SI,DS:[SI.exec0_5C_FCB] ; get the 5c fcb MOV CX,12 ; copy drive, name and ext PUSH CX MOV DI,5Ch MOV BL,DS:[SI] REP MOVSB XOR AX,AX ; zero extent, etc for CPM STOSW STOSW POP CX POP SI ; get block POP DS PUSH DS ; save (again) PUSH SI LDS SI,DS:[SI.exec0_6C_FCB] ; get 6C FCB MOV DI,6Ch ; do same as above MOV BH,DS:[SI] REP MOVSB STOSW STOSW POP SI ; get block (last time) POP DS LDS SI,DS:[SI.exec0_com_line] ; command line MOV CX,80h MOV DI,CX REP MOVSB ; Wham! ; ; Process BX into default AX (validity of drive specs on args) ; DEC CL ; get 0FFh in CX CMP BH,[NUMIO] JBE exec_BH_good MOV BH,CL JMP SHORT exec_BL exec_BH_good: XOR BH,BH exec_BL: CMP BL,[NUMIO] JBE exec_BL_good MOV BL,CL JMP SHORT exec_set_return exec_BL_good: XOR BL,BL exec_set_return: invoke get_user_stack ; get his return address PUSH [SI.user_CS] ; suck out the CS and IP PUSH [SI.user_IP] PUSH [SI.user_CS] ; suck out the CS and IP PUSH [SI.user_IP] POP WORD PTR ES:[PDB_Exit] POP WORD PTR ES:[PDB_Exit+2] XOR AX,AX MOV DS,AX POP DS:[addr_int_terminate] ; save them where we can get them later POP DS:[addr_int_terminate+2] ; when the child exits. IF NOT IBM MOV WORD PTR [DMAADD],80h MOV DS,[CurrentPDB] MOV WORD PTR [DMAADD+2],DS ENDIF IF IBM PUSH DX PUSH DS MOV DS,[CurrentPDB] MOV DX,80h MOV AH,SET_DMA INT int_command POP DS POP DX ENDIF TEST BYTE PTR [exec_func],exec_func_no_execute JZ exec_go LDS SI,DWORD PTR [exec_init_SP] ; get stack LES DI,DWORD PTR [exec_blk] ; and block for return MOV ES:[DI].exec1_SS,DS ; return SS DEC SI ; 'push' default AX DEC SI MOV DS:[SI],BX ; save default AX reg MOV ES:[DI].exec1_SP,SI ; return 'SP' LDS AX,DWORD PTR [exec_init_IP] MOV ES:[DI].exec1_CS,DS ; initial entry stuff MOV ES:[DI].exec1_IP,AX transfer SYS_RET_OK exec_go: IF IBM CALL restore_ctrlc ; restore value of ctrl-c checker ENDIF LDS SI,DWORD PTR [exec_init_IP] ; get entry point CLI IF NOT IBM MOV BYTE PTR INDOS,0 ENDIF MOV SS,[exec_init_SS] ; set up user's stack ASSUME SS:NOTHING MOV SP,[exec_init_SP] ; and SP STI PUSH DS ; fake long call to entry PUSH SI MOV ES,DX ; set up proper seg registers MOV DS,DX MOV AX,BX ; set up proper AX procedure exec_long_ret,FAR RET exec_long_ret ENDP $Exec ENDP procedure exec_dealloc,near ASSUME DS:NOTHING,ES:NOTHING PUSH BX MOV BX,arena_owner_system CALL exec_do_change_owner POP BX return exec_dealloc ENDP procedure exec_alloc,near PUSH BX MOV BX,[CurrentPDB] CALL exec_do_change_owner POP BX return exec_alloc ENDP procedure exec_do_change_owner,NEAR PUSH DS PUSH AX MOV AX,[exec_environ] OR AX,AX JZ exec_alloc_try_load DEC AX MOV DS,AX MOV DS:[arena_owner],BX exec_alloc_try_load: MOV AX,[exec_load_block] OR AX,AX JZ exec_alloc_done DEC AX MOV DS,AX MOV DS:[arena_owner],BX exec_alloc_done: POP AX POP DS RET exec_do_change_owner ENDP IF IBM SYS_RET_ERR: CALL get_user_stack PUSH [SI.user_f] XOR AH,AH MOV [SI.user_AX],AX POPF STC JMP SYS_RET SYS_RET_OK: CALL get_user_stack PUSH [SI.user_f] POPF CLC SYS_RET: PUSHF CALL restore_ctrlc POP [SI.user_f] JMP exec_long_ret ; ; get_user_stack returns the user's stack (and hence registers) in DS:SI ; procedure get_user_stack,NEAR PUSH SS POP DS ASSUME DS:RESGROUP LDS SI,DWORD PTR [user_SP] RET get_user_stack ENDP ; ; restore value of the ctrl-c checker ; procedure restore_ctrlc PUSH AX PUSH DX MOV DL,CS:[exec_ctrlc] MOV AX,(Set_Ctrl_C_Trapping SHL 8) + 1 ; Put it back INT int_command POP DX POP AX RET restore_ctrlc ENDP ZEXECCODESIZE EQU $-ZERO ZEXECCODEEND LABEL BYTE PUBLIC ZEXECCODEEND ZEXEC_CODE ENDS ENDIF