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
