
- •Лекция 1. Введение. Системное программное обеспечение. Состав системного программного обеспечения
- •Лекция 2. Принципы функционирования систем программирования
- •Этапы подготовки программы
- •Трансляторы и интерпретаторы – общая схема работы
- •Лекция 4. Назначение и функции компоновщика.
- •Раздельная компиляция
- •Переместимые коды и абсолютные коды
- •Редактирование связей с оверлеями
- •Связывание с динамически подсоединяемыми библиотеками (dll)
- •Лекция 5. Назначение и функции программы загрузчика
- •Виды загрузчиков. Загрузчики типа «компиляция-выполнение».
- •Абсолютный загрузчик
- •Настраивающий загрузчик
- •Непосредственно связывающий загрузчик
- •Динамический загрузчик
- •Программные отладчики и их эксплуатация
- •Лекция 6. Базовые понятия языка.
- •Лекция 7. Базовые понятия языка.
- •Лекция 8. Команды и алгоритмы языка.
- •Лекция 9.1. Сложные структуры данных.
- •Команда loop
- •Лекция 9.2. Сложные структуры данных. Структуры
- •Объединения
- •Лекция 2.4. Организация и использование подпрограмм
- •Передача параметров по значению
- •Передача параметров по ссылке
- •Передача параметров по возвращаемому значению
- •Передача параметров по результату
- •Передача параметров по имени
- •Передача параметров отложенным вычислением
- •Передача параметров в регистрах
- •Передача параметров в глобальных переменных
- •Передача параметров в стеке
- •Передача параметров в потоке кода
- •Передача параметров в блоке параметров
- •Лекция 2.5. Макросредства языка Ассемблер
- •Лекция 2.6. Работа с файлами, каталогами и дисками под управлением ms-dos
- •Лекция 3.1. Структура и программирование контроллера прерываний.
- •Лекция 4.1. Работа с консолью. Организация ввода/вывода информации.
- •Лекция 5.1. Системные средства управления памятью
- •Окружение dos
- •Лекция 6.1. Основы организации резидентных программ
- •7.1. Функции драйвера
- •7.2. Архитектура драйвера
- •Процесс загрузки драйверов
- •7.3 Команды драйвера
Передача параметров в потоке кода
В этом необычном методе передаваемые процедуре данные размещаются прямо в коде программы, сразу после команды CALL (как реализована процедура print в одной из стандартных библиотек процедур для ассемблера UCRLIB):
call print
db "This ASCIZ-line will be printed",0
(следующая команда)
Чтобы прочитать параметр, процедура должна использовать его адрес, который автоматически передается в стеке как адрес возврата из процедуры. Разумеется, функция должна будет изменить адрес возврата на первый байт после конца переданных параметров перед выполнением команды RET. Например, процедуру print можно реализовать следующим образом:
print proc near
push bp
mov bp,sp
push ax
push si
mov si,[bp+2] ; прочитать адрес
; возврата/начала данных
cld ; установить флаг направления
; для команды lodsb
print_readchar:
lodsb ; прочитать байт из строки,
test al,al ; если это 0 (конец строки),
jz print_done ; вывод строки закончен
int 29h ; вывести символ в AL на экран
jmp short print_readchar
print_done:
mov [bp+2],si ; поместить новый адрес возврата в стек
pop si
pop ax
pop bp
ret
print endp
Передача параметров в потоке кода, так же как и передача параметров в стеке в обратном порядке (справа налево), позволяет передавать различное число параметров, но этот метод — единственный, позволяющий передать по значению параметр различной длины, что и продемонстрировал этот пример. Доступ к параметрам, переданным в потоке кода, несколько медленнее, чем к параметрам, переданным в регистрах, глобальных переменных или стеке, и примерно совпадает со следующим методом.
Передача параметров в блоке параметров
Блок параметров — это участок памяти, содержащий параметры, так же как и в предыдущем примере, но располагающийся обычно в сегменте данных. Процедура получает адрес начала этого блока при помощи любого метода передачи параметров (в регистре, в переменной, в стеке, в коде или даже в другом блоке параметров). В качестве примеров использования этого метода можно назвать многие функции DOS и BIOS, например поиск файла, использующий блок параметров DTA, или загрузка (и исполнение) программы, использующая блок параметров ЕРВ.
Лекция 2.5. Макросредства языка Ассемблер
Макросредства - инструменты (средства) модификации текста программы во время ее трансляции.
Макросредства предназначены для облегчения написания программ на языке Ассемблер и для улучшения понимания исходного текста программы.
Основная идея. Повторяющийся фрагмент программы специальным образом описывается (макрос), именуется, а затем в нужных местах программы указывается ссылка на него. При создании объектного кода вместо ссылки подставляется сам фрагмент, т.е. происходит подстановка фрагмента вместо ссылки.
Транслятор ассемблера состоит из двух частей: макрогенератора и непосредственно транслятора. Транслятор при этом называют макроассеблером.
Обработка программы с использованием макросредств осуществляется транслятором в два этапа. На первом этапе работает макрогенератор, который производит замены для всех макросов, а на втором этапе уже преобразованный текст программы транслируется в объектный код.
Макроопределение
Это описание макроса. Синтаксис макроопределения:
<имя макрокоманды> MACRO [формальные параметры]
тело макроопределения
ENDM
Директива MACRO - это заголовок макроопределения. В ней указывается имя и через запятую перечисляются формальные параметры, если необходимо.
Формальные параметры позволяют копировать макрос не в неизменном виде, а с изменениями. Те величины, которые необходимо будет изменить описываются формальными параметрами.
Замечание. Имена формальных параметров локальны по отношению к макросу, т.е. они могут совпадать с именами в основной программе, макрогенератор понимает их как параметры.
Завершает макроопределение директива ENDM. !!! Не надо повторять имя макроса.
Пример 1 ; настройка сегмента данных
initds macro
mov ax, @data
mov ds, ax
endm
Размещаться макроопределения могут :
1. В любом месте программы.
!!! Обязательно до первой ссылки на него.
2. В отдельном файле.
Чтобы сделать доступными макроопределения в программе, необходимо в начале программы использовать директиву INCLUDE <имя файла>. При этом на этапе работы макрогенератора текст указанного файла будет вставлен полностью на место директивы.
Пример.
model small
include Mymacro.inc
. . .
Можно универсальные макрокоманды записать в один файл, в так называемую макробиблиотеку. Подключать ее с помощью директивы include.
Чтобы в текст программы не включать лишние макроопределения, можно воспользоваться директивой
PURGE <список через запятую имен макроопределений>
Директива указывает, какие макроопределения не должны включаться в текст программы.
Пример. . . .
include mymacro.inc
purge outstr, initds
. . .
Макрокоманды
Макрокоманда - обращение к макроопределению. Или указание макрогенератору на то, что на указанном месте необходимо подставить тело макроопределения. Итак, одна макрокоманда заменяется на группу команд, поэтому она и наз. макро (большая).
Синтаксис макрокоманды:
<имя макроса> [<фактические параметры>]
Замечание. Фактические параметры можно разделять запятыми или пробелами.
Формальные параметры макроопределения заменяются соответствующими фактическими параметрами макрокоманды.
!!! i-тый фактичнский параметр соответствует i-тому формальному параметру
!!! Число фактических параметров должно быть равно числу формальных параметров,
если фактических параметров больше, то лишние игнорируются
если формальных больше, считается что в качестве недостающих фактических указаны пустые тексты
Процесс замещения формальных параметров фактическими называется макроподстановкой. Результат макроподстановки (т.е. полученный в результате текст называется макрорасширением.
Действия макрогенератора:
1) макрогенератор находит макроопределение с указанным именем
2) в его теле заменяет все формальные параметры фактическими
3) полученное макрорасширение подставляет в программу вместо макрокоманды
Сравнительный анализ процедур и макросредств
Повторяющиеся действия (фрагменты) в программе можно описать и как процедуру, и как макроопределение. При этом в обоих случаях повторяющийся участок кода описан только один раз, а обращаемся к нему с помощью одной команды (вызов процедуры или макрокоманда). Но...
После трансляции процедура так и останется описанной один раз, а тело макроопределения подставится во все места вызова и тем самым увеличит размер программы.
Вывод 1. Применение процедур делает код более компактным, т.е. экономим память
Но при обращении к процедуре
а) выполняется засылка параметров в регистры или стек,
б) запоминается адрес возврата
в) осуществляется переход,
г) по окончании работы процедуры восстанавливается адрес возврата,
д) очищаются регистры или стек и т.п.
Итак, при работе процедуры тратится время на переходы и передачу параметров во время выполнения программы.
!!! При замене макрокоманд на макрорасширения тоже тратится время, но это происходит на этапе трансляции, а не во время выполнения программы.
Вывод 2. Применение макросредств экономит время выполнения программы.
Поэтому в программах критических по времени следует применять макросредства, а если необходимо экономить память следует применять процедуры.
Если в повторяющемся участке кода много команд (т.е. большой фрагмент) лучше описать его как процедуру. Если же небольшую группу команд описать процедурой, то число вспомогательных команд по ее вызову и передаче параметров станет сравнимым с числом команд самой процедуры, ее время выполнения станет на много больше.
Вывод 3. Большие участки кода рекомендуется описывать как процедуры, а маленькие - как макроопределения.
!!! Еще одно отличие использования макросредств и процедур заключается в том, что параметрами процедур могут быть только операнды команд, а параметрами макрокоманд могут быть любые последовательности символов, в том числе и сами команды.
Макрокоманды
Осмысленное рассмотрение данного механизма предполагает понимание смысла терминов макрокоманда и макроопределение. Макрокоманда представляет собой строку, одним из компонентов которой является символическое имя макрокоманды. Имя макрокоманды может сопровождаться параметрами. Если данная строка встречается в теле исходного текста программы, то транслятор замещает ее одной или несколькими другими строками. Какими именно строками — определяется макроопределением, которое представляет собой шаблон (описание) макрокоманды.
Таким образом, для использования макрокоманды в программе первым делом задают ее макроопределение.
Синтаксис макроопределения следующий:
имя_макрокоманды macro список_формальных_аргументов
тело макроопределения
endm
Макроопределение обрабатывается компилятором особым образом. Для того чтобы использовать описанное макроопределение, его нужно «активизировать» с помощью макрокоманды. Для этого в нужном месте исходного кода программы на основе текста заголовка макроопределения указывается следующая синтаксическая конструкция:
имя_макрокоманды список_фактических_аргументов
Макродирективы
С помощью макросредств ассемблера можно не только частично изменять входящие в макроопределение строки, но и модифицировать сам набор этих строк и даже порядок их следования. Сделать это можно с помощью набора макродиректив (далее — просто директив). Их можно разделить на две группы.
Директивы повторения WHILE, REPT, IRP и IRPC предназначены для создания макросов, содержащих несколько идущих подряд одинаковых последовательностей строк. При этом возможна частичная модификация этих строк.
Директивы управления процессом генерации макрорасширений EXITM и GOTO предназначены для управления процессом формирования макрорасширения из набора строк соответствующего макроопределения. С помощью этих директив можно как исключать отдельные строки из макрорасширения, так и вовсе прекращать процесс генерации. Директивы EXITM и GOTO обычно используются вместе с условными директивами компиляции, поэтому они будут рассмотрены вместе с ними.
Директивы WHILE и REPT
Директивы WHILE и REPT применяются для повторения определенное количество раз некоторой последовательности строк. Эти директивы имеют следующий синтаксис:
WHILE константное_выражение
последовательность строк
ENDM
REPT константное_выражение
последовательность строк
ENDM
Пример:
N = 0
REPT 5
N = N + 1
DB N
ENDM
Директива IRP
Директива IRP имеет следующий синтаксис:
IRP формальный_аргумент,<строка_символов_1 строка_символов_n>
последовательность строк
ENDM
Действие данной директивы заключается в том, что она повторяет последовательность строк n раз, то есть столько раз, сколько строк символов заключено в угловые скобки во втором операнде директивы IRP.
Пример:
IRP N,<3, 9, 17, 25, 28>
DB N
ENDM
Директива IRPC
Директива IRPC имеет следующий синтаксис:
IRPC формальный_аргумент, строка_символов
последовательность строк
ENDM
Действие данной директивы подобно действию директивы IRP, но отличается тем, что она на каждой очередной итерации заменяет формальный аргумент очередным символом из строки символов.
Пример:
IRPC N,345678
DW N
ENDM