loadle.asm

来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 2,013 行 · 第 1/4 页

ASM
2,013
字号
DEBUG4X EQU     1
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;LE object format.

;
LE_OBJ          struc
LE_OBJ_Size             dd ?    ;virtual size in bytes.
LE_OBJ_Base             dd ?    ;relocation base address.
;
LE_OBJ_Flags            dd ?    ;object flags.
LE_OBJ_PageIndex        dd ?    ;page map index.
LE_OBJ_PageNum          dd ?    ;page map entries.
LE_OBJ_Reserved db 4 dup (0)    ;reserved.
LE_OBJ          ends


;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Somewhere to load the LE header.
;
LEHeader        LE_Header <>

LETemp  db 256 dup (0)

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;Load, relocate and execute the application code. LE format loader.
;
;On Entry:
;
;EBX    - Mode.
;       0 - Normal EXEC.
;       1 - Load for debug.
;       2 - Load for overlay.
;DS:EDX - File name.
;ES:ESI - Command line.
;CX     - Environment selector, 0 to use existing copy.
;
;On Exit:
;
;Carry set on error and AX = error code else,
;
;If Mode=0
;
;AL = ErrorLevel (returned by child's terminate)
;
;If Mode=1
;
;CX:EDX - Entry CS:EIP
;BX:EAX - Entry SS:ESP
;SI     - PSP.
;DI     - Auto DS.
;EBP    - Segment definition memory.
;
;If Mode=2
;
;CX:EDX - Entry CS:EIP
;BX:EAX - Entry SS:ESP
;SI     - PSP.
;
;Error codes:
;
;1      - DOS file access error.
;2      - Not an LE file.
;3      - Not enough memory.
;
LoadLE  proc    near
        mov     ax,ds
        push    ds
        push    es
        push    fs
        push    gs
        assume ds:nothing
        mov     ds,cs:apiDDSeg
        assume ds:_apiCode
        ;
        push    d[load1_Name]
        push    w[load1_Name+4]
        push    d[load1_Flags]
        push    d[load1_Command]
        push    w[load1_command+4]
        push    w[load1_Environment]
        push    w[load1_Handle]
        push    w[load1_PSP]
        push    d[load1_ProgMem]
        push    d[load1_ProgMem+4]
        push    d[load1_Segs]
        push    d[load1_ObjMem]
        push    d[load1_FixupMem]
        push    d[load1_ObjCount]
        push    d[load1_ObjBase]
        push    d[load1_PageCount]
        push    d[load1_PageCount+4]
        push    d[load1_EntryEIP]
        push    w[load1_EntryCS]
        push    d[load1_EntryESP]
        push    w[load1_EntrySS]
        push    w[load1_EntryDS]
        push    w[load1_EntryES]
        push    d[load1_ModLink]
        push    d[load1_ModLink+4]
        push    d[load1_LEOffset]
        ;
        mov     d[load1_Name],edx
        mov     w[load1_Name+4],ax
        mov     d[load1_Flags],ebx
        mov     d[load1_Command],esi
        mov     w[load1_Command+4],es
        mov     w[load1_Environment],cx
        ;
        xor     eax,eax
        mov     w[load1_Handle],ax
        mov     w[load1_PSP],ax
        mov     d[load1_ProgMem],eax
        mov     d[load1_Segs],eax
        mov     d[load1_ObjMem],eax
        mov     d[load1_FixupMem],eax
        mov     d[load1_ModLink],eax
        mov     d[load1_ModLink+4],eax

;
;Try and open the file.
;
        push    ds
        lds     edx,f[load1_Name]
        mov     ax,3d00h                ;open, read only.
        int     21h
        pop     ds
        jc      load1_no_file_error
        mov     w[load1_Handle],ax      ;store the handle.
;
;Check it's an MZ file.
;
        mov     bx,w[load1_Handle]
        mov     edx,offset LEHeader     ;somewhere to put the info.
        mov     ecx,2
        mov     ah,3fh
        int     21h
        jc      load1_file_error
        cmp     ax,cx
        jnz     load1_file_error
        cmp     w[LEHeader],'ZM'
        jnz     load1_file_error

;Look for an LE offset.
;
GetLEOff:
        mov     bx,w[load1_Handle]
        mov     dx,3ch
        xor     cx,cx
        mov     ax,4200h
        int     21h
        mov     edx,offset LEHeader
        mov     ecx,4
        mov     ah,3fh
        int     21h             ;Fetch LE offset.
        jc      load1_file_error
        cmp     ax,cx
        jnz     load1_file_error
        cmp     d[LEHeader],0   ;any offset?
        jz      load1_file_error
        mov     eax,d[LEHeader]

SaveLEOff:
        mov     d[load1_LEOffset],eax
;
;Load the LE header.
;
        mov     dx,w[LEHeader]
        mov     cx,w[LEHeader+2]
        mov     ax,4200h
        int     21h             ;Move to LE section.
        mov     edx,offset LEHeader
        mov     ecx,size LE_Header
        mov     ah,3fh
        int     21h
        jc      load1_file_error
        cmp     ax,cx
        jnz     load1_file_error
;
;Check it really is an LE file.
;
        cmp     w[LEHeader],"EL"
        jnz     load1_file_error
;
;Close the file again.
;
medclose:
        mov     bx,w[load1_Handle]
        mov     ah,3eh
        int     21h
        mov     w[load1_Handle],0
;
;Create a new PSP.
;
        push    ds
        mov     ebx,d[load1_Flags]
        mov     cx,w[load1_Environment]
        les     esi,f[load1_command]
        lds     edx,f[load1_name]
        call    CreatePSP
        pop     ds
        mov     w[load1_PSP],bx
        jc      load1_mem_error
;
;Open the input file again.
;
        push    ds
        lds     edx,f[load1_Name]
        mov     ax,3d00h                ;open, read only.
        int     21h
        pop     ds
        jc      load1_file_error
        mov     w[load1_Handle],ax      ;store the handle.
;
;Process any EXPORT entries that need pulling in.
;
;       cmp     d[LE_Header.LE_ResidentNames+LEHeader],0
TempAddress     =       LE_Header.LE_ResidentNames
TempAddress     =       TempAddress+LEHeader
        cmp     DWORD PTR [TempAddress],0

        jz      load1_NoExports

IFDEF DEBUG4X
        jmp     load1_NoExports
ENDIF

        mov     es,apiDSeg
        assume es:_cwMain
        mov     es,es:RealSegment
        assume es:nothing
        ;
        ;Set file pointer to resident names.
        ;
        mov     ecx,d[LE_Header.LE_ResidentNames+LEHeader]
        add     ecx,d[load1_LEOffset]
        mov     dx,cx
        shr     ecx,16
        mov     bx,w[load1_Handle]
        mov     ax,4200h
        int     21h
        ;
        ;Sit in a loop reading names.
        ;
        xor     ebp,ebp         ;reset entry count.
        mov     edi,4           ;reset bytes required.
load1_ge0:      mov     edx,offset LETemp
        mov     ecx,1
        mov     ah,3fh
        int     21h
        jc      load1_file_error
        cmp     ax,1
        jnz     load1_file_error
        xor     eax,eax
        mov     al,[edx]
        and     al,127
        jz      load1_ge1               ;end of the list?
        add     eax,1           ;include count byte
        add     eax,2           ;include ordinal/segment
        inc     ebp             ;update name count.
        add     edi,eax
        add     edi,4           ;dword of value
        add     edi,4           ;table entry memory required.
        mov     ecx,eax
        dec     ecx
        mov     ah,3fh
        int     21h             ;read rest of the entry to skip it.
        jc      load1_file_error
        cmp     ax,cx
        jnz     load1_file_error
        jmp     load1_ge0               ;fetch all names.
        ;
        ;Allocate EXPORT table memory.
        ;
load1_ge1:      mov     ecx,edi
        sys     GetMemLinear32
        jc      load1_mem_error
        mov     DWORD PTR es:[esi],0            ;reset count.
        push    es
        mov     es,w[load1_PSP]
        mov     DWORD PTR es:[EPSP_Struc.EPSP_Exports],esi
        pop     es
        mov     edi,ebp         ;get number of entries.
        shl     edi,2           ;dword per entry.
        add     edi,4           ;allow for count dword.
        add     edi,esi         ;point to target memory.
        mov     edx,esi
        add     edx,4           ;point to table memory.
        ;
        ;Move back to start of names again.
        ;
        push    ecx
        push    edx
        mov     ecx,d[LE_Header.LE_ResidentNames+LEHeader]
        add     ecx,d[load1_LEOffset]
        mov     dx,cx
        shr     ecx,16
        mov     ax,4200h
        int     21h
        pop     edx
        pop     ecx
        ;
        ;Read all the names again.
        ;
load1_ge2:      or      ebp,ebp         ;done all names?
        jz      load1_ge3
        push    edx
        mov     ecx,1
        mov     edx,offset LETemp
        mov     ah,3fh
        int     21h             ;get name string length.
        pop     edx
        jc      load1_file_error
        cmp     ax,1
        jnz     load1_file_error
        movzx   ecx,b[LETemp]
        and     cl,127          ;name length.
        add     ecx,2           ;include ordinal.
        mov     ah,3fh
        push    edx
        mov     edx,offset LETemp+1
        int     21h             ;read rest of this entry.
        pop     edx
        jc      load1_file_error
        cmp     ax,cx
        jnz     load1_file_error
        inc     DWORD PTR es:[esi]              ;update EXPORT count.
        mov     es:[edx],edi            ;set this entries address.
        add     edx,4
        mov     DWORD PTR es:[edi],0            ;clear offset.
        add     edi,4
        movzx   eax,b[LETemp]
        and     eax,127
        inc     eax
        mov     ecx,eax
        add     eax,offset LETemp
        movzx   eax,w[eax]
        mov     es:[edi],ax             ;set entry table ordinal.
        add     edi,2
        push    esi
        mov     esi,offset LETemp
        rep     movsb           ;copy EXPORT name.
        pop     esi
        dec     ebp
        jmp     load1_ge2
load1_ge3:      dec     DWORD PTR es:[esi]              ;lose module name from the count.
;
;Get object definition memory.
;
load1_NoExports:        mov     eax,size LE_OBJ ;length of an object entry.

;       mul     d[LE_Header.LE_ObjNum+LEHeader] ;number of objects.
TempAddress     =       LE_Header.LE_ObjNum
TempAddress     =       TempAddress+LEHeader
        mul     DWORD PTR [TempAddress] ;number of objects.

        mov     ecx,eax
        sys     GetMemLinear32  ;Get memory.
        jc      load1_mem_error         ;Not enough memory.
        mov     d[load1_ObjMem],esi
;
;Read object definitions.
;
        push    ecx
        mov     bx,w[load1_Handle]
        mov     ecx,d[LE_Header.LE_ObjOffset+LEHeader] ;Get object table offset.
        add     ecx,d[load1_LEOffset]
        mov     dx,cx
        shr     ecx,16
        mov     ax,4200h
        int     21h
        pop     ecx
        mov     edx,d[load1_ObjMem]
        push    ds
        mov     ds,apiDSeg
        assume ds:_cwMain
        mov     ds,RealSegment
        assume ds:_apiCode
        mov     ah,3fh
        int     21h             ;read definitions.
        pop     ds
        jc      load1_file_error
        cmp     ax,cx
        jnz     load1_file_error
;
;Work out how much memory we need for the program.
;
        mov     es,apiDSeg
        assume es:_cwMain
        mov     es,es:RealSegment
        assume es:nothing
        mov     ecx,d[LE_Header.LE_ObjNum+LEHeader]     ;number of objects.
        mov     esi,d[load1_ObjMem]
        xor     ebp,ebp         ;clear memory requirement.
load1_objup0:   mov     eax,es:LE_OBJ.LE_OBJ_Size[esi]
        add     eax,4095
        and     eax,not 4095            ;page align objects
        mov     es:LE_OBJ.LE_OBJ_Size[esi],eax
        add     ebp,eax         ;update program memory length.
        add     esi,size LE_OBJ
        dec     ecx
        jnz     load1_objup0
;
;Get programs memory block.
;
        mov     ecx,ebp
        sys     GetMemLinear32  ;Get memory.
        jc      load1_mem_error         ;Not enough memory.
        mov     d[load1_ProgMem],esi
        mov     d[load1_ProgMem+4],ecx
;
;Run through objects setting up load addresses.
;
        mov     edx,d[load1_ProgMem]    ;reset load offset.
        mov     ecx,d[LE_Header.LE_ObjNum+LEHeader]     ;number of objects.
        mov     esi,d[load1_ObjMem]
load1_objup1:   mov     es:LE_OBJ.LE_OBJ_Base[esi],edx  ;set load address.
        add     edx,es:LE_OBJ.LE_OBJ_Size[esi]  ;update with object length.
        add     esi,size LE_OBJ
        dec     ecx
        jnz     load1_objup1
;
;Get selectors.
;
        mov     ecx,d[LE_Header.LE_ObjNum+LEHeader]
        sys     GetSels
        jc      load1_mem_error
        mov     w[load1_Segs],bx                ;store base selector.
        mov     w[load1_Segs+2],cx      ;store number of selectors.
;
;Update programs memory and selector details in PSP and variables.
;
        push    es
        mov     es,w[load1_PSP]
        mov     ax,w[load1_Segs]                ;get base selector.
        mov     WORD PTR es:[EPSP_Struc.EPSP_SegBase],ax
        mov     ax,w[load1_Segs+2]      ;get number of selectors.
        shl     ax,3
        mov     WORD PTR es:[EPSP_Struc.EPSP_SegSize],ax
        mov     eax,d[load1_ProgMem]    ;get memory address.
        mov     DWORD PTR es:[EPSP_Struc.EPSP_MemBase],eax
        mov     DWORD PTR es:[EPSP_Struc.EPSP_NearBase],eax
        mov     eax,d[load1_ProgMem+4]  ;get memory size.
        mov     DWORD PTR es:[EPSP_Struc.EPSP_MemSize],eax
        pop     es
;
;Fetch entry table and update EXPORT table values.
;
        push    es
        mov     es,w[load1_PSP]
        cmp     DWORD PTR es:[EPSP_Struc.EPSP_Exports],0        ;any exports?
        pop     es
        jz      load1_NoEntries
        push    es
        mov     es,w[load1_PSP]
        mov     eax,DWORD PTR es:[EPSP_Struc.EPSP_Exports]
        pop     es
        cmp     DWORD PTR es:[eax],0            ;just a module name?
        jz      load1_NoEntries
        ;
        ;Move file pointer to start of entry table.
        ;
        mov     ecx,d[LE_Header.LE_EntryTable+LEHeader]
        add     ecx,d[load1_LEOffset]
        mov     bx,w[load1_Handle]
        mov     dx,cx
        shr     ecx,16
        mov     ax,4200h
        int     21h
        ;
        ;Work out how much work space we need.
        ;
        mov     ecx,d[LE_Header.LE_EntryTable+LEHeader]

;       cmp     d[LE_Header.LE_Directives+LEHeader],0
TempAddress     =       LE_Header.LE_Directives
TempAddress     =       TempAddress+LEHeader
        cmp     DWORD PTR [TempAddress],0

        jz      load1_ge4
        sub     ecx,d[LE_Header.LE_Directives+LEHeader]
        jmp     load1_ge5
load1_ge4:      sub     ecx,d[LE_Header.LE_Fixups+LEHeader]
load1_ge5:      neg     ecx
        sys     GetMemLinear32  ;get entry table memory.
        jc      load1_mem_error
        mov     edx,esi
        push    ds
        push    es
        pop     ds
        call    ReadFile                ;read the entry table.
        pop     ds
        jc      load1_file_error
        cmp     eax,ecx
        jnz     load1_file_error
        ;
        ;Work through all EXPORT's setting values.
        ;
        push    es
        mov     es,w[load1_PSP]
        mov     esi,DWORD PTR es:[EPSP_Struc.EPSP_Exports]
        pop     es

⌨️ 快捷键说明

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