Локальные переменные
Теперь вы знаете, как передавать переменные в процедуры, а вот как насчет временных и локальных переменных, которые действуют только внутри процедуры?
Когда мы пишем программы на Си, то применяем локальные переменные для вычислений, сохранения результатов и т. д. Так же, как и в Си, мы можем создать локальные переменные в наших ассемблерных функциях, используя стек. Конечно, можно создать локальные переменные в области данных (например, в сегменте данных), но этого не стоит делать. Почему? Дело в том, что стек как раз и создавался для временного хранения данных и локальных переменных, так что именно им и стоит пользоваться.
Давайте посмотрим, как это делается. Когда мы определяем стек, сохраняя регистр ВР, то можем извлекать параметры путем прибавления положительного смещения к регистру ВР, например, [ВР+6] и т. д. Таким образом, получается, что в действительности стек — это область непрерывной памяти, которую мы можем использовать также и для хранения локальных переменных. Для этого нам надо только использовать отрицательное смещение относительно регистра ВР.
В случае, если мы хотим иметь две локальные переменные 1осаl_1 и 1оса1_2, можно использовать следующую подстановку:
local_1 EQU [ВР-2]
local_2 EQU [BP-4]
Это дает нам два целых числа. Пока нам не известно, что записано по этим адресам и мы можем только предполагать, что данный участок памяти можно использовать безболезненно. Однако нужно помнить, что мы только что использовали стек для хранения данных и теперь нам необходимо самим изменить регистр SP для отражения этого. Если этого не сделать, то первая встретившаяся инструкция PUSH обязательно что-нибудь запишет в нашу переменную и непременно «испортит» ее.
Для исключения этой ситуации можно предложить уменьшить значение регистра SP на длину переменных, которые мы хотим сохранить. В нашем случае это составит четыре байта. В Листинге 2.4 показано, как это сделать.
Листинг 2.4. Корректировка регистра SP.
push ВР ; устанавливаем фрейм стека, как обычно
mov BP,SP
sub SP,4 ; корректируем указатель стека. Теперь наши
;переменные не будут случайно изменены
;Вся работа выполняется здесь
add SP,4 ; перед уничтожением фрейма стека надо восстановить
; исходное значение указателя стека
pop ВР
; уничтожаем фрейм стека,
; восстанавливая регистр ВР