Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 29203
Скачиваний: 1689
Часть III. Файловая оболочка, вирус, резидент
284
;ассемблирования программы)
C_O dw offset Comm_line
...
Теперь еще раз остановимся на структуре командной строки, адрес которой
у нас будет загружен в переменную
Comm_line
:
первый байт содержит длину строки (включая символ
0Dh
);
остальные байты — саму строку;
последний байт — обязательно содержит
0Dh
.
Первый и второй адрес блоков FCB
Блоки FCB, как правило, уже давно не используются, поэтому не будем их во-
обще касаться в данной книге. В эти переменные просто занесем нули, тем самым
сообщив ОС, что FCB задействовано не будет.
29.1.4
. Сохранение регистров
Сохранение регистров процессора показано в листинге 29.5 и на рис. 29.4.
Листинг 29.5. Сохраняем регистры
...
(1) pusha
(2) push ds
(3) push es
(4) mov ss_Seg,ss
(5) mov sp_Seg,sp
...
Рис. 29.4. Сохранение регистров процессора
Глава 29. Загрузка и запуск программ
285
Заносить в стек или сохранять иным образом такие регистры, как
ax
,
bx
,
cx
,
dx
,
si
,
di
и т. п., не обязательно, если вы, конечно, не оставляете в них информацию
перед запуском программы, которая понадобится после завершения порожденного
процесса. Однако в нашем примере мы это делаем для наглядности и полноты
(строка (1)).
Сегментные регистры
ds
и
es
сохранять не обязательно, если они перед запус-
ком новой программы были равны
cs
. В этом случае мы можем после завершения
порожденного процесса выполнить следующие действия (листинг 29.6).
Листинг 29.6. Восстановление сегментных регистров после завершения
порожденного процесса
...
push cs
push cs
pop ds
pop es
...
Тем не менее, для полноты картины мы сохраним эти регистры (строки (2), (3)
листинга 29.5).
Затем идут регистры указателя стека
ss:sp
. Сохранить в стеке мы их не можем,
и это понятно почему. Для такой цели выделяем две переменные, в которые их
и занесем:
ss_Seg
,
sp_Seg
. Иного способа не существует...
29.1.5
. Запуск программы
Теперь можно перейти к запуску программы (листинг 29.7, рис. 29.5).
Листинг 29.7. Запуск программы
...
(1) mov ah,4Bh
(2) mov dx,offset File
(3) mov al,0
(4) int 21h
...
Итак, мы подошли вплотную к вызову функции
4Bh
(1). В регистр
dx
заносим
смещение строки с именем файла (2), который следует загрузить и выполнить.
Подфункция
0
функции
4Bh
прерывания
21h
— загрузка и запуск программы (3).
Это значит, что программа будет загружена в память и запущена.
Существуют также подфункция
1
, которая только загружает программу, но не
передает ей управление, и подфункция
3
, загружающая оверлей. Подфункции
1
и
3
Часть III. Файловая оболочка, вирус, резидент
286
используются редко, и мы их пока рассматривать не будем. Наша цель — заставить
программу загрузиться и выполниться.
После выполнения строки (4) начнется загрузка программы. Следующая за ней
строка получит управление только тогда, когда завершит работу загруженная про-
грамма.
Рис. 29.5. Запуск программы test.com
29.2. "Восстановительные работы"
После того как запущенная программа отработала, необходимо произвести
"восстановительные работы". Первое, что мы должны сделать, — восстановить ре-
гистры стека. Запущенный процесс вполне мог поменять эти регистры, а без стека
мы не сможем работать дальше (листинг 29.8).
Листинг 29.8. Восстановление регистров стека
...
mov ss,cs:ss_Seg
mov sp,cs:sp_Seg
...
Обратите внимание: т. к. мы не уверены, что отработанная программа не поме-
няла регистры
ds
, то обращаемся к переменным
ss_Seg
и
sp_Seg
, используя ре-
гистр
cs
, который, как мы уже знаем, всегда равен тому сегменту, в котором вы-
полняется текущая команда.
Мы сохраняли в стеке не только сегментные, но и все остальные регистры, ко-
торые помещает в стек инструкция
pusha
. Следовательно, нам нужно восстановить
их, дабы не нарушить работу стека (листинг 29.9, рис. 29.6).
Глава 29. Загрузка и запуск программ
287
Листинг 29.9. Восстановление иных сохраненных регистров
...
pop es
pop ds
popa
...
Рис. 29.6. Восстановление регистров
Вот и все! Можно, конечно, еще и память "вернуть на место", но это не столь
принципиально в данном случае.
Дополнительную информацию вы, как всегда, найдете в файлах-приложениях.
Внимательно ознакомьтесь с тремя прилагаемыми файлами. Это позволит вам
лучше понять принцип запуска программ на ассемблере!
Глава 30
Работа с расширенной памятью
30.1. Расширенная (XMS) память.
Общие принципы
В этой главе рассмотрим работу с XMS-памятью. А именно:
определим объем доступной XMS-памяти (XMSmem.asm);
cкопируем файл autoexec.bat в XMS-память, а затем выведем его содержимое на
экран из расширенной памяти (XMSblock.asm);
научимся копировать файлы, используя XMS-память (XMScopy.asm).
В приложении вы найдете 3 файла, каждый из которых выполняет свою отдель-
ную функцию. Как обычно, будем изучать от простого к сложному (XMSmem,
XMSblock, XMScopy).
Прежде чем приступать к рассмотрению материала, обращаем ваше внимание
на следующее:
для получения доступа к XMS-памяти необходимо загрузить драйвер himem.sys
либо подобный ему, который откроет линию A20, а также загрузит процедуры
для работы с расширенной памятью, входящие в состав ядра операционной сис-
темы;
для использования расширенной (XMS) памяти в DOS необходимо прибегать к
помощи прерываний и процедур. Иного способа не существует. Пересылка дан-
ных при помощи команд
movs
не годится. Также невозможно загружать данные
непосредственно в расширенную память;
работа с XMS-памятью — задача не такая простая, как может показаться на
первый взгляд. Более того, отладчики типа AFD, CodeView, Turbo Debugger
и т. п. не позволяют просматривать содержимое расширенной памяти. Это озна-
чает, что при возникновении каких-либо ошибок в программе программисту
придется самому исследовать код и искать ошибку, что, безусловно, усложняет
процесс отладки.
Однако подобных трудностей не возникает у программ, которые написаны спе-
циально для Windows. В этой операционной системе используется совсем другой
принцип обращения к расширенной памяти, подобный принципу обращения к ос-
новной памяти в MS-DOS.