Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ASM_lectures.doc
Скачиваний:
37
Добавлен:
28.04.2019
Размер:
992.77 Кб
Скачать

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

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

????????????????? }

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]