Передача параметров
Программист имеет полную свободу в выборе способа передачи входных параметров в подпрограмму и выходных – из подпрограммы, важно лишь, чтобы обработка параметров в подпрограмме была согласована с заданием параметров в вызывающей программе.
Чаще всего применяется передача параметров через регистры или через стек.
При передаче через регистры программа перед вызовом заносит входные параметры в некоторые регистры процессора, а после возврата выбирает из регистров значения результатов.
При передаче через стек программа перед вызовом заносит параметры в стек с помощью команды push. Обычно при этом считается, что подпрограмма имеет только входные параметры (как функция в языке Си). Чтобы подпрограмма могла изменять значения параметров, следует передавать ей не сами значения, а адреса параметров.
Для доступа к параметрам, переданным в стеке, в начале подпрограммы обычно выполняются команды:
push BP
mov BP, SP
После этого можно адресовать величины в стеке, указывая их смещения относительно верхушки стека, адрес которой – в регистре BP. При подсчете смещения нужно учитывать, что команда call, как отмечалось выше, помещает в стек адрес возврата (одно или два слова). Удобно для адресации параметров описать соответствующую структуру данных.
Можно применять смешанные способы передачи параметров. В частности, для подпрограмм-функций удобно возвращать результат в регистре, даже если входные параметры получены в стеке.
Рассмотрим пример. Пусть подпрограмма типа near имеет два словных параметра, передаваемых через стек. В этом случае после вызова подпрограммы, сохранения и загрузки регистра BP (см. выше), стек будет выглядеть, как показано ниже:
BP | Ü SP сохраненное значение BP |
IP | адрес возврата |
2-й параметр | параметр, занесенный в стек вторым |
1-й параметр | параметр, занесенный в стек первым |
. . . |
Если описать следующую структуру:
__arg struc
__saveBP dw ?
__retAddr dw ?
__Param2 dw ?
__Param1 dw ?
__arg ends,
то доступ к параметрам можно осуществить с помощью команд:
mov AX, __Param1[BP]; загрузить в AX значение первого параметра
mov BX, __Param2[BP]; загрузить в BX значение второго параметра
Для облегчения чистки стека от переданных параметров используется разновидность команды ret с операндом – числом байтов, которые нужно убрать из стека сразу после возврата. Это позволяет вызывающей программе не заботиться об удалении параметров из стека. Для нашего примера команда возврата из подпрограммы может выглядеть следующим образом:
ret 4