Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
43
Добавлен:
15.04.2015
Размер:
1.15 Mб
Скачать
  1. Вызов процедуры

CALL [модификатор] имя

Здесь имя условно, чаще всего это адрес, точка входа в процедуру

Модификатор: near, far, ptr

По этой команде содержимое регистров cs, eip/ip загружается в стек (при дальнем переходе). Далее в регистры cs, eip/ip загружается сегментный адрес и смещение адреса точки входа в процедуру (при ближней адресации загружается только eip/ip).

Команда возврата из процедуры может содержать параметр – число.

Ret [число]

Число – это величина обхода стека при выходе из процедуры

чтение запись

ip

[cs]

dat1

dat2

По команде ret из стека читаются 2 слова (адрес возврата) и загружаются в соответствующие регистры. Если стоит команда ret 4, то указатель стека спускается вниз на 4 байта, чтобы обойти данные dat1 и dat2 (если стоит директива USE16 ) .

Если указано Use 32, то из указателя вершины стека вычитается 8 байт .

  1. Способы вызова процедуры

Начало процедуры может быть обозначено меткой, а в случае косвенного вызова, когда адрес вычисляется и заносится в выделенную ячейку, наличие метки в точке входа в подпрограмму необязательно.

Прямой ближний вызов

Команда CALL помещает в стек содержимое IP и загружает в этот регистр адрес точки входа. В стеке будет задействовано только 2 байта.

Пример:

.code

start proc far

call sub

mov ax, 4c00h

int 21h

start endp

sub proc near

ret

sub endp

end start

Прямой дальний вызов

По команде CALL в стек заносится содержимое регистров cs и ip (4 байта).

Пример:

В программе объявлены 2 кодовых сегмента.

seg1 segment 'code'

start proc far

call far ptr sub

mov ax, 4c00h

int 21h

start endp

seg1 ends

seg2 segment 'code'

sub proc far

ret

sub endp

seg2 ends

Косвенный ближний вызов

Подразумевает запись адреса точки входа (смещения) в ячейку памяти либо регистр и обращение при запуске процедуры к памяти или к регистру, где хранится адрес.

Пример

.data

subadr dw subr ; по адресу subadr записан адрес метки sub

.code

start proc

mov ax,@data

mov ds,ax

call word ptr subadr ; из памяти взять слово

mov ax, 4c00h ; выход

int 21h

start endp

subr proc near

ret

subr endp

end start

При косвенном запуске программы возможны другие варианты,

например:

mov bx, offset subr

call word ptr bx ; адрес процедуры в регистре bx

Косвенный дальний вызов процедуры

dseg segmentdata

subadr dd subr

dseg ends

cseg1 segment ‘code’

start proc far

……

call dword ptr subadr

……….

ret

start endp

cseg1 ends

cseg2 segment ‘code’

subr proc far

ret

subr endp

cseg2 ends

  1. Организация интерфейса между процедурами, расположенными в разных модулях

Используются директивы: EXTRN, PUBLIC, GLOBAL

Директива EXTRN объявляет некоторое имя внешним по отношению к данному модулю.

Это имя должно быть объявлено в другом модуле директивой PUBLIC.

EXTRN имя:тип [, имя:тип] ,[имя:тип] ….

Имя – идентификатор, определенный в другом модуле.

В качестве идентификаторов используются:

  • имена переменных, определенные директивами db, dw, dd и т.д. ,

  • имена процедур,

  • имена констант.

Для переменных тип может быть: byte, word, dword, pword, fword, qword, tbyte.

Тип процедуры far (дальняя) или near (ближняя).

Если имя – константа, то тип в директиве – abs.

Директива PUBLIC объявляет имена, определенные в этом модуле, видимыми из других модулей.

PUBLIC имя [,имя] [,имя]…

Директива GLOBAL, используемая применительно к передаваемому объекту, интерпретируется как директива PUBLIC, а используемая применительно к принимаемому объекту – как EXTRN

Директива GLOBAL имеет формат директивы EXTRN

GLOBAL имя:тип [, имя:тип]

Пример программы, использующей данные директивы:

;модуль1

GLOBAL res : byte, add : far

PUBLIC fix

data segment 'data' ; сегмент данных

fix db 12

data ends

code segment 'code'

start:

…….

……..

mov al, res ; resв другом модуле

call far ptr add ; запускается программа add

code ends

end start

;модуль2

GLOBAL res:byte , add:far

EXTRN fix:byte

dseg2 segment 'data'

res db ?

dseg2 ends

seg2 segment 'сode'

…….

add proc far

mov al, fix ; fix в другом модуле

mov res, al

add endp

ret

seg2 ends