
;              4Bh-1.ASM - программа к Главе № 29

; (С) Авторские права на файлы-приложения принадлежат автору книги
; "Ассемблер? Это просто! Учимся программировать под MS-DOS"
; Автор: Калашников Олег Александрович (e-mail: Assembler@Kalashnikoff.ru)
;	 http://www.Kalashnikoff.ru

; --- Ассемблирование (получение *.com файла) ---
;При использовании MASM 6.11 - 6.13:
;ML.EXE 4bh-1.asm /AT

;При использовании TASM:
;TASM.EXE 4bh-1.asm
;TLINK.EXE 4bh-1.obj /t/x


;__________________________________________________________________________
;
;!!! ВНИМАНИЕ! Сперва прочтите Главу 29, иначе ничего не будет понятно !!!
;__________________________________________________________________________


;Программа загружает файл (File) НЕ через COMMAND.COM с командной строкой
;(Comm_line) 'abc'.

.186   ;shr bx,4 работает на 186+ процессоре!
CSEG segment
assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
org 100h

Start:
      mov bx,offset Finish
      shr bx,4
      inc bx
      mov ah,4Ah
      int 21h    ;Ужимаем размер отведенной памяти до метки Finish

;Ужимаем стек, т.к. он находится в "хвосте" сегмента, на место которого
;будет загружена программа
      mov sp,0FFh

; --- Готовим EPB ---
      mov bx,offset EPB
      mov C_F,cs ;Сегмент командной строки (смещение уже занесено! См. ниже)

; --- Сохраняем ВСЕ регистры, т.к. они будут разрушены!!! ---
      pusha
      push ds
      push es
      mov SS_Seg,ss
      mov SP_Seg,sp

; --- Запускаем программу ---
      mov ah,4Bh         ;Функция EXEC (EXECute - запус программы)
      mov dx,offset File ;Имя файла для запуска
      mov al,0           ;Загрузка и запуск
      int 21h

; --- Восстанавливаем регистры ---
      mov ss,cs:SS_Seg
      mov sp,cs:SP_Seg
      pop es
      pop ds
      popa

      mov ah,9
      jnc OK      ;Не было ошибок - сообщаем 


;ОШИБКА ПРИ ЗАПУСКЕ!
      mov dx,offset Mess_Error
      int 21h
      int 20h

;Успешная загрузка программы
OK:
      mov dx,offset Mess_OK
      int 21h
      int 20h

;Вот, что мы получим, если с помощью данной программы мы загрузим DN,
;а из DN - Volcov Commander (вырезка из VC):

; Размер   Программа      Перехватываемые прерывания
;────────────────────────────────────────────────────
; 53 776   DOS 7.10       01 02 03 04 0E <==== Системная часть DOS
;     64   system         19
;  6 928   KEYB           09 E0
;  3 824   WIN            EA F5
;  3 120   vmm32          33 67
;  1 280   DN.COM         FF             <==== Из DN загружаю 4BH-1.COM
;  7 456   COMMAND        2E             <==== Первым грузится Command.com
;    864   4BH-1.COM                    <==== Потом только 4BH-1.COM
;  1 296   dn.com         2F             <==== 4BH-1 загружает DN.COM
;  7 264   COMMAND        22             <==== Из DN загружаю VC (опять через Command.com!)
; 76 096   VC.COM         00 1B 21 23 24 <==== VC загружен!
;491 200   free memory


;ОБРАТИТЕ ВНИМАНИЕ, что 4BH-1.COM НЕ загружает COMMAND.COM, в отличие от
;DN.COM! Т.е. мы грузим программу напрямую!

;ЕЩЕ МОМЕНТ: 4BH-1.COM, естественно, НЕ перехватывает НИКАКИХ прерываний, что
;видно из приведенной выше таблицы. Это называется "пассивный полурезидент".
;Он получит управление только тогда, когда отработают ВСЕ загруженные после
;него программы! Т.е. нам нужно будет выйти из VC (COMMAND.COM автоматически
;выгружается), а затем из DN.

;Суть понятна? Уверен, что так!

;Файл, который будем загружать.
;Обязательно указывайте расширение файла, даже если это COM или EXE файл.
;Функция 4Bh загружает любые файлы с любым расширением (даже TXT).
;Вопрос только в том, будет ли текстовый файл работать. Если его размер
;не превышает 64Кб, то DOS будет считать, что загружается COM-файл, но не
;с расширением COM.
File db 'test.com',0
;File db 'c:\dn\dn.com',0

;Командная строка:
;5      - длина строки (включая 0Dh)
;' abc' - сама строка (первый символ - пробел!)
;0Dh    - признак окончания строки
Comm_line db 5,' abc',0Dh


; === Exec Parameter Block (EPB) для функции 4Bh ===
EPB:
Env dw 0   ;Сегмент среды (окружения DOS) для загружаемой программы
C_O dw offset Comm_line ;Смещение командной строки +
C_F dw 0   ;+ сегмент командной строки
    dd 0   ;FCB (не используется)
    dd 0   ;FCB (не используется)
Len dw $-EPB  ;Длина EPB


Mess_OK db 0Dh,0Ah,0Ah, 'Сообщение от 4Bh-1.com: Программа была успешно загружена и выполнена!',0Ah,0Dh,0Ah,0Ah,'$'
Mess_Error db 0Dh,0Ah,0Ah, 'Сообщение от 4Bh-1.com: Файл не найден!',0Ah,0Dh,0Ah,0Ah,'$'

; Переменные для хранения сегментных регистров
SS_Seg dw ?
SP_Seg dw ?

; Метка конца программы (урезаем память до этой метки)
Finish equ $

CSEG ends
end Start