Рис. 4. Схема смещения в оперативной памяти программы
Часто основная программа должна передать вызываемой подпрограмме определенные данные, с которыми подпрограмма должна работать. Также подпрограмма после завершения работы должна передать результат своего выполнения в вызвавшую её программу. Существует три основных способа передачи параметров: через регистры, через общую область памяти и через стек. В большинстве языков высокого уровня, включая Pascal и C, передача параметров обычно осуществляется через стек. Передача параметров заключается в том, что вызывающая программа предварительно помещает в стек в определённом порядке параметры, требуемые для выполнения подпрограммы, а затем вызывает эту подпрограмму
[3].
Пример передачи параметров через стек представлен на рис. 5. Перед вызовом подпрограммы в стек размещаются 3
19
параметра (рис. 5,б), а при выполнении команды Call добавляется адрес возврата из подпрограммы (рис. 5,в).
а) - стек до вызова подпрограммы; б) - в стек поместили три параметра; в) - стек после выполнения команды call; г) - стек после возврата из подпрограммы командой ret 6.
Рис. 5. Передача параметров через стек
Команда возврата из подпрограммы RET считывает из стека адрес возврата, но при этом указатель стека SP указывал бы на параметр 3. Так как в дальнейшем эти параметры использоваться не будут, то это может привести к переполнению стека. Поэтом используется команда RET N, которая считывает адрес возврата и прибавляет к регистру SP значение N. На рисунке 5,г представлен случай, когда выполняется команда RET 6, что позволяет указателю стека SP переместится в первоначальное состояние до передачи параметров и вызова подпрограммы.
На языке Ассемблера подпрограммы(процедуры) оформляются в следующем виде:
Name Proc
.....................; команды процедуры
.....................
Ret;(RET N)
Name Endp
20
Рассмотрим пример реализации и использования в программе функции, рассчитывающей среднее значение 3 однобайтных целых чисел без знака:
; add your code here |
|
push 150 |
; передача параметра 1 |
push 150 |
; передача параметра 2 |
push 30 |
; передача параметра 3 |
call myFunction |
; вызов подпрограммы MyFunction |
HLT ; halt! |
; остановка работы процессора |
myFunction proc |
; подпрограмма MyFunction |
push bp |
; сохраняем предыдущее значение |
mov bp,sp |
; запоминаем в регистре ВР адрес последнего |
|
элемента стека |
xor ah,ah |
; обнуляем старший байт регистра АХ(АН) |
mov al,[bp+4] |
; записываем в регистр AL значение параметра |
|
3 |
add al,[bp+6] |
; складываем содержимое регистров AL и па- |
|
раметра 2 и сохраняем результат в AL |
jnc l1 |
; если есть переполнение регистра AL, |
inc ah |
; то увеличиваем регистр АН на 1 |
I1: |
; метка |
add al,[bp+8] |
; прибавляем к регистру AL содержимое па- |
|
раметра 1 |
jnc l2 |
; если есть переполнение регистра AL, |
inc ah |
; то увеличиваем регистр АН на 1 |
|
; в итоге в регистре АХ будет содержать сумму |
|
3 параметров |
I2: |
|
mov bl,3 |
; помещаем в регистр BL значение 3 |
div bl |
; делим содержимое регистра AX на BL |
|
; в регистре AL - будет целая часть результата |
|
операции деления, в АН - остаток. |
pop bp |
; восстанавливаем содержимое регистра ВР |
ret 6 |
; вытаскиваем из стека адрес возврата и уста- |
|
навливаем SP=SP+6 |
myFunction endp |
|
Три входных параметра передаются функции MyFunction через стек. Для обращения к параметрам внутри функции используется регистр BP. Так как данный регистр
21
мог использоваться в основной программе, то его первоначальное значение нужно сохранить.
Поэтому первой командой подпрограммы является сохранение значения регистра BP в стек и предпоследней - восстановление первоначального значения. В результате, в стеке оказывается 5 двухбайтных элементов: 3 входных параметра, адрес возврата и значение регистра BP.
Следующей командой процедуры в регистр BP заносим значение указателя стека SP, который содержит адрес последнего элемента стека. Зная адрес последнего элемента и порядок загрузки параметров можно обращаться к нужному параметру, используя регистровую относительную адресацию, по следующей формуле:
A=[BP+Sm], Sm=4+(n-i)*2, |
(3.1) |
где A -адрес параметра; BP - регистр микропроцессора, хранящий адрес последнего элемента стека; Sm - смещение параметра в байтах от вершины стека; n - количество параметров; i - порядковый номер параметра.
Параметр команды RET N определяется формулой:
N=n*2. |
(3.2) |
Последней командой процедуры восстанавливаем адрес возврата и устанавливаем значение SP в первоначальное состояние [5].
Задачи:
1. Разработать процедуру, вычисляющую значение линейной функции:
y=(a+b)/2 |
(3.3) |
где y - результат, который сохраняется в регистр AL;
22
a,b - целые однобайтные числа без знака , которые передаются в качестве параметров процедуре;
2.Разработать программу, использующую процедуру из пункта 1 задания, и проверить её в пошаговом режиме в эмуляторе Emu8086;
3.Сделать выводы и составить отчет по работе.
Порядок выполнения работы :
1.Создайте новый проект в среде эмулятора
Emu8086, используя шаблон «Bin template»;
2.Разработайте процедуру на языке ассемблера согласно заданию 1 из постановки задачи. Значения параметров a
иb возьмите из табл. 5 согласно своему варианту.
Таблица 5
Варианты заданий
Номер |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
|
варианта |
|||||||||||
|
|
|
|
|
|
|
|
|
|
||
a |
15 |
16 |
10 |
120 |
50 |
110 |
39 |
33 |
25 |
89 |
|
b |
20 |
30 |
60 |
100 |
39 |
51 |
69 |
79 |
32 |
63 |
|
Номер |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
|
варианта |
|||||||||||
|
|
|
|
|
|
|
|
|
|
||
a |
22 |
29 |
68 |
75 |
81 |
36 |
73 |
92 |
74 |
22 |
|
b |
167 |
75 |
93 |
134 |
88 |
101 |
99 |
49 |
38 |
150 |
3.Разработайте программу, использующую процедуру, реализованную во втором пункте. За основу возьмите пример кода, представленного в теоретической части данной работы;
4.Запустите проект на эмуляцию, нажав кнопку меню «Emulate». Нажмите в окне «emulator» кнопку «stack» для отображения содержимого стека;
5.Начните выполнение программы в пошаговом режиме, нажав кнопку «Single step». Перед выполнением команды «Call MyFunction», зафиксируйте значения регистров IP
иSP соответственно как IP1 и SP1 в табл. 6. Вычислите значе-
23