Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf
Добавлен: 16.02.2019
Просмотров: 29262
Скачиваний: 1690
Часть III. Файловая оболочка, вирус, резидент
274
Все просто! Более того, обратите внимание, что и перемещаться по каталогу
в памяти достаточно удобно. Хотим получить имя пятого файла в цепочке? Произ-
водим нехитрые вычисления: 5 2 = 10. Умножаем на 2 потому, что смещение за-
нимает 2 байта. Таким образом, получаем смещение пятого файла в сегменте
Seg_files
. Остается только вывести его на экран.
Реально наша оболочка заносит не только имя файла + ASCII 0, но и его статус
(текущий, отмеченный) и размер. Сюда же можно добавить еще атрибуты и дату
создания/изменения файла.
Вот, собственно, и весь алгоритм. Теоретически все просто, но на практике мо-
гут возникнуть некоторые трудности. Безусловно, мы понимаем, что чем больше
программа, тем сложнее в ней разобраться. Помните: за терпение, упорство и же-
лание изучить ассемблер вам воздастся полностью.
28.3. Новые переменные в оболочке
Рассмотрим еще несколько новых переменных, которые задействованы в обо-
лочке:
Current_file
Start_file
Out_fstat
Первая переменная
Current_file
хранит в себе смещение текущего файла, т. е.
файла, на котором установлен курсор. Так удобней и быстрее будет искать теку-
щий файл.
Вторая переменная
Start_file
содержит смещение файла, с которого следует
выводить файлы на экран. Наша оболочка может отображать на экране 21 файл.
Если же в каталоге больше файлов, то, дойдя до нижнего или верхнего файла на
экране, необходимо "прокрутить" список файлов. Верхний/нижний файл на экране
убирается, а на его месте появляется следующий/предыдущий. Переменная
Start_file
как раз и будет хранить смещение файла, с которого нужно выводить
на экран все последующие файлы.
Обратите внимание, что под словом "прокрутка" понимается не так называемый
скроллинг, а запись файлов поверх себя. Дело в том, что скроллинг осуществляется
с помощью прерывания
10h
, что существенно тормозит работу. Мы будем пользо-
ваться нашим способом, который не требует вызова прерывания. Назовем этот спо-
соб "псевдоскроллинг".
Третья переменная
Out_fstat
хранит состояние вывода одного файла, а именно
данные о том, чистить ли строку перед выводом или нет. Зачем чистить строку пе-
ред выводом файла? Предположим, что список файлов прокручивается на экране.
Названия файлов будут размещаться на экране так, как показано в табл. 28.2.
Таблица 28.2. Размещение файлов на экране
M
A
I
N
.
A
S
M
O
T
H
E
R
.
A
S
M
Глава 28. Алгоритм считывания имен файлов в память
275
Таким образом, после прокрутки списка файлов вниз, название файла main.asm
"ляжет" поверх названия other.asm, а на экране мы увидим буквально следующее:
main.asmm
От названия файла, которое располагалось на этом месте до прокрутки, останет-
ся символ "m". Чтобы избежать этого, мы перед выводом очередного файла чистим
(забиваем пробелами) строку на экране.
Переменная
Out_fstat
сообщает процедуре о том, следует ли чистить строку
перед тем, как вывести очередной файл или нет. Почему в одних случаях мы будем
чистить строку на экране, а в других — нет?
Если чистить строку каждый раз, то создастся эффект мерцания файлов на экра-
не, что не очень удобно для просмотра, особенно на медленных компьютерах.
Иными словами, весь экран будет забиваться пробелами, а затем все текущие фай-
лы будут выводиться заново. Безусловно, это происходит практически мгновенно,
однако в некоторых случаях "мерцание" экрана может быть заметно.
Например, пользователь нажимает клавишу <Insert> на названии верхнего фай-
ла, что приводит к отметке файла, т. е. на экране название будет выделено светло-
желтым цветом (рис. 28.4).
Рис. 28.4. Выделение файла
Делается это следующим образом. У нас существует процедура вывода файлов
(
Out_files
, files.asm), которая выводит список файлов, начиная с позиции
Start_file
и до конца (либо всего 21 файл). Как уже отмечалось, в буфер заносит-
ся не только имя найденного файла, но и его статус, а все файлы изначально имеют
нулевой статус, т. е. не являются ни отмеченными, ни текущими. После перечиты-
вания каталога мы автоматически делаем первый файл текущим (статус 1). Теку-
щий файл — тот, на названии которого стоит курсор.
Допустим, пользователь нажал клавишу <Insert>. Статус текущего файла меня-
ется на 2, файл становится отмеченным. Первый байт в буфере для файла (его ста-
Часть III. Файловая оболочка, вирус, резидент
276
тус) отмечается как 2. Следующему файлу присваиваем статус 1 (текущий) и вызы-
ваем процедуру
Out_files
. Процедура
Out_files
проверяет статус первого файла.
Если это 1, то файл выводится с обычными атрибутами (как будто на него указыва-
ет курсор), если 2 — как отмеченный (светло-желтым цветом), если статус иной, то
файл выводится и как отмеченный, и как текущий. И так с каждым файлом.
Таким образом, присвоив нужный статус тому или иному файлу, мы вызываем
процедуру
Out_files
, которая обновит файлы на экране.
Если не было "прокрутки" файлов, то мы вызываем
Out_files
, при этом заносим
в переменную
Out_fstat
число 0, указывая процедуре
Out_files
на то, что чистить
строки не надо, т. к. все символы будут ложиться поверх уже существующих, только
в некоторых случаях с разными атрибутами: отмеченный, обычный и т. п.
Если же произошла прокрутка файлов, то вызываем процедуру
Out_files
, при
этом заносим в
Out_fstat
число 1, указывая процедуре чистить строку перед выво-
дом каждого файла.
28.4. Обработка клавиш <PageUp>
и <PageDown>
При нажатии одной из этих клавиш программа имитирует нажатие клавиши < >
или < > столько раз, сколько файлов отображено на экране.
28.5. Обработка клавиш <Home> и <End>
Процедуры
Up_pressed
и
Down_pressed
(нажатие клавиш < > и < >) устанавли-
вают флаг переноса, если достигнуты конец или начало списка файлов. Работа же
самих процедур показана в листинге 28.3.
Листинг 28.3. Процедуры обработки клавиш <Home> и <End>
...
; === Клавиша Home ASCII 49h ===
(01) K_Home proc
;Выводить будем до тех пор, пока процедура Up_pressed не вернет
;установленный флаг переноса (Carry Flag)
(02) Next_khome:
(03) call Up_pressed
(04) jnc Next_khome
(05) ret
(06) K_Home endp
; === Клавиша End ASCII 49h ===
(07) K_end proc
(08) Next_kend:
Глава 28. Алгоритм считывания имен файлов в память
277
(09) call Down_pressed
(10) jnc Next_kend
(11) ret
(12) K_End endp
...
Таким образом, нажатие на клавишу <Home> или <End> — не что иное, как
имитация нажатия клавиш < > или < > до тех пор, пока процедуры не достигнут
начала или конца списка файлов. При достижении первого или последнего файла
устанавливается флаг переноса, который сигнализирует о том, что больше файлов
нет. Именно поэтому мы и вызываем процедуру нажатия клавиш < > или < > до
тех пор, пока не будет установлен флаг переноса.
Глава 29
Загрузка и запуск программ
Данная глава полностью посвящена функции
4Bh
прерывания
21h
. Эта функция
выполняет загрузку и запуск программ. Запустить программу на ассемблере — за-
дача не такая простая, как может показаться с первого взгляда, и нередко по дан-
ной теме возникает много вопросов. Поэтому рассмотрим запуск программ под-
робно.
Обратите внимание, что в приложении находятся три небольших файла: 4bh-
1.asm, 4bh-2.asm и test.asm. Но не спешите их сразу ассемблировать и запускать!
Желательно прочитать эту главу до конца.
29.1. Подготовка к запуску программы
и ее загрузка
Прежде чем запустить программу, необходимо тщательно подготовиться, а именно:
1. Выделить память для загружаемой программы.
2. "Ужать" стек, если это COM-файл.
3. Сохранить необходимые регистры.
4. Подготовить EPB.
5. Подготовить строку с именем файла, который будем загружать.
6. Подготовить командную строку.
7. Сохранить сегментные регистры, если необходимо.
8. Сохранить стековые регистры
ss
и
sp
в переменных.
9. Запустить программу, вызвав прерывание
21h
.
С момента вызова прерывания
21h
наша программа (родительская) находится
в памяти до тех пор, пока запущенная (порожденная) программа не отработает. Как
только последняя завершила работу, управление получает наша (родительская)
программа. Дальше необходимо сделать следующее:
1. Восстановить стековые регистры
ss
и
sp
.
2. Восстановить сохраненные в стеке регистры (сегментные и пр., если их сохра-
няли).
3. Произвести другие необходимые действия.
Вот, собственно, и все.