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