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