loadle.asm
来自「开放源码的编译器open watcom 1.6.0版的源代码」· 汇编 代码 · 共 2,407 行 · 第 1/3 页
ASM
2,407 行
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;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
pushm ds,es,fs,gs
assume ds:nothing
mov ds,cs:apiDDSeg
assume ds:_apiCode
;
pushm d[@@Name],w[@@Name+4],d[@@Flags],d[@@Command],w[@@command+4]
pushm w[@@Environment],w[@@Handle],w[@@PSP],d[@@ProgMem],d[@@ProgMem+4]
pushm d[@@Segs],d[@@ObjMem],d[@@FixupMem],d[@@ObjCount]
pushm d[@@ObjBase],d[@@PageCount],d[@@PageCount+4]
pushm d[@@EntryEIP],w[@@EntryCS],d[@@EntryESP],w[@@EntrySS]
pushm w[@@EntryDS],w[@@EntryES],d[@@ModLink],d[@@ModLink+4],d[@@LEOffset]
IFDEF LXWORK
push WORD PTR [@@LXFlag] ; MED
ENDIF
;
mov d[@@Name],edx
mov w[@@Name+4],ax
mov d[@@Flags],ebx
mov d[@@Command],esi
mov w[@@Command+4],es
mov w[@@Environment],cx
;
xor eax,eax
mov w[@@Handle],ax
mov w[@@PSP],ax
mov d[@@ProgMem],eax
mov d[@@Segs],eax
mov d[@@ObjMem],eax
mov d[@@FixupMem],eax
mov d[@@ModLink],eax
mov d[@@ModLink+4],eax
IFDEF LXWORK
mov WORD PTR [@@LXFlag],ax ; MED
ENDIF
;
;Try and open the file.
;
push ds
lds edx,f[@@Name]
mov ax,3d00h ;open, read only.
int 21h
pop ds
jc @@no_file_error
mov w[@@Handle],ax ;store the handle.
;
;Check it's an MZ file.
;
mov bx,w[@@Handle]
mov edx,offset LEHeader ;somewhere to put the info.
mov ecx,2
mov ah,3fh
int 21h
jc @@file_error
cmp ax,cx
jnz @@file_error
cmp w[LEHeader],'ZM'
jnz @@file_error
;
;Look for an LE offset.
;
mov bx,w[@@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 @@file_error
cmp ax,cx
jnz @@file_error
cmp d[LEHeader],0 ;any offset?
jz @@file_error
mov eax,d[LEHeader]
mov d[@@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 @@file_error
cmp ax,cx
jnz @@file_error
;
;Check it really is an LE file.
;
cmp w[LEHeader],"EL"
; jnz @@file_error
jz medclose
; add check for LX file, MED 12/18/95
IFDEF LXWORK
mov cs:[0],al
cmp w[LEHeader],"XL"
jnz @@file_error
mov cs:[0],al
ENDIF
jmp @@file_error
;
;Close the file again.
;
medclose:
mov bx,w[@@Handle]
mov ah,3eh
int 21h
mov w[@@Handle],0
;
;Create a new PSP.
;
push ds
mov ebx,d[@@Flags]
mov cx,w[@@Environment]
les esi,f[@@command]
lds edx,f[@@name]
call CreatePSP
pop ds
mov w[@@PSP],bx
jc @@mem_error
;
;Open the input file again.
;
push ds
lds edx,f[@@Name]
mov ax,3d00h ;open, read only.
int 21h
pop ds
jc @@file_error
mov w[@@Handle],ax ;store the handle.
;
;Process any EXPORT entries that need pulling in.
;
cmp d[LE_ResidentNames+LEHeader],0
jz @@NoExports
IFDEF DEBUG4
jmp @@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_ResidentNames+LEHeader]
add ecx,d[@@LEOffset]
mov dx,cx
shr ecx,16
mov bx,w[@@Handle]
mov ax,4200h
int 21h
;
;Sit in a loop reading names.
;
xor ebp,ebp ;reset entry count.
mov edi,4 ;reset bytes required.
@@ge0: mov edx,offset LETemp
mov ecx,1
mov ah,3fh
int 21h
jc @@file_error
cmp ax,1
jnz @@file_error
xor eax,eax
mov al,[edx]
and al,127
jz @@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 @@file_error
cmp ax,cx
jnz @@file_error
jmp @@ge0 ;fetch all names.
;
;Allocate EXPORT table memory.
;
@@ge1: mov ecx,edi
sys GetMemLinear32
jc @@mem_error
mov es:d[esi],0 ;reset count.
push es
mov es,w[@@PSP]
mov es:d[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.
;
pushm ecx,edx
mov ecx,d[LE_ResidentNames+LEHeader]
add ecx,d[@@LEOffset]
mov dx,cx
shr ecx,16
mov ax,4200h
int 21h
popm ecx,edx
;
;Read all the names again.
;
@@ge2: or ebp,ebp ;done all names?
jz @@ge3
push edx
mov ecx,1
mov edx,offset LETemp
mov ah,3fh
int 21h ;get name string length.
pop edx
jc @@file_error
cmp ax,1
jnz @@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 @@file_error
cmp ax,cx
jnz @@file_error
inc es:d[esi] ;update EXPORT count.
mov es:[edx],edi ;set this entries address.
add edx,4
mov es:d[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 @@ge2
@@ge3: dec es:d[esi] ;lose module name from the count.
;
;Get object definition memory.
;
@@NoExports: mov eax,size LE_OBJ ;length of an object entry.
mul d[LE_ObjNum+LEHeader] ;number of objects.
mov ecx,eax
sys GetMemLinear32 ;Get memory.
jc @@mem_error ;Not enough memory.
mov d[@@ObjMem],esi
;
;Read object definitions.
;
push ecx
mov bx,w[@@Handle]
mov ecx,d[LE_ObjOffset+LEHeader] ;Get object table offset.
add ecx,d[@@LEOffset]
mov dx,cx
shr ecx,16
mov ax,4200h
int 21h
pop ecx
mov edx,d[@@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 @@file_error
cmp ax,cx
jnz @@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_ObjNum+LEHeader] ;number of objects.
mov esi,d[@@ObjMem]
xor ebp,ebp ;clear memory requirement.
@@objup0: mov eax,es:LE_OBJ_Size[esi]
add eax,4095
and eax,not 4095 ;page align objects
mov es:LE_OBJ_Size[esi],eax
add ebp,eax ;update program memory length.
add esi,size LE_OBJ
dec ecx
jnz @@objup0
;
;Get programs memory block.
;
mov ecx,ebp
sys GetMemLinear32 ;Get memory.
jc @@mem_error ;Not enough memory.
mov d[@@ProgMem],esi
mov d[@@ProgMem+4],ecx
;
;Run through objects setting up load addresses.
;
mov edx,d[@@ProgMem] ;reset load offset.
mov ecx,d[LE_ObjNum+LEHeader] ;number of objects.
mov esi,d[@@ObjMem]
@@objup1: mov es:LE_OBJ_Base[esi],edx ;set load address.
add edx,es:LE_OBJ_Size[esi] ;update with object length.
add esi,size LE_OBJ
dec ecx
jnz @@objup1
;
;Get selectors.
;
mov ecx,d[LE_ObjNum+LEHeader]
sys GetSels
jc @@mem_error
mov w[@@Segs],bx ;store base selector.
mov w[@@Segs+2],cx ;store number of selectors.
;
;Update programs memory and selector details in PSP and variables.
;
push es
mov es,w[@@PSP]
mov ax,w[@@Segs] ;get base selector.
mov es:w[EPSP_SegBase],ax
mov ax,w[@@Segs+2] ;get number of selectors.
shl ax,3
mov es:w[EPSP_SegSize],ax
mov eax,d[@@ProgMem] ;get memory address.
mov es:d[EPSP_MemBase],eax
mov es:d[EPSP_NearBase],eax
mov eax,d[@@ProgMem+4] ;get memory size.
mov es:d[EPSP_MemSize],eax
pop es
;
;Fetch entry table and update EXPORT table values.
;
push es
mov es,w[@@PSP]
cmp es:d[EPSP_Exports],0 ;any exports?
pop es
jz @@NoEntries
push es
mov es,w[@@PSP]
mov eax,es:d[EPSP_Exports]
pop es
cmp es:d[eax],0 ;just a module name?
jz @@NoEntries
;
;Move file pointer to start of entry table.
;
mov ecx,d[LE_EntryTable+LEHeader]
add ecx,d[@@LEOffset]
mov bx,w[@@Handle]
mov dx,cx
shr ecx,16
mov ax,4200h
int 21h
;
;Work out how much work space we need.
;
mov ecx,d[LE_EntryTable+LEHeader]
cmp d[LE_Directives+LEHeader],0
jz @@ge4
sub ecx,d[LE_Directives+LEHeader]
jmp @@ge5
@@ge4: sub ecx,d[LE_Fixups+LEHeader]
@@ge5: neg ecx
sys GetMemLinear32 ;get entry table memory.
jc @@mem_error
mov edx,esi
push ds
push es
pop ds
call ReadFile ;read the entry table.
pop ds
jc @@file_error
cmp eax,ecx
jnz @@file_error
;
;Work through all EXPORT's setting values.
;
push es
mov es,w[@@PSP]
mov esi,es:d[EPSP_Exports]
pop es
mov ecx,es:[esi] ;get number of entries.
add es:d[esi+4],4+2 ;correct module name pointer.
add esi,4+4
@@exp0: pushm ecx,esi,edx
mov esi,es:[esi] ;point to this entry.
xor ebp,ebp
xchg bp,es:w[esi+4] ;get & clear ordinal.
dec ebp
@@exp1: mov bh,es:[edx] ;get bundle count.
or bh,bh
jz @@bad_entry
mov bl,es:[edx+1] ;get bundle type.
add edx,2
mov edi,edx ;point to object number incase we need it.
xor eax,eax
mov al,0
cmp bl,0
jz @@exp2
add edx,2 ;skip object number.
mov al,3
cmp bl,1
jz @@exp2
mov al,5
cmp bl,2
jz @@exp2
mov al,5
cmp bl,3
jz @@exp2
mov al,7
cmp bl,4
jz @@exp2
jmp @@bad_entry
@@exp2: ;
@@exp3: or bh,bh
jz @@exp1 ;end of this bundle.
or ebp,ebp ;our ordinal?
jz @@exp4
add edx,eax ;next entry.
dec ebp
dec bh
jmp @@exp3
;
@@exp4: or bl,bl
jz @@bad_entry
dec bl
jz @@exp_16bit
dec bl
IFDEF DEBUG4
jz @@bad_fixup1
ENDIF
jz @@bad_fixup
dec bl
jz @@exp_32bit
dec bl
jz @@bad_entry
jmp @@bad_entry
;
@@bad_entry: popm ecx,esi,edx
IFDEF DEBUG4
push eax
push ebx
push ecx
push edx
push ds
push cs
pop ds
cmp bl,4
jae debugf2ae10
mov edx,OFFSET debugf2textl10
jmp debugf2loop2
debugf2ae10:
mov edx,OFFSET debugf2textae10
debugf2loop2:
cmp BYTE PTR ds:[edx],0
je debugf2b
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugf2loop2
debugf2b:
mov edx,OFFSET debugf2textcrlf
push cs
pop ds
mov ecx,2
mov bx,1
mov ah,40h
int 21h
pop ds
pop edx
pop ecx
pop ebx
pop eax
jmp debugf2out
debugf2textl10 DB '<10',0
debugf2textae10 DB '>=10',0
debugf2textcrlf DB 13,10
debugf2out:
jmp @@bad_fixup2
ENDIF
jmp @@bad_fixup
;
@@exp_16bit: movzx eax,es:w[edi] ;get the object number.
dec eax
shl ax,3
add ax,w[@@Segs]
mov es:[esi+4],ax
movzx eax,es:w[edx+1] ;get the offset.
mov es:[esi],eax
jmp @@exp8
;
@@exp_32bit: movzx eax,es:w[edi]
dec eax
push eax
shl eax,2
mov ebx,eax
add ebx,ebx
shl eax,2
add ebx,eax
add ebx,d[@@ObjMem]
mov ebx,es:LE_OBJ_Base[ebx]
pop eax
shl ax,3
add ax,w[@@Segs]
mov es:[esi+4],ax
mov eax,es:[edx+1]
add eax,ebx
mov es:[esi],eax
jmp @@exp8
;
@@exp8: popm ecx,esi,edx
add esi,4
dec ecx
jnz @@exp0
;
mov esi,edx
sys RelMemLinear32
;
;Read program objects.
;
@@NoEntries: mov ebp,d[LE_ObjNum+LEHeader] ;number of objects.
mov esi,d[@@ObjMem]
@@load0: mov eax,es:LE_OBJ_Flags[esi] ;get objects flags.
and eax,LE_OBJ_Flags_FillMsk ;isolate fill type.
cmp eax,LE_OBJ_Flags_Zero ;zero filled?
jnz @@load1
;
;Zero this objects memory.
;
mov ecx,es:LE_OBJ_Size[esi] ;get objects virtual length.
mov edi,es:LE_OBJ_Base[esi]
xor eax,eax
push ecx
and ecx,3
rep stosb
pop ecx
shr ecx,2
rep stosd
;
@@load1: ;Set file offset for data.
;
mov eax,es:LE_OBJ_PageIndex[esi] ;get first page index.
dec eax
mul d[LE_PageSize+LEHeader] ;* page size.
add eax,d[LE_Data+LEHeader] ;data offset.
mov dx,ax
shr eax,16
mov cx,ax
mov ax,4200h
mov bx,w[@@Handle]
int 21h ;set the file pointer.
;
;Work out how much data we're going to load.
;
mov eax,es:LE_OBJ_PageNum[esi] ;get number of pages.
mov ebx,eax
mul d[LE_PageSize+LEHeader] ;* page size.
mov edx,es:LE_OBJ_Base[esi] ;get load address.
xor ecx,ecx
or eax,eax
jz @@loadz
mov ecx,es:LE_OBJ_Size[esi]
add ebx,es:LE_OBJ_PageIndex[esi] ;get base page again.
dec ebx
cmp ebx,d[LE_Pages+LEHeader] ;we getting the last page?
jnz @@load2
mov ebx,d[LE_PageSize+LEHeader]
sub ebx,d[LE_LastBytes+LEHeader]
sub eax,ebx
@@load2: cmp ecx,eax
jc @@load3
mov ecx,eax
;
@@load3: ;Load the data.
;
mov bx,w[@@Handle]
push ds
push es
pop ds
call ReadFile
pop ds
jc @@file_error
cmp eax,ecx
jnz @@file_error
;
;@@loadz:
;Zero any memory we didn't just load to for Watcom's BSS benefit.
;
cmp ecx,es:LE_OBJ_Size[esi]
jnc @@load4
push edi
mov edi,edx
add edi,ecx
sub ecx,es:LE_OBJ_Size[esi]
neg ecx
xor eax,eax
push ecx
shr ecx,2
or ecx,ecx
jz @@load6
@@load5: mov es:[edi],eax
add edi,4
dec ecx
jnz @@load5
@@load6: pop ecx
and ecx,3
rep stosb
pop edi
;
@@load4: ;Next object.
@@loadz:
;
add esi,size LE_OBJ
dec ebp
jnz @@load0
;
;Get fixup table memory & load fixups.
;
mov ecx,d[LE_FixupSize+LEHeader]
sys GetMemLinear32 ;Get memory.
jc @@mem_error ;Not enough memory.
mov d[@@FixupMem],esi
push ecx
mov ecx,d[LE_Fixups+LEHeader]
add ecx,d[@@LEOffset]
mov dx,cx
shr ecx,16
mov bx,w[@@Handle]
mov ax,4200h
int 21h ;move to fixup data.
pop ecx
mov edx,esi
push ds
mov ds,apiDSeg
assume ds:_cwMain
mov ds,RealSegment
assume ds:_apiCode
call ReadFile
pop ds
jc @@file_error
cmp eax,ecx
jnz @@file_error
;
;Get IMPORT module name links.
;
mov ecx,d[LE_ImportModNum+LEHeader]
or ecx,ecx
jz @@GotImpMods
shl ecx,2
add ecx,4
sys GetMemLinear32
jc @@mem_error
mov es:d[esi],0 ;clear entry count for now.
push es
mov es,w[@@PSP]
mov es:d[EPSP_Imports],esi
pop es
mov d[@@ModLink],esi
;
;Work out offset in fixup data.
;
mov esi,d[LE_ImportModNames+LEHeader]
sub esi,d[LE_Fixups+LEHeader]
add esi,d[@@FixupMem]
;
;Work through each name getting the module link address.
;
@@NextModLnk: cmp d[LE_ImportModNum+LEHeader],0
jz @@GotImpMods
;
;Preserve current header state.
;
push esi
mov ecx,size LE_Header
sys GetMemLinear32
mov ebp,esi
pop esi
jc @@mem_error
mov edi,ebp
push esi
mov esi,offset LEHeader
rep movsb
pop esi
;
;Search for this name.
;
IFDEF DEBUG2
push eax
push ebx
push ecx
push edx
push esi
push ds
push cs
pop ds
mov edx,OFFSET debugabtext1
debugabloop2:
cmp BYTE PTR ds:[edx],0
je debugabb
mov ecx,1
mov bx,1
mov ah,40h
int 21h
inc edx
jmp debugabloop2
debugabb:
push es
pop ds
movzx ecx,BYTE PTR ds:[esi]
inc esi
;debugabloop1:
; cmp BYTE PTR ds:[esi],' '
; jbe debugaba
mov edx,esi
; mov ecx,1
mov bx,1
mov ah,40h
int 21h
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?