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 + -
显示快捷键?