doexec.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 294 行

ASM
294
字号
;*****************************************************************************
;*
;*                            Open Watcom Project
;*
;*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
;*
;*  ========================================================================
;*
;*    This file contains Original Code and/or Modifications of Original
;*    Code as defined in and that are subject to the Sybase Open Watcom
;*    Public License version 1.0 (the 'License'). You may not use this file
;*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
;*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
;*    provided with the Original Code and Modifications, and is also
;*    available at www.sybase.com/developer/opensource.
;*
;*    The Original Code and all software distributed under the License are
;*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
;*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
;*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
;*    NON-INFRINGEMENT. Please see the License for the specific language
;*    governing rights and limitations under the License.
;*
;*  ========================================================================
;*
;* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
;*               DESCRIBE IT HERE!
;*
;*****************************************************************************


include msdos.inc
include mdef.inc
include struct.inc

        name    doexec

if _MODEL and _BIG_CODE
        extrn   execve_         :far
        extrn   __init_execve_  :far
else
        extrn   execve_         :near
        extrn   __init_execve_  :near
endif
        extrn   __close_ovl_file:dword

_TEXT   segment byte public 'CODE'
_TEXT   ends

include xinit.inc

        xinit   __init_execve_,DEF_PRIORITY

        assume  cs: _TEXT, ds: DGROUP, ss: DGROUP, es: DGROUP

CR      =       00dh                    ; ASCII carriage return
NL      =       00ah                    ; ASCII line feed

common_code macro
        local   beg,badfmt,badenv,nomem
beg:
        push    cs                      ; Set up ds = cs.
        pop     ds                      ;
        callos                          ; Actually perform the load.
        _if     c                       ; If it failed,
          _guess                        ; .. determine appropriate message,
            cmp         al,E_ifunc      ;
            _quif       ne              ;
            mov         dx,badfmt-beg   ;
          _admit                        ;
            cmp         al,E_badfmt     ;
            _quif       ne              ;
            mov         dx,badfmt-beg   ;
          _admit                        ;
            cmp         al,E_badenv     ;
            _quif       ne              ;
            mov         dx,badenv-beg   ;
          _admit                        ;
            mov         dx,nomem-beg    ;
          _endguess                     ;
          callos message                ; .. print it out,
          mov   al,-1                   ; .. and terminate with a return code
          callos terminate              ; .. of -1.
badfmt    db    'Bad format on exec',CR,NL,'$'
badenv    db    'Bad environment on exec',CR,NL,'$'
nomem     db    'Not enough memory on exec',CR,NL,'$'
        _endif                          ; Endif.
        endm

        _TEXT   segment
fake    proc    far                     ; Force returns to be far returns.
exebeg:
        common_code                     ; Do load, check for errors.

        mov     si,newss-exebeg         ;
        lodsw                           ; Set up the new stack.
        mov     dx,ax                   ;
        lodsw                           ;
        mov     ss,dx                   ;
        mov     sp,ax                   ;
        lodsw                           ; Set up new cs:ip by faking up an
        push    ax                      ; address for a far return.
        lodsw                           ;
        push    ax                      ;
        push    es                      ; Set up new ds.
        pop     ds                      ;
        ret                             ; Start execution of loaded program.

newss   dw      ?                       ; Save area for ss,
newsp   dw      ?                       ; sp,
newcs   dw      ?                       ; cs,
newip   dw      ?                       ; and ip.
exeend:

combeg:
        common_code                     ; Do load, check for errors.

        mov     bx,cs                   ; Set up the stack for the load module
        mov     ax,es                   ; just below the loader (The loader is
        sub     bx,ax                   ; as high as possible in memory.)
        cmp     bx,1000h                ; Since ss = ds = cs,
        _if     a                       ; If more than 4k (64k bytes) avail
          mov   bx,1000h                ; .. limit ourselves to 4k
        _endif                          ; Endif.
        mov     cl,4                    ; Convert from paragraphs to bytes.
        shl     bx,cl                   ;
        dec     bx                      ;
        dec     bx                      ;
        mov     word ptr es:[bx],0000h  ; es:bx will be the top stack word.
        mov     ss,ax                   ; Set up new stack.
        mov     sp,bx                   ;
        push    es                      ; Set up new cs:ip by faking up an
        mov     ax,100h                 ; address for a far return.
        push    ax                      ;
        push    es                      ; Set up new ds.
        pop     ds                      ;
        mov     ax,bp                   ; ah, al == 0ffh iff fcb1, 2 are valid.
        ret                             ; Start execution of loaded program.
comend:
fake    endp
_TEXT   ends

psplen  =       100h                    ; length of psp
max_para =      (comend-combeg+80h+15)/16; .COM loader is bigger, 80h stack

        _DATA   segment

        extrn   "C",_psp:word
        public  ___p_overlay
___p_overlay  dw        2

        public  ___exec_para
___exec_para dw max_para                ; paragraphs needed for loader

loader  label   dword                   ; far pointer to loader
loaderip dw     0                       ; ip always 0
loadercs dw     ?                       ; cs will be filled in

pathlen dw      ?                       ; length of path

_DATA   ends

        _TEXT   segment
;
;       void _doexec( path, cmdline, exe, exess, exesp, execs, exeip )
;
        public  __doexec
__doexec proc    far

        mov     bp,sp                   ; gain access to parms

