Функции загрузки и выполнения программы
Рассмотрим теперь, как можно загрузить и выполнить программу из другой программы. Функция шест.4B дает возможность одной программе загрузить другую программу в память и при необходимости выполнить.
Для этой функции необходимо загрузить адрес ASCIIZ-строки в регистр DX, а адрес блока параметров в регистр BX (в действительности в регистровую пару ES:BX). В регистре AL устанавливается номер функции 0 или 3:
AL=0. Загрузка и выполнение
Данная операция устанавливает префикс программного сегмента для новой программы, а также адрес подпрограммы реакции на Cntrl/Break и адрес передачи управления на следующую команду после завершения новой программы. Так как все регистры, включая SP, изменяют свои значения, то данная операция не для новичков.
Блок параметров, адресуемый по ES:BX, имеет следующий формат:
Двухбайтовый сегментный адрес строки параметров для передачи.
Четырехбайтовый указатель на командную строку в PSP+80H.
Четырехбайтовый указатель на блок FCB в PSP+5CH.
Четырехбайтовый указатель на блок FCB в PSP+6CH.
AL=3. Оверлейная загрузка
Данная операция загружает программу или блок кодов, но не создает PSP и не начинает выполнение.
Таким образом можно создавать оверлейные программы. Блок параметров адресуется по регистровой паре ES:BX и имеет следующий формат:
Двухбайтовый адрес сегмента для загрузки файла.
Двухбайтовый фактор настройки загрузочного модуля.
Возможные коды ошибок, возвращаемые в регистре AX: 01, 02, 05, 08, 10 и 11.
Важно:
uВ основной программе, вызывающей подпрограмму, необходимо определять точку входа как EXTRN, а в подпрограмме — как PUBLIC.
uБудьте внимательны при использовании рекурсий, когда подпрограмма 1 вызывает подпрограмму 2, которая в свою очередь вызывает подпрограмму 1.
uВ случае, если кодовые сегменты необходимо скомпоновать в один сегмент, то необходимо определить их с одинаковыми именами, одинаковыми классами и атрибутом PUBLIC.
uДля простоты программирования начинайте выполнение с основной программы.
uОпределение общих данных в основной программе обычно проще (но не обязательно). Основная программа определяет общие данные как PUBLIC, а подпрограмма (или подпрограммы) — как EXTRN.
Лекция 13.
Выполнение программ
Начинаем работать
Когда рабочая часть DOS будет загружена в память, на экране появится запрос для ввода даты и времени, а затем буква текущего дисковода, обычно A для дискеты и C для винчестера (твердого диска). Изменить текущий дисковод можно, нажав соответствующую букву, двоеточие и клавишу Enter.
Это обычная процедура загрузки, которую следует использовать всякий раз.
В этом первом упражнении для просмотра содержимого ячеек памяти используется программа DOS DEBUG. Для запуска этой программы введите DEBUG и нажмите Enter, в результате программа DEBUG должна загрузится с диска в память. После окончания загрузки на экране появится приглашение в виде дефиса, что свидетельствует о готовности программы DEBUG для приема команд.
Размер памяти
Сначала проверим размер доступной для работы памяти. В зависимости от модели компьютера это значение связано с установкой внутренних переключателей и может быть меньше, чем реально существует. Данное значение находится в ячейках памяти шест.413 и 414 и его можно просмотреть из DEBUG по адресу, состоящему из двух частей: 400 — это адрес сегмента, который записывается как 40 (последний нуль подразумевается) и 13 — это смещение от начала сегмента. Таким образом, можно ввести следующий запрос:
D 40:13 (и нажать Enter).
Первые два байта, появившиеся в результате на экране, содержат размер памяти в килобайтах и в шестнадцатеричном представлении, причем байты располагаются в обратной последовательности.
Серийный номер
Серийный номер компьютера «зашит» в ROM по адресу шест. FE000. Для того, чтобы увидеть его, следует ввести:
D FE00:0 (и нажать Enter)
В результате на экране появится семизначный номер компьютера и дата копирайт.
Дата ROM BIOS
Дата ROM BIOS в формате mm/dd/yy находится по шест. адресу FFFF5. Введите
D FFFF:05 (и нажмите Enter)
Знание этой информации (даты) иногда бывает полезным для определения модели и возраста компьютера. Теперь, поскольку вы знаете, как пользоваться командой D (Display), можно устанавливать адрес любой ячейки памяти для просмотра содержимого.
Можно также пролистывать память, периодически нажимая клавишу D, — DEBUG выведет на экран адреса, следующие за последней командой.
Для окончания работы и выхода из отладчика в DOS введите команду Q (Quit). Рассмотрим теперь использование отладчика DEBUG для непосредственного ввода программ в память и трассировки их выполнения.
Машинные команды имеют различную длину: один, два или три байта. Машинные команды находятся в памяти непосредственно друг за другом. Выполнение программы начинается с первой команды и далее последовательно выполняются остальные.
Можно ввести программу непосредственно в память машины и выполнить ее покомандно. В тоже время можно просматривать cодержимое регистров после выполнения каждой команды. После загрузки DEBUG на экране высвечивается приглашение к вводу команд в виде дефиса.
Для непосредственного ввода программы на машинном языке введите следующую команду, включая пробелы:
E CS:100 B8 23 01 05 25 00 (нажмите Enter)
Команда E обозначает Enter(ввод). CS:100 определяет адрес памяти, куда будут вводиться команды, — шест.100 (256) байт от начала сегмента кодов. (Обычный стартовый адрес для машинных кодов в отладчике DEBUG).
Команда E записывает каждую пару шестнадцатеричных цифр в память в виде байта, начиная с адреса CS:100 до адреса CS:105.
Следующая команда Enter:
E CS:106 8B D8 03 D8 8B CB (Enter)
вводит шесть байтов в ячейки, начиная с адреса CS:106 и далее в 107, 108, 109, 10A и 10B. Последняя команда Enter:
E CS:10C 2B C8 2B C0 90 CB (Enter)
вводит шесть байтов, начиная с CS:10C в 10D, 10E, 10F, 110 и 111.
Проверьте правильность ввода значений. В случае, если есть ошибки, то следует повторить команды, которые были введены неправильно.
Теперь осталось самое простое — выполнить эти команды.
Введите команду R для просмотра содержимого регистров и флагов. В данный момент отладчик покажет содержимое регистров в шест. формате, например, AX=0000, BX=0000,...
Содержимое регистра IP (указатель команд) выводится в виде IP=0100, показывая что выполняемая команда находится на смещении 100 байт от начала сегмента кодов. Регистр флагов показывает следующие значения флагов:
NV UP DI PL NZ NA PO NC
Данные значения соответствуют:
u NV —нет переполнения
u UP — правое направление
u DI — прерывания запрещены
u PL — знак плюс
u NZ — не ноль
u NA — нет внешнего переноса
u PO — контроль на честность
u NC — нет переноса.
Команда R показывает также по смещению 0100 первую выполняемую машинную команду.
MOV AX,0123 — ассемблерный мнемонический код, соответствующий введенной машинной команде. Это есть результат операции дизассемблирования, которую обеспечивает отладчик для более простого понимания машинных команд. Рассматриваемая в данном случае команда обозначает пересылку непосредственного значения в регистр AX.
В данный момент команда MOV еще не выполнена. Для ее выполнения нажмите клавишу T (для трассировки) и клавишу Enter. В результате команда MOV будет выполнена и отладчик выдаст на экран содержимое регистров, флаги, а также следующую на очереди команду. Заметим, что регистр AX теперь содержит 0123. Машинная команда пересылки в регистр AX имеет код B8 и за этим кодом следует непосредственные данные 2301. В ходе выполнения команда B8 пересылает значение 23 в младшую часть регистра AX, то есть, однобайтовый регистр AL, а значение 01 — в старшую часть регистра AX, то есть, в регистр AH:
AX: | 01 | 23 |
Содержимое регистра IP:0103 показывает адрес следующей выполняемой команды в сегменте кодов:
13C6:0103 052500 ADD AX,0025
Для выполнения данной команды снова введите T. Команда прибавит 25 к младшей (AL) части регистра AX и 00 к старшей (AH) части регистра AX, то есть, прибавит 0025 к регистру AX. Теперь регистр AX содержит 0148, а регистр IP 0106 — адрес cледующей команды для выполнения.
Введите снова команду T. Следующая машинная команда пересылает содержимое регистра AX в регистр BX и после ее выполнения в регистре BX будет содержаться значение 0148. Регистр AX сохраняeт прежнее значение 0148, поскольку команда MOV только копиpует данные из одного места в другое. Теперь вводите команду T для пошагового выполнения каждой оставшейся в программе команды. Следующая команда прибавит cодержимое регистра AX к содержимому регистраBX, в последнем получим 0290. Затем программа скопирует содержимое pегистра BX в CX, вычтет AX изCX, и вычтет AX из него самого. После этой последней команды, флаг нуля изменит свое состояние c NZ(не нуль) на ZR (нуль), так как результатом этой команды является нуль (вычитание AXиз самого себя очищает этот регистр в 0).
Можно ввести T для выполнения последних команд NOP и RET, но это мы сделаем позже. Для просмотра программы в машинных кодах в сегменте кодов введите D для дампа:
D CS:100
В результате отладчик выдаст на каждую строку экрана по 16 байт данных в шест. представлении (32 шест. цифры) и в символьном представлении в коде ASCII (один символ на каждую пару шест. цифр). Представление машинного кода в символах ASCII не имеет смысла и может быть игнорировано.
Первая строка дампа начинается с 00 и представляет содержимое ячеек от CS:100 до CS:10F. Вторая строка представляет cодержимое ячеек от CS:110 до CS:11F. Несмотря на то, что ваша программа заканчивается по адресу CS:111, команда Dump aвтоматически выдаст на восьми строках экрана дамп с адреса CS:100 до адреса CS:170.
При необходимости повторить выполнение этих команд сбросьте содержимое регистра IP и повторите трассировку снова. Введите R IP, введите 100, а затем необходимое число команд T. После каждой команды нажимайте клавишу Enter.
Для завершения работы с программой DEBUG введите Q (Quit — выход). В результате произойдет возврат в DOS и на экране появится приглашение A> или C>. В случае, если печатался протокол работы с отладчиком, то для прекращения печати cнова нажмите Ctrl/PrtSc.
Определение данных
В предыдущем примере использовались непосредственные данные, описанные непосредственно в первых двух командах (MOV и ADD). Теперь рассмотрим аналогичный пример, в котором значения 0123 и 0025 определены в двух полях сегмента данных. Данный пример позволяет понять как компьютер обеспечивает доступ к данным посредством регистра DS и адресного смещения. В настоящем примере определены области данных, содержащие cоответственно следующие значения: