Р а б о т а

с

п о д п р о г р а м м а м и

Команда вызова процедур CALL

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

Синтаксис:CALL Имя_процедуры

Логика работы команды в случае Near-вызова процедуры:
PUSH IP
IP= IP + смещение_к_нужной_процедуре


Логика работы команды в случае Far-вызова процедуры:
PUSH CS
PUSH IP
CS=Code2
IP= IP + смещение_к_нужной_процедуре


Если у вызываемой процедуры есть параметры, они передаются через стек ДО вызова процедуры.

Для облегчения передачи параметров можно использовать команду CALL в расширенном синтаксисе: CALL Имя_процедуры [язык[, арг1]...] ,
где язык - это С, СРР, PASCAL, BASIC, FORTRAN, PROLOG, NOLANGUAGE,
арг — аргумент, помещаемый в стек в соответствии с принятыми соглашениями.

Команда возврата в точку вызова RET

Команда RET (RETurn from procedure — возврат из процедуры) по действию является обратной команде CALL. Она обеспечивает возврат управления вызывающей программе и, если нужно, очистку стека на величину 16-разрядной константы [Iml6] байт.

Синтаксис:RET [Iml6]

Логика работы команды в случае Near-вызова процедуры:
POP IP


Логика работы команды в случае Far-вызова процедуры:
POP IP
POP CS


Соглашения о вызовах в стиле C/C++

Параметры в стек передаются справа налево.
Первым в стек помещается ПОСЛЕДНИЙ параметр, последним — ПЕРВЫЙ.
По окончании работы очистить стек должна ВЫЗЫВАЮЩАЯ процедура.

; x=(2*a + b*c)/(d-a)
; int x,a,b,c,d;
CODESEG
Extrn C X1:Dword
Extrn C X2:Dword                                       ; Глобальные переменные
Public C prim
; int prim (int a, int b, int c, int d,);
prim proc far
push bp
mov bp, sp                                                       ; указатель bp - на вершину стека
                                                                                  ; !!! параметры в стеке хранятся в ОБРАТНОМ порядке
CS EQU [bp+2] IP equ [bp+4]

a EQU [bp+6]
b EQU [bp+8]
c EQU [bp+10]
d EQU [bp+12]
mov ax,2
imul a                                                                     ; < dx >:< ax > = 2*a
mov bx,dx                                                          ; bx <== ст. часть (dx)
mov cx,ax                                                           ; cx <== мл. часть (ax)
mov ax,b
imul c                                                                      ; < dx >:< ax > = b*c
add ax, cx                                                            ; < ax > = < ax > + < cx > (мл. часть)
adc dx, bx                                                            ; < dx > = < dx > + < bx >(ст. часть)
mov word PTR X1, ax
mov word PTR X1+2, dx                            ; числитель
mov cx, d
sub cx, a                                                               ; < cx > = < cx > -a
mov X2,cx                                                            ; знаменатель
idiv cx                                                                     ; < ax > = < dx > : < ax > / < cx >

pop bp
ret
prim endp
end


Модель large означает, что все процедуры имеют атрибут FAR.
Функция int prim (int a, lilt b, int с, int d) вызывает из С++.
ДО вызова функции в стек должны быть переданы параметры в обратном порядке (справа налево: d,c,b,a):

  • PUSH d
  • PUSH с
  • PUSH b
  • PUSH a

О передаче параметров заботится программа на С++.
Затем следует ДАЛЬНИЙ вызов функции: CALL prim.
При этом в стек загружается адрес возврата в точку вызова:
PUSH IP
PUSH CS

Затем начинает выполняться функцию, реализованную на Ассемблере. Вначале устанавливаем указатель на вершину стека. Для этого используется регистр BP: push bp
mov bp,sp


Содержимое стека после вызова подпрограммы prim:

Положение вершины стека Содержимое стека (длина ячейки 16 бит) Значение смещения относительно регистра BP
SP ???
BP
CS +2
IP +4
a +6
b +8
c +10
d +12

В конце подпрограммы происходит восстановление значения регистра BP и возврат в точку вызова. Очистка стека здесь НЕ делается, этим должна заниматься программа на С++. Директива EQU применяется для удобства сопоставления смещения в стеке с реальными параметрами.


Программирование на Машинно-Ориентированных Языках.
Преподаватель: Коробов С.А.