Файл: О.А.Калашников. Ассемблер Это Просто. Учимся программировать.pdf

ВУЗ: Не указан

Категория: Книга

Дисциплина: Программирование

Добавлен: 16.02.2019

Просмотров: 29244

Скачиваний: 1689

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
background image

Глава 21. Работа с блоками основной памяти 

219 

21.2. Работа с основной памятью DOS 

21.2.1. Управление памятью 

В  этом  разделе  рассмотрим  принципы  и  методы  работы  с  основной  памятью  

в режиме эмуляции MS-DOS. Основная память имеет объем до 640 Кбайт. Подроб-
но рассмотреть управление памятью в одной главе невозможно. Мы затронем лишь 
ключевые, основополагающие моменты. 

Как  только  программа  загрузилась,  DOS  автоматически  отводит  для  нее  всю 

свободную  основную  память.  Программист  может  по своему усмотрению урезать 
блоки памяти, отводить другие, а также освобождать отведенные участки (блоки) 
памяти. 

Зачем это нужно и где это можно применять? Представьте ситуацию: мы напи-

сали некоторую программу, которая, в свою очередь, должна загружать другую. Но 
так  как  вся  память  изначально  выделена  только  нашей  программе,  то мы не смо-
жем загрузить ничего более. Ведь загружаемой программе (порождаемому процес-
су) также необходимо некоторое количество памяти не только для работы, но и для 
загрузки. 

Для  того  чтобы  урезать  память,  используется  функция 

4Ah

  прерывания 

21h

 

(табл. 21.2). 

Таблица 21.2. Функция 

4Ah

 

прерывания 

21h

:  

изменить объем свободной основной памяти 

Вход 

Выход 

ah = 4Ah 

es 

= сегмент распределенного блока 

bx 

= размер блока в 16-байтовых параграфах 

jc 

— ошибка, при этом: 

ax 

= код ошибки 

 
Распределенный блок в нашем случае — вся память, отведенная программе, на-

чиная  с  нулевого  смещения  сегмента 

cs

  и  заканчивая  последним  свободным  бай-

том. Поэтому перед вызовом функции 

4Ah

 следует убедиться в том, что 

es

 указыва-

ет на сегмент, куда мы загрузились. В табл. 21.3 показано состояние памяти после 
загрузки программы в память для ее последующего выполнения. 

Таблица 21.3. Состояние памяти после загрузки программы 

Данные 

Описание 

Системные файлы 

Память занята от 0 до текущего байта 

Резидентные программы 

Память занята от 0 до текущего байта 

Наша программа 

Память занята от 0 до текущего байта 

Метка Finish 

Память занята от 0 до текущего байта 

Отведенная память нашей программе 

Память занята от 0 до конца 


background image

 

Часть III. Файловая оболочка, вирус, резидент 

220 

После  того  как  наша  программа  загрузилась  в  память,  вся  основная свободная 

память отведена только нашей программе. 

Задача: урезать занятую программой память до метки 

Finish

. Для чего это нуж-

но — рассмотрим позже. Обратите внимание, каким образом мы ужимаем сущест-
вующий блок памяти (

Prepare_memory

, main.asm) (листинг 21.10). 

Листинг 21.10. Освобождение отведенной памяти 

... 
mov bx,offset Finish    ;bx=последний байт нашей программы 
;Так как bx должен содержать не количество байтов, а количество блоков 
;по 16 байт, то мы должны сдвинуть биты вправо на 4 
shr bx,4 
inc bx          ;Увеличим bx на один (на всякий случай) 
mov ah,4Ah      ;Функция уменьшения/увеличения существующего блока памяти 
;В данном случае урезаем, т. к. наша программа, естественно, меньше 
;отведенного блока памяти после загрузки. 
int 21h 
... 

После выполнения функции 

4Ah

  состояние  основной  памяти  будет  следующим 

(табл. 21.4). 

Таблица 21.4. Состояние памяти после освобождения блока 

Данные 

Описание 

Системные файлы 

Память занята от 0 до текущего байта 

Резидентные программы 

Память занята от 0 до текущего байта 

Наша программа 

Память занята от 0 до текущего байта 

Метка Finish 

Память занята от 0 до текущего байта 

Память за меткой Finish 

Память свободна до конца 640 Кбайт, начиная  

с первого байта, следующего за меткой Finish 

 
То есть  размер  свободной  памяти  равен  640 Кбайт  минус  смещение  метки 

Finish

После освобождения памяти можно попробовать отвести отдельный блок памя-

ти  размером,  скажем,  1000h  16-байтовых  блоков  (параграфов)  или  65 536 байт 
(листинг 21.11). 

Листинг 21.11. Отведение блока памяти размером 65 536 байт 

... 
mov ah,48h 
mov bx,1000h 


background image

Глава 21. Работа с блоками основной памяти 

221 

int 21h 
... 
mov Seg_files,ax    ;Сохраним сегмент отведенного блока 
... 

В этом примере мы использовали новую функцию. Она описана в табл. 21.5. 

Таблица 21.5. Функция 

48h

 

прерывания 

21h

