diff options
| author | 2024-04-25 21:24:10 +0100 | |
|---|---|---|
| committer | 2024-04-25 22:32:27 +0000 | |
| commit | 2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch) | |
| tree | 80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/DOS/EXEC.ASM | |
| parent | Merge pull request #430 from jpbaltazar/typoptbr (diff) | |
| download | ms-dos-main.tar.gz ms-dos-main.tar.xz ms-dos-main.zip | |
Diffstat (limited to 'v4.0/src/DOS/EXEC.ASM')
| -rw-r--r-- | v4.0/src/DOS/EXEC.ASM | 931 |
1 files changed, 931 insertions, 0 deletions
diff --git a/v4.0/src/DOS/EXEC.ASM b/v4.0/src/DOS/EXEC.ASM new file mode 100644 index 0000000..aa120c2 --- /dev/null +++ b/v4.0/src/DOS/EXEC.ASM | |||
| @@ -0,0 +1,931 @@ | |||
| 1 | ; SCCSID = @(#)exec.asm 1.3 85/08/13 | ||
| 2 | ; SCCSID = @(#)exec.asm 1.3 85/08/13 | ||
| 3 | ; AN000 version 4.0 jan. 1988 | ||
| 4 | ; A007 PTM 3957 - fake vesrion for IBMCACHE.COM | ||
| 5 | ; A008 PTM 4070 - fake version for MS WINDOWS | ||
| 6 | |||
| 7 | SUBTTL $exec - load/go a program | ||
| 8 | PAGE | ||
| 9 | ; | ||
| 10 | ; Assembler usage: | ||
| 11 | ; LDS DX, name | ||
| 12 | ; LES BX, blk | ||
| 13 | ; MOV AH, Exec | ||
| 14 | ; MOV AL, func | ||
| 15 | ; INT int_command | ||
| 16 | ; | ||
| 17 | ; AL Function | ||
| 18 | ; -- -------- | ||
| 19 | ; 0 Load and execute the program. | ||
| 20 | ; 1 Load, create the program header but do not | ||
| 21 | ; begin execution. | ||
| 22 | ; 3 Load overlay. No header created. | ||
| 23 | ; | ||
| 24 | ; AL = 0 -> load/execute program | ||
| 25 | ; | ||
| 26 | ; +---------------------------+ | ||
| 27 | ; | WORD segment address of | | ||
| 28 | ; | environment. | | ||
| 29 | ; +---------------------------+ | ||
| 30 | ; | DWORD pointer to ASCIZ | | ||
| 31 | ; | command line at 80h | | ||
| 32 | ; +---------------------------+ | ||
| 33 | ; | DWORD pointer to default | | ||
| 34 | ; | FCB to be passed at 5Ch | | ||
| 35 | ; +---------------------------+ | ||
| 36 | ; | DWORD pointer to default | | ||
| 37 | ; | FCB to be passed at 6Ch | | ||
| 38 | ; +---------------------------+ | ||
| 39 | ; | ||
| 40 | ; AL = 1 -> load program | ||
| 41 | ; | ||
| 42 | ; +---------------------------+ | ||
| 43 | ; | WORD segment address of | | ||
| 44 | ; | environment. | | ||
| 45 | ; +---------------------------+ | ||
| 46 | ; | DWORD pointer to ASCIZ | | ||
| 47 | ; | command line at 80h | | ||
| 48 | ; +---------------------------+ | ||
| 49 | ; | DWORD pointer to default | | ||
| 50 | ; | FCB to be passed at 5Ch | | ||
| 51 | ; +---------------------------+ | ||
| 52 | ; | DWORD pointer to default | | ||
| 53 | ; | FCB to be passed at 6Ch | | ||
| 54 | ; +---------------------------+ | ||
| 55 | ; | DWORD returned value of | | ||
| 56 | ; | CS:IP | | ||
| 57 | ; +---------------------------+ | ||
| 58 | ; | DWORD returned value of | | ||
| 59 | ; | SS:IP | | ||
| 60 | ; +---------------------------+ | ||
| 61 | ; | ||
| 62 | ; AL = 3 -> load overlay | ||
| 63 | ; | ||
| 64 | ; +---------------------------+ | ||
| 65 | ; | WORD segment address where| | ||
| 66 | ; | file will be loaded. | | ||
| 67 | ; +---------------------------+ | ||
| 68 | ; | WORD relocation factor to | | ||
| 69 | ; | be applied to the image. | | ||
| 70 | ; +---------------------------+ | ||
| 71 | ; | ||
| 72 | ; Returns: | ||
| 73 | ; AX = error_invalid_function | ||
| 74 | ; = error_bad_format | ||
| 75 | ; = error_bad_environment | ||
| 76 | ; = error_not_enough_memory | ||
| 77 | ; = error_file_not_found | ||
| 78 | ; | ||
| 79 | ; Revision history: | ||
| 80 | ; | ||
| 81 | ; A000 version 4.00 Jan. 1988 | ||
| 82 | ; | ||
| 83 | include EA.INC | ||
| 84 | include version.inc | ||
| 85 | |||
| 86 | I_Need Temp_Var2,WORD ;AN000;file type from $open | ||
| 87 | I_Need Special_Entries,WORD ;AN007;address of special entries | ||
| 88 | I_Need Special_Version,WORD ;AN007;special version number | ||
| 89 | I_Need Fake_Count,BYTE ;AN008;fake version count | ||
| 90 | |||
| 91 | IF BUFFERFLAG | ||
| 92 | extrn restore_user_map:near | ||
| 93 | ENDIF | ||
| 94 | |||
| 95 | TABLE SEGMENT | ||
| 96 | |||
| 97 | exec_init_SP DW ? | ||
| 98 | exec_init_SS DW ? | ||
| 99 | exec_init_IP DW ? | ||
| 100 | exec_init_CS DW ? | ||
| 101 | |||
| 102 | exec_internal_buffer EQU OpenBuf | ||
| 103 | |||
| 104 | exec_signature DW ? ; must contain 4D5A (yay zibo!) | ||
| 105 | exec_len_mod_512 DW ? ; low 9 bits of length | ||
| 106 | exec_pages DW ? ; number of 512b pages in file | ||
| 107 | exec_rle_count DW ? ; count of reloc entries | ||
| 108 | exec_par_dir DW ? ; number of paragraphs before image | ||
| 109 | exec_min_BSS DW ? ; minimum number of para of BSS | ||
| 110 | exec_max_BSS DW ? ; max number of para of BSS | ||
| 111 | exec_SS DW ? ; stack of image | ||
| 112 | exec_SP DW ? ; SP of image | ||
| 113 | exec_chksum DW ? ; checksum of file (ignored) | ||
| 114 | exec_IP DW ? ; IP of entry | ||
| 115 | exec_CS DW ? ; CS of entry | ||
| 116 | exec_rle_table DW ? ; byte offset of reloc table | ||
| 117 | Exec_header_len EQU $-Exec_Signature | ||
| 118 | |||
| 119 | exec_internal_buffer_size EQU (128+128+53+curdirLEN) | ||
| 120 | %out Please make sure that the following are contiguous and of the | ||
| 121 | %out following sizes: | ||
| 122 | %out | ||
| 123 | %out OpenBuf 128 | ||
| 124 | %out RenBuf 128 | ||
| 125 | %out SearchBuf 53 | ||
| 126 | %out DummyCDS CurDirLen | ||
| 127 | |||
| 128 | TABLE ENDS | ||
| 129 | |||
| 130 | .sall | ||
| 131 | |||
| 132 | procedure $Exec,NEAR | ||
| 133 | ASSUME DS:NOTHING, ES:NOTHING | ||
| 134 | PUBLIC EXEC001S,EXEC001E | ||
| 135 | EXEC001S: | ||
| 136 | LocalVar exec_blk,DWORD | ||
| 137 | LocalVar exec_func,BYTE | ||
| 138 | LocalVar exec_load_high,BYTE | ||
| 139 | LocalVar exec_fh,WORD | ||
| 140 | LocalVar exec_rel_fac,WORD | ||
| 141 | LocalVar exec_res_len_para,WORD | ||
| 142 | LocalVar exec_environ,WORD | ||
| 143 | LocalVar exec_size,WORD | ||
| 144 | LocalVar exec_load_block,WORD | ||
| 145 | LocalVar exec_dma,WORD | ||
| 146 | LocalVar execNameLen,WORD | ||
| 147 | LocalVar execName,DWORD | ||
| 148 | EXEC001E: | ||
| 149 | Enter | ||
| 150 | ; | ||
| 151 | ; validate function | ||
| 152 | ; | ||
| 153 | |||
| 154 | CMP AL,3 ; only 0, 1 or 3 are allowed | ||
| 155 | JNA exec_check_2 | ||
| 156 | |||
| 157 | exec_bad_fun: | ||
| 158 | MOV EXTERR_LOCUS,errLOC_Unk ; Extended Error Locus | ||
| 159 | mov al,error_invalid_function | ||
| 160 | |||
| 161 | exec_ret_err: | ||
| 162 | Leave | ||
| 163 | transfer SYS_RET_ERR | ||
| 164 | |||
| 165 | exec_check_2: | ||
| 166 | CMP AL,2 | ||
| 167 | JZ exec_bad_fun | ||
| 168 | |||
| 169 | MOV exec_blkL,BX ; stash args | ||
| 170 | MOV exec_blkH,ES | ||
| 171 | MOV exec_func,AL | ||
| 172 | MOV exec_load_high,0 | ||
| 173 | ; | ||
| 174 | ; set up length of exec name | ||
| 175 | ; | ||
| 176 | MOV execNameL,DX | ||
| 177 | MOV execNameH,DS | ||
| 178 | MOV SI,DX ; move pointer to convenient place | ||
| 179 | invoke DStrLen | ||
| 180 | MOV ExecNameLen,CX ; save length | ||
| 181 | |||
| 182 | XOR AL,AL ; open for reading | ||
| 183 | PUSH BP | ||
| 184 | invoke $OPEN ; is the file there? | ||
| 185 | POP BP | ||
| 186 | JC exec_ret_err | ||
| 187 | ;File Type Checking | ||
| 188 | ; CMP BYTE PTR [Temp_Var2],EAEXISTING ;AN000;;FT. old file ? | ||
| 189 | ; JZ oldexf ;AN000;;FT. yes | ||
| 190 | ; TEST BYTE PTR EXEC_FUNC,EXEC_FUNC_OVERLAY ;AN000;;FT. exec overlay? | ||
| 191 | ; JNZ exovrly ;AN000;;FT. yes | ||
| 192 | ; CMP BYTE PTR [Temp_Var2],EAEXECUTABLE ;AN000;;FT. only file type | ||
| 193 | ; JZ oldexf ;AN000;;FT. 3 & 4 will pass | ||
| 194 | ; CMP BYTE PTR [Temp_Var2],EAINSTALLABLE ;AN000;;FT. | ||
| 195 | ; JZ oldexf ;AN000;;FT. | ||
| 196 | ;exerr: ;AN000;;FT. | ||
| 197 | ; MOV AL,error_access_denied ;AN000;;FT. error | ||
| 198 | ; JMP exec_ret_err ;AN000;;FT. | ||
| 199 | ;exovrly: ;AN000;;FT. | ||
| 200 | ; CMP BYTE PTR [Temp_Var2],EAOVERLAY ;AN000;;FT. only 5,6,7 pass | ||
| 201 | ; JZ oldexf ;AN000;;FT. | ||
| 202 | ; CMP BYTE PTR [Temp_Var2],EADEV_DRIVER ;AN000;;FT. | ||
| 203 | ; JZ oldexf ;AN000;;FT. | ||
| 204 | ; CMP BYTE PTR [Temp_Var2],EAIFS_DRIVER ;AN000;;FT. | ||
| 205 | ; JNZ exerr ;AN000;;FT. | ||
| 206 | ; | ||
| 207 | ;oldexf: ;AN000; | ||
| 208 | ;File Type Checking | ||
| 209 | |||
| 210 | MOV exec_fh,AX | ||
| 211 | MOV BX,AX | ||
| 212 | XOR AL,AL | ||
| 213 | invoke $IOCTL | ||
| 214 | JC Exec_bombJ | ||
| 215 | TEST DL,devid_ISDEV | ||
| 216 | JZ exec_check_environ | ||
| 217 | MOV AL,error_file_not_found | ||
| 218 | Exec_bombJ: | ||
| 219 | JMP Exec_Bomb | ||
| 220 | |||
| 221 | BadEnv: | ||
| 222 | MOV AL,error_bad_environment | ||
| 223 | JMP exec_bomb | ||
| 224 | |||
| 225 | exec_check_environ: | ||
| 226 | MOV exec_load_block,0 | ||
| 227 | MOV exec_environ,0 | ||
| 228 | |||
| 229 | TEST BYTE PTR exec_func,exec_func_overlay ; overlays... no environment | ||
| 230 | JNZ exec_read_header | ||
| 231 | LDS SI,exec_blk ; get block | ||
| 232 | MOV AX,[SI].Exec1_environ ; address of environ | ||
| 233 | OR AX,AX | ||
| 234 | JNZ exec_scan_env | ||
| 235 | MOV DS,CurrentPDB | ||
| 236 | MOV AX,DS:[PDB_environ] | ||
| 237 | MOV exec_environ,AX | ||
| 238 | OR AX,AX | ||
| 239 | JZ exec_read_header | ||
| 240 | |||
| 241 | exec_scan_env: | ||
| 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 | JNZ BadEnv | ||
| 250 | DEC CX ; Dec CX for the next nul byte test | ||
| 251 | JB BadEnv ; gone beyond the end of the environment | ||
| 252 | SCASB ; is there another nul byte? | ||
| 253 | JNZ exec_get_environ_len ; no, scan some more | ||
| 254 | PUSH DI | ||
| 255 | LEA BX,[DI+0Fh+2] | ||
| 256 | ADD BX,ExecNameLen ; BX <- length of environment | ||
| 257 | ; remember argv[0] length | ||
| 258 | ; round up and remember argc | ||
| 259 | MOV CL,4 | ||
| 260 | SHR BX,CL ; number of paragraphs needed | ||
| 261 | PUSH ES | ||
| 262 | invoke $ALLOC ; can we get the space? | ||
| 263 | POP DS | ||
| 264 | POP CX | ||
| 265 | JNC exec_save_environ | ||
| 266 | JMP exec_no_mem ; nope... cry and sob | ||
| 267 | |||
| 268 | exec_save_environ: | ||
| 269 | MOV ES,AX | ||
| 270 | MOV exec_environ,AX ; save him for a rainy day | ||
| 271 | XOR SI,SI | ||
| 272 | MOV DI,SI | ||
| 273 | REP MOVSB ; copy the environment | ||
| 274 | MOV AX,1 | ||
| 275 | STOSW | ||
| 276 | LDS SI,execName | ||
| 277 | MOV CX,execNameLen | ||
| 278 | REP MOVSB | ||
| 279 | |||
| 280 | exec_read_header: | ||
| 281 | ; | ||
| 282 | ; We read in the program header into the above data area and determine | ||
| 283 | ; where in this memory the image will be located. | ||
| 284 | ; | ||
| 285 | Context DS | ||
| 286 | MOV CX,exec_header_len ; header size | ||
| 287 | MOV DX,OFFSET DOSGROUP:exec_signature | ||
| 288 | PUSH ES | ||
| 289 | PUSH DS | ||
| 290 | CALL ExecRead | ||
| 291 | POP DS | ||
| 292 | POP ES | ||
| 293 | JC exec_bad_file | ||
| 294 | OR AX,AX | ||
| 295 | JZ exec_bad_file | ||
| 296 | CMP AX,exec_header_len ; did we read the right number? | ||
| 297 | JNZ exec_com_filej ; yep... continue | ||
| 298 | TEST exec_max_BSS,-1 ; indicate load high? | ||
| 299 | JNZ exec_check_sig | ||
| 300 | MOV exec_load_high,-1 | ||
| 301 | exec_check_sig: | ||
| 302 | MOV AX,exec_signature | ||
| 303 | CMP AX,exe_valid_signature ; zibo arises! | ||
| 304 | JZ exec_save_start ; assume com file if no signature | ||
| 305 | CMP AX,exe_valid_old_signature ; zibo arises! | ||
| 306 | JZ exec_save_start ; assume com file if no signature | ||
| 307 | |||
| 308 | exec_com_filej: | ||
| 309 | JMP exec_com_file | ||
| 310 | |||
| 311 | ; | ||
| 312 | ; We have the program header... determine memory requirements | ||
| 313 | ; | ||
| 314 | exec_save_start: | ||
| 315 | MOV AX,exec_pages ; get 512-byte pages | ||
| 316 | MOV CL,5 ; convert to paragraphs | ||
| 317 | SHL AX,CL | ||
| 318 | SUB AX,exec_par_dir ; AX = size in paragraphs | ||
| 319 | MOV exec_res_len_para,AX | ||
| 320 | |||
| 321 | ; | ||
| 322 | ; Do we need to allocate memory? Yes if function is not load-overlay | ||
| 323 | ; | ||
| 324 | TEST BYTE PTR exec_func,exec_func_overlay | ||
| 325 | JZ exec_allocate ; allocation of space | ||
| 326 | ; | ||
| 327 | ; get load address from block | ||
| 328 | ; | ||
| 329 | LES DI,exec_blk | ||
| 330 | MOV AX,ES:[DI].exec3_load_addr | ||
| 331 | MOV exec_dma,AX | ||
| 332 | MOV AX,ES:[DI].exec3_reloc_fac | ||
| 333 | MOV exec_rel_fac,AX | ||
| 334 | IF DEBUG | ||
| 335 | JMP exec_find_res | ||
| 336 | ELSE | ||
| 337 | JMP SHORT exec_find_res | ||
| 338 | ENDIF | ||
| 339 | |||
| 340 | exec_no_mem: | ||
| 341 | MOV AL,error_not_enough_memory | ||
| 342 | JMP SHORT exec_bomb | ||
| 343 | |||
| 344 | exec_bad_file: | ||
| 345 | MOV AL,error_bad_format | ||
| 346 | |||
| 347 | exec_bomb: | ||
| 348 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 349 | MOV BX,exec_fh | ||
| 350 | CALL exec_dealloc | ||
| 351 | LeaveCrit CritMem | ||
| 352 | SaveReg <AX,BP> | ||
| 353 | invoke $CLOSE | ||
| 354 | RestoreReg <BP,AX> | ||
| 355 | JMP Exec_Ret_Err | ||
| 356 | |||
| 357 | exec_allocate: | ||
| 358 | DOSAssume CS,<DS>,"EXEC/exec_allocate" | ||
| 359 | PUSH AX | ||
| 360 | MOV BX,0FFFFh ; see how much room in arena | ||
| 361 | PUSH DS | ||
| 362 | invoke $ALLOC ; should have carry set and BX has max | ||
| 363 | POP DS | ||
| 364 | POP AX | ||
| 365 | ADD AX,10h ; room for header | ||
| 366 | CMP BX,11h ; enough room for a header | ||
| 367 | JB exec_no_mem | ||
| 368 | CMP AX,BX ; is there enough for bare image? | ||
| 369 | JA exec_no_mem | ||
| 370 | TEST exec_load_high,-1 ; if load high, use max | ||
| 371 | JNZ exec_BX_max ; use max | ||
| 372 | ADD AX,exec_min_BSS ; go for min allocation | ||
| 373 | JC exec_no_mem ; oops! carry | ||
| 374 | CMP AX,BX ; enough space? | ||
| 375 | JA exec_no_mem ; nope... | ||
| 376 | SUB AX,exec_min_BSS | ||
| 377 | ADD AX,exec_max_BSS ; go for the MAX | ||
| 378 | JC exec_BX_max | ||
| 379 | CMP AX,BX | ||
| 380 | JBE exec_got_block | ||
| 381 | |||
| 382 | exec_BX_max: | ||
| 383 | MOV AX,BX | ||
| 384 | |||
| 385 | exec_got_block: | ||
| 386 | PUSH DS | ||
| 387 | MOV BX,AX | ||
| 388 | MOV exec_size,BX | ||
| 389 | invoke $ALLOC ; get the space | ||
| 390 | POP DS | ||
| 391 | JC exec_no_mem | ||
| 392 | MOV exec_load_block,AX | ||
| 393 | ADD AX,10h | ||
| 394 | TEST exec_load_high,-1 | ||
| 395 | JZ exec_use_ax ; use ax for load info | ||
| 396 | ADD AX,exec_size ; go to end | ||
| 397 | SUB AX,exec_res_len_para ; drop off header | ||
| 398 | SUB AX,10h ; drop off pdb | ||
| 399 | exec_use_ax: | ||
| 400 | MOV exec_rel_fac,AX ; new segment | ||
| 401 | MOV exec_dma,AX ; beginning of dma | ||
| 402 | |||
| 403 | ; | ||
| 404 | ; Determine the location in the file of the beginning of the resident | ||
| 405 | ; | ||
| 406 | exec_find_res: | ||
| 407 | MOV DX,exec_par_dir | ||
| 408 | PUSH DX | ||
| 409 | MOV CL,4 | ||
| 410 | SHL DX,CL ; low word of location | ||
| 411 | POP AX | ||
| 412 | MOV CL,12 | ||
| 413 | SHR AX,CL ; high word of location | ||
| 414 | MOV CX,AX ; CX <- high | ||
| 415 | |||
| 416 | ; | ||
| 417 | ; Read in the resident image (first, seek to it) | ||
| 418 | ; | ||
| 419 | MOV BX,exec_fh | ||
| 420 | PUSH DS | ||
| 421 | XOR AL,AL | ||
| 422 | invoke $LSEEK ; seek to resident | ||
| 423 | POP DS | ||
| 424 | jnc exec_big_read | ||
| 425 | jmp exec_bomb | ||
| 426 | |||
| 427 | exec_big_read: ; Read resident into memory | ||
| 428 | MOV BX,exec_res_len_para | ||
| 429 | CMP BX,1000h ; too many bytes to read? | ||
| 430 | JB exec_read_ok | ||
| 431 | MOV BX,0FE0h ; max in one chunk FE00 bytes | ||
| 432 | |||
| 433 | exec_read_ok: | ||
| 434 | SUB exec_res_len_para,BX ; we read (soon) this many | ||
| 435 | PUSH BX | ||
| 436 | MOV CL,4 | ||
| 437 | SHL BX,CL ; get count in bytes from paras | ||
| 438 | MOV CX,BX ; count in correct register | ||
| 439 | PUSH DS | ||
| 440 | MOV DS,exec_dma ; Set up read buffer | ||
| 441 | ASSUME DS:NOTHING | ||
| 442 | XOR DX,DX | ||
| 443 | PUSH CX ; save our count | ||
| 444 | CALL ExecRead | ||
| 445 | POP CX ; get old count to verify | ||
| 446 | POP DS | ||
| 447 | JC exec_bad_fileJ | ||
| 448 | DOSAssume CS,<DS>,"EXEC/exec_read_ok" | ||
| 449 | CMP CX,AX ; did we read enough? | ||
| 450 | POP BX ; get paragraph count back | ||
| 451 | JZ execCheckEnd ; and do reloc if no more to read | ||
| 452 | ; | ||
| 453 | ; The read did not match the request. If we are off by 512 bytes or more | ||
| 454 | ; then the header lied and we have an error. | ||
| 455 | ; | ||
| 456 | SUB CX,AX | ||
| 457 | CMP CX,512 | ||
| 458 | JAE Exec_Bad_fileJ | ||
| 459 | ; | ||
| 460 | ; We've read in CX bytes... bump DTA location | ||
| 461 | ; | ||
| 462 | ExecCheckEnd: | ||
| 463 | ADD exec_dma,BX ; bump dma address | ||
| 464 | TEST exec_res_len_para,-1 | ||
| 465 | JNZ exec_big_read | ||
| 466 | ; | ||
| 467 | ; The image has now been read in. We must perform relocation to | ||
| 468 | ; the current location. | ||
| 469 | ; | ||
| 470 | exec_do_reloc: | ||
| 471 | MOV CX,exec_rel_fac | ||
| 472 | MOV AX,exec_SS ; get initial SS | ||
| 473 | ADD AX,CX ; and relocate him | ||
| 474 | MOV exec_init_SS,AX | ||
| 475 | |||
| 476 | MOV AX,exec_SP ; initial SP | ||
| 477 | MOV exec_init_SP,AX | ||
| 478 | |||
| 479 | LES AX,DWORD PTR exec_IP | ||
| 480 | MOV exec_init_IP,AX | ||
| 481 | MOV AX,ES | ||
| 482 | ADD AX,CX ; relocated... | ||
| 483 | MOV exec_init_CS,AX | ||
| 484 | |||
| 485 | XOR CX,CX | ||
| 486 | MOV DX,exec_rle_table | ||
| 487 | MOV BX,exec_fh | ||
| 488 | PUSH DS | ||
| 489 | XOR AX,AX | ||
| 490 | invoke $LSEEK | ||
| 491 | POP DS | ||
| 492 | |||
| 493 | JNC exec_get_entries | ||
| 494 | exec_bad_filej: | ||
| 495 | JMP exec_bad_file | ||
| 496 | |||
| 497 | exec_get_entries: | ||
| 498 | MOV DX,exec_rle_count ; Number of entries left | ||
| 499 | |||
| 500 | exec_read_reloc: | ||
| 501 | ASSUME DS:NOTHING | ||
| 502 | PUSH DX | ||
| 503 | MOV DX,OFFSET DOSGROUP:exec_internal_buffer | ||
| 504 | MOV CX,((exec_internal_buffer_size)/4)*4 | ||
| 505 | PUSH DS | ||
| 506 | CALL ExecRead | ||
| 507 | POP ES | ||
| 508 | POP DX | ||
| 509 | JC exec_bad_filej | ||
| 510 | MOV CX,(exec_internal_buffer_size)/4 | ||
| 511 | MOV DI,OFFSET DOSGROUP:exec_internal_buffer ; Pointer to byte location in header | ||
| 512 | ; | ||
| 513 | ; Relocate a single address | ||
| 514 | ; | ||
| 515 | MOV SI,exec_rel_fac | ||
| 516 | |||
| 517 | exec_reloc_one: | ||
| 518 | OR DX,DX ; Any more entries? | ||
| 519 | JE exec_set_PDBJ | ||
| 520 | |||
| 521 | exec_get_addr: | ||
| 522 | LDS BX,DWORD PTR ES:[DI] ; Get ra/sa of entry | ||
| 523 | MOV AX,DS ; Relocate address of item | ||
| 524 | ADD AX,SI | ||
| 525 | MOV DS,AX | ||
| 526 | ADD [BX],SI | ||
| 527 | ADD DI,4 | ||
| 528 | DEC DX | ||
| 529 | LOOP exec_reloc_one ; End of internal buffer? | ||
| 530 | |||
| 531 | ; | ||
| 532 | ; We've exhausted a single buffer's worth. Read in the next piece | ||
| 533 | ; of the relocation table. | ||
| 534 | ; | ||
| 535 | |||
| 536 | PUSH ES | ||
| 537 | POP DS | ||
| 538 | JMP exec_read_reloc | ||
| 539 | |||
| 540 | exec_set_PDBJ: | ||
| 541 | JMP exec_set_PDB | ||
| 542 | |||
| 543 | exec_no_memj: | ||
| 544 | JMP exec_no_mem | ||
| 545 | |||
| 546 | ; | ||
| 547 | ; we have a .COM file. First, determine if we are merely loading an overlay. | ||
| 548 | ; | ||
| 549 | exec_com_file: | ||
| 550 | TEST BYTE PTR exec_func,exec_func_overlay | ||
| 551 | JZ exec_alloc_com_file | ||
| 552 | LDS SI,exec_blk ; get arg block | ||
| 553 | LODSW ; get load address | ||
| 554 | MOV exec_dma,AX | ||
| 555 | MOV AX,0FFFFh | ||
| 556 | JMP SHORT exec_read_block ; read it all! | ||
| 557 | |||
| 558 | ; We must allocate the max possible size block (ick!) and set up | ||
| 559 | ; CS=DS=ES=SS=PDB pointer, IP=100, SP=max size of block. | ||
| 560 | ; | ||
| 561 | exec_alloc_com_file: | ||
| 562 | MOV BX,0FFFFh | ||
| 563 | invoke $ALLOC ; largest piece available as error | ||
| 564 | OR BX,BX | ||
| 565 | JZ exec_no_memj | ||
| 566 | MOV exec_size,BX ; save size of allocation block | ||
| 567 | PUSH BX | ||
| 568 | invoke $ALLOC ; largest piece available as error | ||
| 569 | POP BX ; get size of block... | ||
| 570 | MOV exec_load_block,AX | ||
| 571 | ADD AX,10h ; increment for header | ||
| 572 | MOV exec_dma,AX | ||
| 573 | XOR AX,AX ; presume 64K read... | ||
| 574 | CMP BX,1000h ; 64k or more in block? | ||
| 575 | JAE exec_read_com ; yes, read only 64k | ||
| 576 | MOV AX,BX ; convert size to bytes | ||
| 577 | MOV CL,4 | ||
| 578 | SHL AX,CL | ||
| 579 | exec_read_com: | ||
| 580 | SUB AX,100h ; remember size of psp | ||
| 581 | exec_read_block: | ||
| 582 | PUSH AX ; save number to read | ||
| 583 | MOV BX,exec_fh ; of com file | ||
| 584 | XOR CX,CX ; but seek to 0:0 | ||
| 585 | MOV DX,CX | ||
| 586 | XOR AX,AX ; seek relative to beginning | ||
| 587 | invoke $LSEEK ; back to beginning of file | ||
| 588 | POP CX ; number to read | ||
| 589 | MOV DS,exec_dma | ||
| 590 | XOR DX,DX | ||
| 591 | PUSH CX | ||
| 592 | CALL ExecRead | ||
| 593 | POP SI ; get number of bytes to read | ||
| 594 | jnc OkRead | ||
| 595 | jmp exec_bad_file | ||
| 596 | OkRead: | ||
| 597 | CMP AX,SI ; did we read them all? | ||
| 598 | JZ exec_no_memj ; exactly the wrong number... no memory | ||
| 599 | TEST BYTE PTR exec_func,exec_func_overlay | ||
| 600 | JNZ exec_set_PDB ; no starto, chumo! | ||
| 601 | MOV AX,exec_DMA | ||
| 602 | SUB AX,10h | ||
| 603 | MOV exec_init_CS,AX | ||
| 604 | MOV exec_init_IP,100h ; initial IP is 100 | ||
| 605 | ; | ||
| 606 | ; SI is at most FF00h. Add FE to account for PSP - word of 0 on stack. | ||
| 607 | ; | ||
| 608 | ADD SI,0FEh ; make room for stack | ||
| 609 | MOV exec_init_SP,SI ; max value for read is also SP! | ||
| 610 | MOV exec_init_SS,AX | ||
| 611 | MOV DS,AX | ||
| 612 | MOV WORD PTR [SI],0 ; 0 for return | ||
| 613 | |||
| 614 | exec_set_PDB: | ||
| 615 | MOV BX,exec_fh ; we are finished with the file. | ||
| 616 | CALL exec_dealloc | ||
| 617 | PUSH BP | ||
| 618 | invoke $CLOSE ; release the jfn | ||
| 619 | POP BP | ||
| 620 | CALL exec_alloc | ||
| 621 | TEST BYTE PTR exec_func,exec_func_overlay | ||
| 622 | JZ exec_build_header | ||
| 623 | CALL Scan_Execname ;MS.;AN007; | ||
| 624 | CALL Scan_Special_Entries ;MS.;AN007; | ||
| 625 | Leave | ||
| 626 | transfer SYS_RET_OK ; overlay load -> done | ||
| 627 | |||
| 628 | exec_build_header: | ||
| 629 | MOV DX,exec_load_block | ||
| 630 | ; | ||
| 631 | ; assign the space to the process | ||
| 632 | ; | ||
| 633 | |||
| 634 | MOV SI,arena_owner ; pointer to owner field | ||
| 635 | |||
| 636 | MOV AX,exec_environ ; get environ pointer | ||
| 637 | OR AX,AX | ||
| 638 | JZ NO_OWNER ; no environment | ||
| 639 | DEC AX ; point to header | ||
| 640 | MOV DS,AX | ||
| 641 | MOV [SI],DX ; assign ownership | ||
| 642 | NO_OWNER: | ||
| 643 | MOV AX,exec_load_block ; get load block pointer | ||
| 644 | DEC AX | ||
| 645 | MOV DS,AX ; point to header | ||
| 646 | MOV [SI],DX ; assign ownership | ||
| 647 | |||
| 648 | PUSH DS ;AN000;MS. make ES=DS | ||
| 649 | POP ES ;AN000;MS. | ||
| 650 | MOV DI,ARENA_NAME ;AN000;MS. ES:DI points to destination | ||
| 651 | CALL Scan_Execname ;AN007;MS. parse execname | ||
| 652 | ; ds:si->name, cx=name length | ||
| 653 | PUSH CX ;AN007;;MS. save for fake version | ||
| 654 | PUSH SI ;AN007;;MS. save for fake version | ||
| 655 | |||
| 656 | movename: ;AN000; | ||
| 657 | LODSB ;AN000;;MS. get char | ||
| 658 | CMP AL,'.' ;AN000;;MS. is '.' ,may be name.exe | ||
| 659 | JZ mem_done ;AN000;;MS. no, move to header | ||
| 660 | ;AN000; | ||
| 661 | STOSB ;AN000;;MS. move char | ||
| 662 | LOOP movename ;AN000;;MS. continue | ||
| 663 | mem_done: ;AN000; | ||
| 664 | XOR AL,AL ;AN000;;MS. make ASCIIZ | ||
| 665 | CMP DI,SIZE ARENA ;AN000;MS. if not all filled | ||
| 666 | JAE fill8 ;AN000;MS. | ||
| 667 | STOSB ;AN000;MS. | ||
| 668 | fill8: ;AN000; | ||
| 669 | POP SI ;AN007;MS. ds:si -> file name | ||
| 670 | POP CX ;AN007;MS. | ||
| 671 | |||
| 672 | CALL Scan_Special_Entries ;AN007;MS. | ||
| 673 | |||
| 674 | PUSH DX | ||
| 675 | MOV SI,exec_size | ||
| 676 | ADD SI,DX | ||
| 677 | invoke $Dup_PDB ; ES is now PDB | ||
| 678 | POP DX | ||
| 679 | |||
| 680 | PUSH exec_environ | ||
| 681 | POP ES:[PDB_environ] | ||
| 682 | ; | ||
| 683 | ; set up proper command line stuff | ||
| 684 | ; | ||
| 685 | LDS SI,exec_blk ; get the block | ||
| 686 | PUSH DS ; save its location | ||
| 687 | PUSH SI | ||
| 688 | LDS SI,[SI.exec0_5C_FCB] ; get the 5c fcb | ||
| 689 | ; | ||
| 690 | ; DS points to user space 5C FCB | ||
| 691 | ; | ||
| 692 | MOV CX,12 ; copy drive, name and ext | ||
| 693 | PUSH CX | ||
| 694 | MOV DI,5Ch | ||
| 695 | MOV BL,[SI] | ||
| 696 | REP MOVSB | ||
| 697 | ; | ||
| 698 | ; DI = 5Ch + 12 = 5Ch + 0Ch = 68h | ||
| 699 | ; | ||
| 700 | XOR AX,AX ; zero extent, etc for CPM | ||
| 701 | STOSW | ||
| 702 | STOSW | ||
| 703 | ; | ||
| 704 | ; DI = 5Ch + 12 + 4 = 5Ch + 10h = 6Ch | ||
| 705 | ; | ||
| 706 | POP CX | ||
| 707 | POP SI ; get block | ||
| 708 | POP DS | ||
| 709 | PUSH DS ; save (again) | ||
| 710 | PUSH SI | ||
| 711 | LDS SI,[SI.exec0_6C_FCB] ; get 6C FCB | ||
| 712 | ; | ||
| 713 | ; DS points to user space 6C FCB | ||
| 714 | ; | ||
| 715 | MOV BH,[SI] ; do same as above | ||
| 716 | REP MOVSB | ||
| 717 | STOSW | ||
| 718 | STOSW | ||
| 719 | POP SI ; get block (last time) | ||
| 720 | POP DS | ||
| 721 | LDS SI,[SI.exec0_com_line] ; command line | ||
| 722 | ; | ||
| 723 | ; DS points to user space 80 command line | ||
| 724 | ; | ||
| 725 | OR CL,80h | ||
| 726 | MOV DI,CX | ||
| 727 | REP MOVSB ; Wham! | ||
| 728 | ; | ||
| 729 | ; Process BX into default AX (validity of drive specs on args). We no longer | ||
| 730 | ; care about DS:SI. | ||
| 731 | ; | ||
| 732 | DEC CL ; get 0FFh in CL | ||
| 733 | MOV AL,BH | ||
| 734 | XOR BH,BH | ||
| 735 | invoke GetVisDrv | ||
| 736 | JNC exec_BL | ||
| 737 | MOV BH,CL | ||
| 738 | exec_BL: | ||
| 739 | MOV AL,BL | ||
| 740 | XOR BL,BL | ||
| 741 | invoke GetVisDrv | ||
| 742 | JNC exec_Set_Return | ||
| 743 | MOV BL,CL | ||
| 744 | exec_set_return: | ||
| 745 | invoke get_user_stack ; get his return address | ||
| 746 | PUSH [SI.user_CS] ; suck out the CS and IP | ||
| 747 | PUSH [SI.user_IP] | ||
| 748 | PUSH [SI.user_CS] ; suck out the CS and IP | ||
| 749 | PUSH [SI.user_IP] | ||
| 750 | POP WORD PTR ES:[PDB_Exit] | ||
| 751 | POP WORD PTR ES:[PDB_Exit+2] | ||
| 752 | XOR AX,AX | ||
| 753 | MOV DS,AX | ||
| 754 | POP DS:[addr_int_terminate] ; save them where we can get them later | ||
| 755 | POP DS:[addr_int_terminate+2] ; when the child exits. | ||
| 756 | MOV WORD PTR DMAADD,80h | ||
| 757 | MOV DS,CurrentPDB | ||
| 758 | MOV WORD PTR DMAADD+2,DS | ||
| 759 | TEST BYTE PTR exec_func,exec_func_no_execute | ||
| 760 | JZ exec_go | ||
| 761 | |||
| 762 | LDS SI,DWORD PTR exec_init_SP ; get stack | ||
| 763 | LES DI,exec_blk ; and block for return | ||
| 764 | MOV ES:[DI].exec1_SS,DS ; return SS | ||
| 765 | |||
| 766 | DEC SI ; 'push' default AX | ||
| 767 | DEC SI | ||
| 768 | MOV [SI],BX ; save default AX reg | ||
| 769 | MOV ES:[DI].exec1_SP,SI ; return 'SP' | ||
| 770 | |||
| 771 | LDS AX,DWORD PTR exec_init_IP | ||
| 772 | MOV ES:[DI].exec1_CS,DS ; initial entry stuff | ||
| 773 | |||
| 774 | MOV ES:[DI].exec1_IP,AX | ||
| 775 | Leave | ||
| 776 | transfer SYS_RET_OK | ||
| 777 | |||
| 778 | exec_go: | ||
| 779 | LDS SI,DWORD PTR exec_init_IP ; get entry point | ||
| 780 | LES DI,DWORD PTR exec_init_SP ; new stack | ||
| 781 | MOV AX,ES | ||
| 782 | ; | ||
| 783 | ; DS:SI points to entry point | ||
| 784 | ; AX:DI points to initial stack | ||
| 785 | ; DX has PDB pointer | ||
| 786 | ; BX has initial AX value | ||
| 787 | ; | ||
| 788 | CLI | ||
| 789 | MOV BYTE PTR INDOS,0 | ||
| 790 | ASSUME SS:NOTHING | ||
| 791 | MOV SS,AX ; set up user's stack | ||
| 792 | MOV SP,DI ; and SP | ||
| 793 | STI | ||
| 794 | PUSH DS ; fake long call to entry | ||
| 795 | PUSH SI | ||
| 796 | MOV ES,DX ; set up proper seg registers | ||
| 797 | MOV DS,DX | ||
| 798 | MOV AX,BX ; set up proper AX | ||
| 799 | procedure exec_long_ret,FAR | ||
| 800 | |||
| 801 | IF BUFFERFLAG | ||
| 802 | invoke restore_user_map | ||
| 803 | ENDIF | ||
| 804 | |||
| 805 | RET | ||
| 806 | EndProc exec_long_ret | ||
| 807 | |||
| 808 | EndProc $Exec | ||
| 809 | |||
| 810 | Procedure ExecRead,NEAR | ||
| 811 | CALL exec_dealloc | ||
| 812 | MOV bx,exec_fh | ||
| 813 | PUSH BP | ||
| 814 | invoke $READ | ||
| 815 | POP BP | ||
| 816 | CALL exec_alloc | ||
| 817 | return | ||
| 818 | EndProc ExecRead | ||
| 819 | |||
| 820 | procedure exec_dealloc,near | ||
| 821 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 822 | PUSH BX | ||
| 823 | MOV BX,arena_owner_system | ||
| 824 | EnterCrit CritMEM | ||
| 825 | CALL ChangeOwners | ||
| 826 | POP BX | ||
| 827 | return | ||
| 828 | EndProc exec_dealloc | ||
| 829 | |||
| 830 | procedure exec_alloc,near | ||
| 831 | PUSH BX | ||
| 832 | MOV BX,CurrentPDB | ||
| 833 | CALL ChangeOwners | ||
| 834 | LeaveCrit CritMEM | ||
| 835 | POP BX | ||
| 836 | return | ||
| 837 | EndProc exec_alloc | ||
| 838 | |||
| 839 | procedure ChangeOwners,NEAR | ||
| 840 | pushf | ||
| 841 | PUSH AX | ||
| 842 | MOV AX,exec_environ | ||
| 843 | CALL ChangeOwner | ||
| 844 | MOV AX,exec_load_block | ||
| 845 | Call ChangeOwner | ||
| 846 | POP AX | ||
| 847 | popf | ||
| 848 | return | ||
| 849 | EndProc ChangeOwners | ||
| 850 | |||
| 851 | Procedure ChangeOwner,near | ||
| 852 | OR AX,AX ; is area allocated? | ||
| 853 | retz ; no, do nothing | ||
| 854 | DEC AX | ||
| 855 | PUSH DS | ||
| 856 | MOV DS,AX | ||
| 857 | MOV DS:[arena_owner],BX | ||
| 858 | POP DS | ||
| 859 | return | ||
| 860 | EndProc ChangeOwner | ||
| 861 | |||
| 862 | Procedure Scan_Execname,near ;AN000;MS. | ||
| 863 | |||
| 864 | LDS SI,execName ;AN000;MS. DS:SI points to name | ||
| 865 | save_begin: ;AN000; | ||
| 866 | MOV CX,SI ;AN000;MS. CX= starting addr | ||
| 867 | scan0: ;AN000; | ||
| 868 | LODSB ;AN000;MS. get char | ||
| 869 | CMP AL,':' ;AN000;;MS. is ':' , may be A:name | ||
| 870 | JZ save_begin ;AN000;;MS. yes, save si | ||
| 871 | CMP AL,'\' ;AN000;;MS. is '\', may be A:\name | ||
| 872 | JZ save_begin ;AN000;;MS. yes, save si | ||
| 873 | CMP AL,0 ;AN000;;MS. is end of name | ||
| 874 | JNZ scan0 ;AN000;;MS. no, continue scanning | ||
| 875 | SUB SI,CX ;AN000;;MS. get name's length | ||
| 876 | XCHG SI,CX ;AN000;;MS. cx= length, si= starting addr | ||
| 877 | |||
| 878 | return ;AN000;;MS. | ||
| 879 | EndProc Scan_Execname ;AN000;;MS. | ||
| 880 | |||
| 881 | |||
| 882 | Procedure Scan_Special_Entries,near ;AN000;MS. | ||
| 883 | |||
| 884 | DEC CX ;AN007;MS. cx= name length | ||
| 885 | MOV DI,CS:[Special_Entries] ;AN007;MS. es:di -> addr of special entries | ||
| 886 | CALL Reset_Version ;AN008;MS. | ||
| 887 | PUSH CS ;AN007;MS. | ||
| 888 | POP ES ;AN007;MS. | ||
| 889 | Getentries: ;AN007;MS. | ||
| 890 | MOV AL,ES:[DI] ;AN007;MS. end of list | ||
| 891 | OR AL,AL ;AN007;MS. | ||
| 892 | JZ end_list ;AN007;MS. yes | ||
| 893 | MOV CS:[Temp_Var2],DI ;AN007;MS. save di | ||
| 894 | CMP AL,CL ;AN007;MS. same length ? | ||
| 895 | JNZ skipone ;AN007;MS. no | ||
| 896 | INC DI ;AN007;MS. es:di -> special name | ||
| 897 | PUSH CX ;AN007;MS. save length and name addr | ||
| 898 | PUSH SI ;AN007;MS. | ||
| 899 | REPZ CMPSB ;AN007;MS. same name ? | ||
| 900 | JNZ not_matched ;AN007;MS. no | ||
| 901 | MOV AX,ES:[DI] ;AN007;MS. get special version | ||
| 902 | MOV CS:[Special_Version],AX ;AN007;MS. save it | ||
| 903 | MOV AL,ES:[DI+2] ;AN008;MS. get fake count | ||
| 904 | MOV CS:[Fake_Count],AL ;AN007;MS. save it | ||
| 905 | POP SI ;AN007;MS. | ||
| 906 | POP CX ;AN007;MS. | ||
| 907 | JMP SHORT end_list ;AN007;MS. | ||
| 908 | not_matched: ;AN007;MS. | ||
| 909 | POP SI ;AN007;MS. restore si,cx | ||
| 910 | POP CX ;AN007;MS. | ||
| 911 | skipone: ;AN007;MS. | ||
| 912 | MOV DI,CS:[Temp_Var2] ;AN007;MS. restore old di | ||
| 913 | XOR AH,AH ;AN007;MS. position to next entry | ||
| 914 | ADD DI,AX ;AN007;MS. | ||
| 915 | ADD DI,4 ;AN007;MS. | ||
| 916 | JMP Getentries ;AN007;MS. | ||
| 917 | |||
| 918 | |||
| 919 | end_list: ;AN007;MS. | ||
| 920 | return | ||
| 921 | EndProc Scan_Special_Entries ;AN000;;MS. | ||
| 922 | |||
| 923 | Procedure Reset_Version,near ;AN008;MS. | ||
| 924 | |||
| 925 | CMP CS:[Fake_Count],0FFH ;AN008;MS. | ||
| 926 | JNZ dont_reset ;AN008;MS. | ||
| 927 | MOV CS:[Special_Version],0 ;AN008;MS. reset to current version | ||
| 928 | dont_reset: | ||
| 929 | return | ||
| 930 | EndProc Reset_Version,near ;AN008;;MS. | ||
| 931 | \ No newline at end of file | ||