diff options
Diffstat (limited to 'v2.0/source/EXEC.ASM')
| -rw-r--r-- | v2.0/source/EXEC.ASM | 1035 |
1 files changed, 1035 insertions, 0 deletions
diff --git a/v2.0/source/EXEC.ASM b/v2.0/source/EXEC.ASM new file mode 100644 index 0000000..d41aceb --- /dev/null +++ b/v2.0/source/EXEC.ASM | |||
| @@ -0,0 +1,1035 @@ | |||
| 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 | ||