s_frame struc                           ; define stack frame
        dd      ?                       ; return address
path    dw      ?                       ; pointer to path
cmdline dw      ?                       ; pointer to command line
isexe   dw      ?                       ; 1 => .EXE, 0 => .COM
exess   dw      ?                       ; ss offset for .EXE
exesp   dw      ?                       ; sp value for .EXE
execs   dw      ?                       ; cs offset for .EXE
exeip   dw      ?                       ; ip value for .EXE
s_frame ends

        mov     ax,ss                   ; set ds=ss
        mov     ds,ax                   ; . . .
        mov     ax,_psp                 ;
        mov     es,ax                   ;
        xor     al,al                   ; Zero out FCB's 1 and 2.
        mov     di,5ch                  ;
        mov     cx,DOS_cmdline-5ch      ;
        rep     stosb                   ;
        mov     si,cmdline[bp]          ; Copy over command line.
        mov     cl,0[si]                ;
        inc     cx                      ; +1 to include the length byte
        inc     cx                      ; +1 more to get the trailing CR
        cmp     cx,128                  ; if too long
        _if     a                       ; then
          mov   cx,128                  ; - set to maximum
        _endif                          ; endif
        rep     movsb                   ;

        push    ds                      ; Save ds.
        mov     ax,es                   ;
        mov     ds,ax                   ;
        mov     dx,DOS_cmdline          ; Set Disk Transfer Address
        callos  setDMA                  ;
        mov     di,5ch                  ; Set up FCB 1.
        mov     si,DOS_cmdline+1        ;
        mov     al,01h                  ;
        callos  fcbparse                ;
        cmp     al,0ffh                 ;
        _if     ne                      ; If succeeded
          xor   al,al                   ; .. set flag to 0
        _endif                          ; Endif
        mov     bl,al                   ; **** Saved in bl for later.
        mov     di,6ch                  ; Set up FCB 2.
        mov     al,01h                  ;
        callos  fcbparse                ;
        cmp     al,0ffh                 ;
        _if     ne                      ; If succeeded
          xor   al,al                   ; .. set flag to 0
        _endif                          ; Endif
        mov     bh,al                   ; **** Saved in bh for later.
        pop     ds                      ; Restore ds.

        mov     ax,ds                   ;
        mov     es,ax                   ;
        mov     di,path[bp]             ; Calculate length of path.
        xor     cx,cx                   ;
        not     cx                      ; cx = 0ffffh
        xor     al,al                   ;
        repne   scasb                   ;
        not     cx                      ; cx = length
        mov     pathlen,cx              ;
        mov     dx,cx                   ;
        add     dx,15                   ; Convert to para.
        mov     cl,4                    ;
        shr     dx,cl                   ;
        mov     es,_psp                 ; Calculate where we should put loader.
        mov     ax,es:DOS_maxpara       ; top of block
        sub     ax,dx                   ; account for path
        sub     ax,max_para             ; and for loader and stack
        mov     es,ax                   ;
        mov     loadercs,ax             ; Save for eventual jump to loader.
        xor     di,di                   ; Put loader at offset 0.
        cmp     word ptr isexe[bp],0    ;
        _if     ne                      ; If exe file
          mov   si,offset exebeg        ; .. use .EXE file loader
          mov   cx,exeend-exebeg        ;
        _else                           ; Else
          mov   si,offset combeg        ; .. use .COM file loader
          mov   cx,comend-combeg        ;
        _endif                          ; Endif.
        push    ds                      ;
        mov     ax,cs                   ;
        mov     ds,ax                   ;
        rep     movsb                   ; Move loader into high memory.
        pop     ds                      ;
        mov     di,max_para*16          ;
        mov     si,path[bp]             ;
        mov     cx,pathlen              ;
        rep     movsb                   ; Move path into high memory.
        mov     cx,_psp                 ; Calculate relocation factor for load.
        add     cx,psplen/16            ;
        cmp     word ptr isexe[bp],0    ;
        _if     ne                      ; If we have an EXE file
          mov   ax,exess[bp]            ; .. fix up and save the new ss,
          add   ax,cx                   ;
          mov   word ptr es:[newss-exebeg],ax;
          mov   ax,exesp[bp]            ; .. sp,
          mov   word ptr es:[newsp-exebeg],ax;
          mov   ax,execs[bp]            ; .. cs,
          add   ax,cx                   ;
          mov   word ptr es:[newcs-exebeg],ax;
          mov   ax,exeip[bp]            ; .. and ip.
          mov   word ptr es:[newip-exebeg],ax;
        _endif                          ; Endif.
        call    dword ptr __close_ovl_file; close overlay file - if open
        mov     bp,bx                   ; Get flags for FCBs into bp.
        mov     ax,es                   ; Switch to loader stack.
        mov     dx,max_para*16          ; Pointer to path.
        mov     ss,ax                   ;
        mov     sp,dx                   ; Stack just below path.
        mov     es,_psp                 ; es points to mem block to be loaded.
        mov     bx,psplen               ;
        mov     es:0[bx],cx             ; Segment where file will be loaded.
        mov     es:2[bx],cx             ; Relocation to be applied to image.
        mov     ax,04b03h               ; Load overlay function.
        jmp     loader
__doexec endp
_TEXT   ends

        end

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?