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