Табличные вызовы подпрограмм. 
";


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Табличные вызовы подпрограмм.



 

В тех случаях, когда программа с включенными в неё подпрограммами выполняется по достаточно несложному алгоритму, вызывая подпрограммы в заданном заранее порядке, подпрограммы можно разместить в отдельных процедурах (или назначить им входные метки) и вызывать по именам. В более гибких программных системах бывает удобно предусмотреть механизм вызова требуемой подпрограммы по её номеру. Так сделано в 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 с.)