CSEG    SEGMENT PARA  PUBLIC
        ASSUME  CS:CSEG, DS: CSEG, ES: CSEG, SS: CSEG
        ORG     100h

;--------------------------------------
START:
        LEA     SP,HeapStack           ; Устанавливаем вешину стека
        ADD     SP,500H                ; +500H байт от конца программы
        POP     AX                     ; Устанваливаем адрес возврата на
        XOR     AX,AX                  ; PSP.[0]
        PUSH	AX
        CALL    SetEPB                 ; Заполняем данные EPB
        MOV     AH,4AH                 ; Ужимаем текщий блок памяти
        MOV     BX,OFFSET HeapStack    ; до размеров программы+стек
        ADD     BX,500H
        MOV     CL,4
        SHR     BX,CL
        INC     BX
        INT     21H
        JC      Error                  ; Ошибка выполнения
        CALL    ReadHeader
        MOV     AH,4BH                 ; Загружаем в освобожденную память
        MOV     AL,1                   ; программу, указанную
        LEA     BX,EPB                 ; в переменной ExeProg
        LEA     DX,ExeProg
;       PUSH    DS
        INT     21H
        JC      Error
        MOV     AH,62H
        INT     21H
        ADD     BX,10H                 ; Настраиваем SS:SP на стек загруженной
        MOV     SP,WORD PTR Header.10H                                       
        MOV     AX,BX                  ; программы
        ADD     AX,WORD PTR Header.0EH
        MOV     SS,AX
        MOV     AX,BX
        ADD     AX,WORD PTR Header.16H
        PUSH    AX                     ; Устанавливаем точку входа в
        MOV     AX,WORD PTR Header.14H      ; программу
        PUSH    AX
        SUB     BX,10H
        MOV     DS,BX                  ; Настраиваем DS и ES на новый PSP
        MOV     ES,BX
        LEA     DX,Rest
        MOV     BX,0AH
        MOV     [BX],DX                ; Точку возврата на Rest
        RETF
Rest:                                  ; Восстанавливаем DS после отработки
        PUSH    CS                     ; в чужой программе
        POP     DS

        MOV     AL,00
        JMP     EXIT

Exit:
        MOV     AH,4CH
        INT     21H
;--------------------------------------
Error:                                 ; Обработчик ошибок
        MOV     AH,09H
        LEA     DX,ErrorMessage
        INT     21H
        JMP     EXIT
;--------------------------------------
SetEPB:                                ; Установка сегментов в EPB
        LEA     BX,EPB
        MOV     AX,DS
        MOV     [BX][ 4],AX
        MOV     [BX][ 8],AX
        MOV     [BX][12],AX
        MOV     [BX][16],AX
        MOV     [BX][20],AX
        RETN
;--------------------------------------
;--------------------------------------
ReadHeader:
        MOV     AX,3D02H
        LEA     DX,ExeProg
        INT     21H
        JC      Error
        MOV     Handle,AX
        XOR     AX,AX
        MOV     AH,3FH
        MOV     BX,Handle
        MOV     CX,32
        LEA     DX,Header
        INT     21H
        MOV     AH,3EH
        MOV     BX,Handle
        INT     21H
        RET
;-----------------------  Exec Parameters Block
EPB             DW      0              ; 0000 - используем текущее окружение
                DW      OFFSET CMD     ; Указатель на CMD
                DW      0              ;
                DW      OFFSET FCB1    ; Указатель на FCB1
                DW      0              ;
                DW      OFFSET FCB2    ; Указатель на FCB2
                DW      0              ;
                DW      OFFSET Rest    ; Указатель на Rest
                DW      0              ;
                DW      OFFSET Exit    ; Указатель на Exit
                DW      0              ;
CMD             DB      0,13
FCB1            DB      16 DUP (0)
FCB2            DB      16 DUP (0)
ExeProg         DB      'TEST.EXE',0
Handle          DW      0
Header          DB      32 DUP(0)      ; Первый 32-байта exe-файла



ErrorMessage    DB      'Ошибка выполнения! Стоп программы..$'
HeapStack       DW      0

CSEG    ENDS
        END   Start


