Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Табличные вызовы подпрограмм.
В тех случаях, когда программа с включенными в неё подпрограммами выполняется по достаточно несложному алгоритму, вызывая подпрограммы в заданном заранее порядке, подпрограммы можно разместить в отдельных процедурах (или назначить им входные метки) и вызывать по именам. В более гибких программных системах бывает удобно предусмотреть механизм вызова требуемой подпрограммы по её номеру. Так сделано в DOS и BIOS. Для вызова функции DOS в AH заносится номер функции и с помощью int 21h вызываем диспетчер DOS. Диспетчер извлекает из AH номер функции и активизирует по этому номеру соответствующую программу из числа функций DOS. Рассмотрим упрощенную имитацию диспетчера DOS. В нашей программе должен быть диспетчер, вызываемый с помощью прерывания и переопределяющий управление подпрограмм с заданным в AH номером. Адрес диспетчера внесем в один из свободных номеров. jmp start ; Диспетчер прерывания 65h new_65h: push bx push dx mov bl,ah mov bh,0 shl bx,1;Логический сдвиг влево на один разряд call add_tbl[bx]; pop dx pop bx iret ;Подпрограммы-функции sub0: mov ah,9 lea dx,mes0 int 21h ret ... ... ... sub4: mov ah,9 lea dx,mes4 int 21h ret start: mov ax,2565h;функция заполнения вектора ; прерывания int 65h mov dx, offset new_65h int 21h ;Последовательно вызываем подпрограммы mov ah,0 int 65h mov ah,1 int 65h ... ... ... mov ah,4 int 65h mov ax,4c00h int 21h ;Таблица адресов и подпрограмм add_tbl dw sub0 dw sub1 ... ... ... dw sub4 ;Сообщения mess0 db ‘Отработала подпрограмма 0’, 13,10,’$’ ... ... ... mess4 db ‘Отработала подпрограмма 4’, 13,10,’$’
Номер функции пересылается из AH в регистр BX, который в дальнейшем используется в качестве индексного. Сдвиг BX соответствует умножению на 2. Теперь BX - индекс, в таблице адресов addr_tbl, в которой записаны смещения (относительные адреса) подпрограмм в порядке, определяющем их номера. Команда call addr_tbl[bx] косвенного вызова, передает управление на требуемую подпрограмму. Диспетчер с помощью iret возвращает управление в основную программу.
{?????????????????
Вектор Z слова разделяется на CS и IP Вектор можно изменить непосредственно, засылая байты по адресу вектора. При изменении вектора нужно соблюдать меры предосторожности. В некоторых случаях может возникнуть прерывание в процессе изменения вектора. Команда CLI запрещает прерывания, все кроме NMI-немаскируемых прерываний. xor ax,ax mov es,ax cli;приостановить прерывания mov word ptr es:36,xx;переслать из вектора смещения mov word ptr es:38,yy;и сегментную часть sti;разрешить прерывания
Можно скомбинировать две команды mov в одну. movs - пересылка строки. Однако лучше отдать это DOS и не делать своими руками. lea dx, buffer_end;адрес конца программы int 27h;выход с сохранением программы в памяти
Print_handler proc far
Пример использования функции 37=25h DOS для установки вектора прерывания: mov dx,xx;загрузить в вектор смещение mov ds,yy;загрузить сегментную часть вектора mov ah,25h;код функции mov al,9;изменить вектор прерывания номер 9 int 33;прерывание вызова функции (Прерывание 9 генерируется при нажатии клавиши)
Это наиболее простой способ использования служебной функции DOS. Однако, один из адресов, передаваемых DOS, нужно загрузить в DS, что по существу препятствует нормальному доступу через этот регистр к нашим данным. Следующая программа разрешает эту проблему: push ds;сохранить текущий сегмент данных mov dx,offset xxx;получить смещение вектора push cs;переслать наш новый сегмент кода... pop ds;в сегмент данных mov ah,25h;функция установки вектора прерывания mov al,9;изменить вектор прерывания номер 9 int 21h;вызов DOS pop ds;восстановить начальный сегмент данных
Для функции 25h: ah=25h al= номер прерывания ds:dx - указатель программы обработчика прерывания Оператор offset возвращает относительный адрес (смещение) переменной или метки внутри сегмента данных или кода. Формат: offset переменная или метка Пример mov dx,offset tablea;помещает в dx смещение ;поля tablea в сегменте данных Программа
code_seg segment assume cs:code_seg, ds:code_seg, es:code_seg org 100h jmp start print_vector dd?;место для хранения исходного вектора 17h start: mov ah,35h mov al,17h int 21h mov word ptr print_vector,bx mov word ptr print_vector+2,es
cli push ds mov dx, offset print_handler push cs;mov ax, seg print_handler pop ds;mov ds,ax mov ah,25h mov al,17h int 21h pop ds sti
????????????????? }
Макрокоманды.
Для каждой команды на ассемблере транслятор генерирует одну машинную инструкцию. Т.о. происходит трансляция «один в один». При трансляции программы на языке высокого уровня каждый оператор заменяется чаще всего не одной, а несколькими командами машинного языка. Т.о. можно сказать, что языки высокого уровня состоят из макрооператоров. Ассемблер также имеет макро средства, но макроопределения или макрокоманды задаются программистом. Использование макрокоманд (макросов) позволяет: · упростить и сократить исходный текст. · сделать программу более понятной. · уменьшить число ошибок, т.е. увеличить скорость отладки.
Макроопределения.
Прежде, чем программист сможет использовать в тексте своей программы макрокоманду, он должен сначала её определить - такое задание макрокоманды называется макроопределением.
Формат макроопределения. имя macro;начало макроопределения . .;тело макроопределения .. endm;конец макроопределения Директива macro указывает ассемблеру, что следующие команды до директивы endm являются макроопределением. Теперь при трансляции программы, когда ассемблер встретит имя программы, вместо него будут подсьавлены команды, составляющие тело макроса. Например: _print_ macro;Вывод сообщения на экран mov ah, 09h lea dx, mes int 21h endm Использование параметров в макроопределениях.
В предыдущем примере макрокоманда всегда выводит на экран сообщение, находящееся в mes. Для того, чтобы макрокоманда была более гибкой и могла распечатывать любые сообщения, определим указатель сообщения, как формальный параметр. Формальный параметр в макроопределении указывает ассемблеру на соответствие их имен аналогичным именам в теле макроопределения. Например: _print_ macro msg;Вывод сообщения на экран mov ah, 09h lea dx, msg int 21h endm Теперь при использовании директивы _print_ необходимо указать в качестве параметра действительный адрес сообщения, например: _print_ msg1 _print_ msg2 Макроопределение может содержать ссылку на другое макроопределение. Рассмотрим пример: dos21 macro dosfunc mov ah, dosfunc int 21h endm Для использования данной макрокоманды при вводе с клавиатуры необходимо: lea dx,namepar dos21 0ah Предполагается, что имеется другое макроопределение, использующее функцию 02 в регистре ah для ввода символа. disp macro char mov ah,02 mov dl,char int 21h endm Можно изменить макроопределение disp, воспользовавшись макрокомандой dos21:
disp macro char mov dl,char dos21 02 endm Для вывода ‘*’ достаточно просто написать: disp ‘*’ Директива LOCAL
Если в теле макрокоманды определены метки, то при использовании такой макрокоманды в программе более одного раза - метки будут повторятся и ассемблер выдаст сообщение об ошибке. Для обеспечения уникальности генерируемых в каждом макрорасширении имен используется директива LOCAL, которая должна быть непосредственно после macro. Общий формат: local метка1, метка2 Например: prim_ macro local compar,exit ... compar:... ... exit:... и макрокоманда prim_ два раза встречается в контексте нашей программы: ... prim_ ... prim_ В первом макрорасширении генерируются метки??0000 и??0001 соответственно для compar и exit. Во втором макрорасширении - метки??0002 и?0003 и т.д.
|
||
Последнее изменение этой страницы: 2017-02-07; просмотров: 274; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.191.157.186 (0.005 с.) |