Листинг 3-8. Загрузка программы с помощью функции MS-DOS
4Bh (AL = 0)
----------------------------------------------------------------
;======LOAD.ASM - Этот файл вырабатывает файл типа .COM ========
; LOAD имеет возможность загрузки и выполнения другой программы.
; LOAD вызывается путем набора следующей информации:
; "LOAD <имя файла> < аргументы программы>
; Между LOAD и именем файла, а также между именем файла и аргу-
; ментами должен быть только один символ "пробел". Имя файла
; должно включать расширение.
;
NEWPROG EQU 82h ; адрес загрузки командной строки в PSP
NEWSTR EQU 81h ; адрес строки в PSP (пробел 20h)
NEWLEN EQU 80h ; адрес длины командной строки
;
INCLUDE STDMAC.INC ; включение описания макробиблиотеки
;====== ПРОГРАММНАЯ СЕКЦИЯ =====================================
;
code_seg SEGMENT
ASSUME cs:code_seg
ASSUME ds:code_seg
ORG 0
SEG_ORG EQU $
main PROC FAR
start:
mov sp,offset TOP_STK ; установка вершины стека
;
; Грамматический разбор командной строки для поиска конца или
; пробела. Преобразование имени программы в строку ASCIIZ.
;
mov bx,0 ; очистка BX
mov bl,NEWLEN[bx] ; получение длины ком.строки
or bl,bl ; проверка длины строки
jnz cmd_ok
@DisStr bad_cmd ; ошибка в командной строке
jmp exit
cmd_ok:
dec bx ; вычитание 1 для пробелов
mov cx,bx ; копирование длины в счетчик
mov di,NEWPROG ; поиск адреса (1-й не пробел)
mov al,' ' ; поиск значения (пробел)
repne scasb ; поиск расширения файла
pushf ; сохранение результата поиска
sub bx,cx ; получение оставшегося счетчи-
popf ; ка и результатов поиска
jz set_zb ; нулевой флажок => параметры
; (найден пробел)
inc bx ; ненулевой флажок подразуме-
; вает конец строки
set_zb: ; преобразование командной
; строки в ASCIIZ
mov byte ptr NEWSTR[bx],0
mov cmd_buf,cl ; установка длины строки пара-
; метра
cmp cl,0 ; достигнут конец строки?
jle free_mem ; нет параметров команды
;
; Прием остатка строки и передача его в текстовый буфер команд-
; ной строки для вызываемой программы
;
inc cl ; передача CR
mov si,di ; передача исходного индекса
mov di,offset cmd_txt ; или установка индекса назна-
; чения
rep movsb ; передача остатка строки
add cmd_buf,1 ; увеличение количества проб.
;
; Освобождение системной памяти для загрузчика и вызываемой
; программы. Сокращение блока распределения до необходимого
; минимума.
;
free_mem:
mov bx,(offset LST_BYT - SEG_ORG + 15) shr 4
mov ah,04Ah ; ES содержит адрес PSP
@DosCall ; модификация распред. памяти
jnc modify_ok
push ax ; (помещение в стек при ошиб-
; ке)
@DisStr fail4A ; сообщение об ошибке или
; завершение, если сбой
jmp error
;
; Установка блока параметров и регистровых параметров для
; вызова функции загрузки или выполнения программы.
modify_ok:
mov ax,cs ; установка всех параметров
mov p1,ax ; сегментов в этот сегмент
mov p2,ax
mov p3,ax
mov dx,offset NEWPROG
mov bx,offset param_block
mov spoint,sp ; сохранение указателя стека
mov ax,4B00h ; функция загрузки или выпол-
; нения программы
@DosCall
;
; Восстановление регистров сегмента и указателя стека после
; вызова.
;
mov cx,cs ; дублирование CS во все сегм.
mov ss,cx ; сначала восстанавливается стек
mov sp,cs:spoint ; восстановление указателя стека
mov ds,cx
mov es,cx
jnc exit ; выход из программы, если все хорошо
push ax ; сохранение кода ошибки
@DisStr fail4B ; вывод ошибки, если сбой
;
; Грамматический разбор кода ошибки, возвращаемого системой
; и отображение соответствующего текста сообщения
;
error:
pop ax ; обратное получение кода ошибки
@Case ax,<+,2,7,8,9,10h,11h>,
mov dx,offset err0 ; плохой код ошибки - неравны
jmp merge
em1: mov dx,offset err1 ; неправильная функция
jmp merge
em2: mov dx,offset err2 ; файл не найден
jmp merge
em7: mov dx,offset err7 ; память засорена
jmp merge
em8: mov dx,offset err8 ; недостаточно памяти
jmp merge
em9: mov dx,offset err9 ; неправильный блок памяти
jmp merge
em10: mov dx,offset err10 ; неправильная среда
jmp merge
em11: mov dx,offset err11 ; неправильный формат файла .EXE
jmp merge
merge: mov ah,09h ; отображение строки
@DosCall
exit: mov ax,04C00h ; завершение при окончании
@DosCall
main ENDP
;
bad_cmd db 'Error in Command Line',CR,LF,'$'
; ошибка в командной строке
fail4A db 'Failed to Modify Allocated Memory Blocks'
db CR,LF,'$'
; сбой при модификации блока распределенной памяти
fail4B db 'Failed to Load Program Overlay',CR,LF,'$'
; сбой при загрузке программного оверлея
err0 db '>>> UNKNOWN ERROR CODE <<<',CR,LF,'$'
; неизвестный код ошибки
err1 db '>>> invalid function <<<',CR,LF,'$'
; неправильная функция
err2 db '>>> file not found <<<',CR,LF,'$'
; файл не найден
err7 db '>>> memory arena trashed <<<',CR,LF,'$'
; память засорена
err8 db '>>> not enough memory <<<',CR,LF,'$'
; недостаточно памяти
err9 db '>>> invalid memory block <<<',CR,LF,'$'
; неправильный блок памяти
err10 db '>>> bad environment <<<',CR,LF,'$'
; неправильная среда
err11 db '>>> bad .EXE file format <<<',CR,LF,'$'
; неправильный формат файла .EXE
;
spoint dw ? ; память для указателя стека
param_block label word
dw 0 ; используемая среда порождающей программы
dw offset cmd_buf
p1 dw ? ; сегмент командной строки
dw 5Ch ; сегмент FCB #1 или смещение
p2 dw ?
dw 6Ch ; сегмент FCB #2 или смещение
p3 dw ?
cmd_buf db ? ; длина командной строки
db ' ' ; всегда предполагается пробел
cmd_txt db 80 dup (?) ; 80 символов
;
; Описание локального стека
EVEN ; слово выравнивания стека
stack db 32 dup ('stack ') ; локальный стек
TOP_STK EQU $-2 ; установка адреса вершины стека
LST_BYT EQU $ ; последний байт в программе
;
code_seg ENDS
END start
----------------------------------------------------------------
|