Шаг 39.
Возврат результата из процедуры

    На этом шаге мы рассмотрим возврат результата из процедуры через стек.

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

  1. С использованием регистров. Ограничения здесь те же, что и при передаче данных, - это небольшое количество доступных регистров и их фиксированный размер. Функции DOS используют именно этот способ. Из рассматриваемых здесь трех вариантов данный способ является наиболее быстрым, поэтому его есть смысл использовать для организации критичных по времени вызова процедур.

  2. С использованием общей области памяти. Этот способ удобен при возврате большого количества данных, но требует внимательности в определении областей данных и подробного документирования для устранения неоднозначностей.

  3. С использованием стека. Здесь, подобно передаче аргументов через стек, также нужно использовать регистр BP. При этом возможны следующие варианты:
    • использование для возвращаемых аргументов тех же ячеек в стеке, которые применялись для передачи аргументов в процедуру. То есть предполагается замещение ставших ненужными входных аргументов выходными данными;
    • предварительное помещение в стек наряду с передаваемыми аргументами фиктивных аргументов с целью резервирования места для возвращаемого значения. При использовании этого варианта процедура, конечно же, не должна пытаться очистить стек командой RET. Эту операцию придется делать в вызывающей программе, например командой POP.

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

    Проиллюстрируем возврат вычисленного в процедуре значения через стек, изменив последнюю программу. Вычисленный результат будем помещать на место первого аргумента, а второй аргумент будем извлекать из стека при выходе из процедуры командой RET 2. Таким образом, после выхода из процедуры в вершине стека будет находиться результат. Его можно извлечь из стека командой POP.

        TITLE Возврат данных из процедуры через стек.
        ;Программа сделана как EXE-файл.
        ;-------------------------------
        ;----- Сегмент стека
StackSg SEGMENT PARA STACK 'Stack'
DW      256  DUP(?)
StackSg ENDS
        ;----- Сегмент кодов
CodeSg  SEGMENT  PARA  PUBLIC
        ASSUME CS: CodeSg, SS: StackSg
Begin   PROC  FAR
        ;Пролог EXE-файла.
        PUSH DS
        XOR AX,AX
        PUSH AX
        ;Конец пролога
        MOV AX,2
        PUSH AX        ;Запись в стек первого аргумента.
        MOV BX,3
        PUSH BX        ;Запись в стек второго аргумента.
        CALL Summa     ;Обращение к процедуре.
        POP DX         ;Размещение кода цифры  в DX. 
        MOV AH,2
        INT 21h             ;Выводим символ на экран.
        RET
Begin	ENDP
Summa   PROC   NEAR ;"Близкая" процедура с n (n=2) аргументами.
        ;Начало пролога.
        PUSH BP
        MOV BP,SP
        ;Конец пролога.
        MOV AX,[BP+4] ;Загрузка  второго аргумента. 
        ADD AX,[BP+6] ;Сложение второго аргумента с первым. 
        ADD AL,30h ;Получили код выводимой цифры.
        MOV [BP+6],AX;Поместили код цифры 
                     ;на место первого аргумента.
        ;Начало эпилога.
        MOV SP,BP ;Восстановление SP.
        POP BP    ;Восстановление BP.
        RET  2    ;Возврат в вызывающую программу с удалением 
                  ;второго аргумента из стека.
        ;Конец эпилога.
Summa   ENDP
CodeSg  ENDS
        END Begin
Текст этой программы можно взять здесь.

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




Предыдущий шаг Содержание Следующий шаг