cseg	segment para public 'code'
org	100h

; Copyright 1983 Data Base Decisions
; This program is used as a header for an EXE file to load it
; faster. It is copied onto the front of an EXE file as follows:
; copy exetocom.bin/b+prog.exe/b newprog.com, where prog.exe is your
; program. The resulting COM file must be less than 64K.

jumploc equ 0efh		; jump to psp for copy

exetocom proc far
	assume cs:cseg,ds:cseg,ss:nothing,es:nothing

	mov si,offset endprog	; end of this prog
	mov ax,[si]		; get EXE signature
	cmp ax,5a4dh		; exe file?
	jz p010 		; yes
	mov dx,offset errmsg1

p005:	mov ah,9
	int 21h
	int 20h 		; terminate

p010:
	mov ax,si
	mov cl,4
	shr ax,cl		; # of pghs in this prog
	mov bx,ds
	add ax,bx		; seg of exe header
	add ax,[si+8]		; plus header size (pghs)
	mov oseg,ax		; gives orig exe start seg

	mov ax,cs		; get new exe start seg
	add ax,10h
	mov nseg,ax

	mov ax,[si+10h] 	; check stack placement
	mov cl,4		; get stack size
	shr ax,cl		; convert to pghs
	add ax,nseg		; add base seg
	add ax,[si+0eh] 	; and sp offset
	mov bx,2
	mov bx,[bx]		; get top of memory
	cmp bx,ax		; room for the stack?
	jae p015		; yes
	mov dx,offset errmsg2
	jmp p005

p015:	mov ax,nseg
	mov bx,si
	add bx,[si+18h] 	; first relocation item
	mov cx,[si+6]		; # of items
	jcxz p030		; none

p020:	mov dx,[bx+2]		; get code seg
	add dx,oseg		; add old start seg
	mov es,dx		; in es
	mov di,[bx]		; set instruction in es
	add es:[di],ax		; add new start seg
	add bx,4		; do another
	loop p020		; done?

p030:	push si 		; pass control
	push cs
	pop es			; set es = cs
	mov di,jumploc		; copy copycode to psp
	mov si,offset copycode
	mov cx,17
	rep movsb
	pop si

	mov ax,nseg		; new prog seg
	add ax,[si+16h] 	; plus cs offset gives new cs
	push ax 		; save it
	mov ax,[si+14h] 	; new ip
	push ax 		; save it

	push ds 		; save ds & es
	push ds

	mov ax,nseg		; new prog seg
	mov es,ax		; point to new seg
	xor di,di		; offset 0

	add ax,[si+0eh] 	; plus stack seg offset
	push ax 		; save new ss
	mov ax,[si+10h] 	; set sp
	push ax 		; save it

	mov bx,[si+4]		; get exe size (pages)
	mov ax,[si+8]		; get header size (pghs)
	mov cl,5
	shr ax,cl		; convert pghs to pages
	sub bx,ax		; prog size (pages)
	mov cl,8
	shl bx,cl		; convert pages to words
	mov cx,bx		; repeat count for copy

	mov ax,oseg
	mov ds,ax		; point to old seg
	xor si,si		; offset 0

	mov bx,jumploc
	jmp bx			; jump to copycode

	copycode equ this byte
	rep movsw		; copied code
	pop ax			; for sp
	pop bx			; for ss
	pop es			; restore es
	pop ds			; restore ds
	pop cx			; for ip
	pop dx			; for cs
	cli
	mov ss,bx		; set new stack
	mov sp,ax
	sti
	push dx 		; push cs & ip
	push cx
	ret 0			; go to the exe prog

errmsg1 db 'EXE header not found',10,13,'$'
errmsg2 db 'Program too large',10,13,'$'

oseg	dw 0			; original exe prog seg
nseg	dw 0			; new prog seg

endprog equ this word		; must be on a paragraph boundary!

exetocom endp
cseg	ends
end	exetocom