: выделить блок основной памяти 

Вход 

Выход 

ah = 48h 

bx 

= размер блока в 16-байтовых пара-

графах 

jc 

— ошибка, при этом: 

ax 

= код ошибки 

Иначе: ax = сегмент выделенного блока 

 

Состояние памяти после отведения блока размером 65 536 байт показано в табл. 21.6. 

Таблица 21.6. Состояние памяти после отведения блока памяти 

Данные 

Описание 

Системные файлы 

Память занята от 0 до текущего байта 

Резидентные программы 

Память занята от 0 до текущего байта 

Наша программа 

Память занята от 0 до текущего байта 

Метка Finish 

Память занята от 0 до текущего байта 

Память за меткой Finish + 65 536 байт 

Память занята 

Память, начиная с адреса Finish + 
65 537 

байт 

Свободна 

 
На рис. 21.3 показан в отладчике участок кода, который отводит память с помо-

щью функции 

4Ah

 прерывания 

21h

 

Рис. 21.3. Урезание и отведение памяти после загрузки программы 


background image

 

Часть III. Файловая оболочка, вирус, резидент 

222 

21.2.2. Считываем файлы в отведенную память 

Для каких целей мы выделяем блок памяти размером 64 Кбайт? 
В эту область памяти будет загружаться информация о найденных файлах в те-

кущем каталоге. Таким же образом поступают и все оболочки: просто считывают 
файлы в отведенный блок памяти, а затем с ними работают. 

Но, например, внутренняя команда 

DIR

 не загружает в память найденные файлы. 

Да  и  нет  смысла.  Она  нашла  файл,  тут  же  вывела  информацию  о  нем  на  экран  
и  ищет  следующий.  Выделять,  копировать  и  удалять  файлы  эта  команда,  естест-
венно, не может. 

Каким образом заносим в отведенную память найденные файлы? Алгоритм про-

стейший: 
1.  Ищем первый файл. Если файлов нет, то переходим к шагу 5. 
2.  Заносим имя файла в отведенный блок памяти. Дописываем после имени файла 

ноль. 

3.  Ищем следующий файл. Если файлов больше нет, переходим к шагу 5. 
4.  Заносим  следующий  файл  в  память  сразу  же  за  найденным  предыдущим,  про-

должаем поиск файлов (шаг 3). 

5.  Заносим  еще  один  ноль  после  последнего  найденного  файла  для  того,  чтобы 

дать  понять  процедурам  нашей  оболочки,  что  это  был  последний  найденный 
файл. 

6.  Выводим указанное количество файлов на экран (сколько находится в перемен-

ной 

Number_files

) (

Out_files

, files.asm). 

Труда  разобраться с тонкостями процедур не составит, тем более что в файле-

приложении вполне достаточно комментариев. 

 


background image

 

 

 

Глава 22 

 

Часто задаваемые вопросы 

 

 
В  процессе  изучения  нового  языка  программирования,  как  и  любого  другого 

предмета, всегда возникает множество вопросов. В этой главе мы рассмотрим наи-
более  типичные  вопросы,  которые  задают  начинающие  программисты  экспертам 
портала http://RFpro.ru

1.  Что такое дизассемблер и для чего он нужен? 

Дизассемблер —  это  программа,  которая  переводит  машинный  код  на  язык 
ассемблера.  Дизассемблер  может  применяться  при  получении  исходного  кода 
для  изучения  работы  программы  или  корректировки  его  кода  с  последующим 
ассемблированием. 
Если  в  программе  необходимо  изменить  два-три  байта  (например,  убрать 
ограничение  на  ее  работу  в  более  поздних  версиях  MS-DOS),  то  можно 
воспользоваться и специальным текстовым редактором Hacker's View, который 
и может выступать в роли дизассемблера. 

2.  Перечислите флаги процессора. Где они расположены и за что отвечают? 

 

Флаг переноса 

CF

 (Carry Flag). Содержит 1, если произошел перенос единицы 

при  сложении  или  заем  единицы  при  вычитании.  Используется  также  в  цик-
лических операциях и операциях сравнения. 

 

Флаг четности 

PF

. Содержит 1, если в результате операции получено число  

с  четным  количеством  значащих  разрядов,  т. е.  дополняет  результат  до 
нечетного числа — используется в операциях обмена для контроля данных. 

 

Флаг  внешнего  переноса 

AF

.  Контролирует  перенос  из  3-го  бита  данных. 

Полезен при операциях над упакованными десятичными цифрами. 

 

Флаг  нуля 

ZF

  (Zero  Flag).  Равен  1,  если  в  результате  операции  получен  0,  

и равен 0 — в противном случае. 

 

Флаг  знака 

SF

  (Sign  Flag).  Равен  1,  если  в  результате  операции  получено 

отрицательное  число  (с  единицей  в  старшем  разряде,  т. е.  последний  бит 
(биты нумеруются справа налево)). 

 

Флаг  трассировки 

TF

  (Trass  Flag).  Равен  1,  если  программа  выполняется  по 

шагам,  с  передачей  управления  после  каждой  выполненной  команды 
прерыванию с вектором 1.