Пример передачи параметров через стек
Пусть процедура заполняет нулями массив A[0..n-1] , основная программа обращается к ней для обнуления массивов X[0..99] и Y[0..49]. Через стек в ПП передается имя массива и его размер, размер можно передавать по значению, а имя массива нужно передавать по ссылке, т.к. этот параметр является и входным и выходным.
zero_1 proc
push BP ; входные
mov BP, SP ; действия
push BX ; сохранение значений
push CX ; регистров
mov CX, [BP + 4] ; CX = n считывание из стека
mov BX, [BP + 6] ; BX = A параметров
m1: mov byte ptr [BX], 0 ; цикл обнуления
inc BX ; массива
loop m1 ; A[0..n-1]
; восстановление регистров и выходные действия
pop CX
pop BX
pop BP
Ret 4
zero_1 endp
Фрагмент основной программы:
X DB 100 dup (?)
Y DB 50 dup (?)
------------------------
lea AX, X ; загрузка параметров:
push AX ; адреса массива X
mov AX, 100 ; и его размера
push AX ; в стек
call zero_1 ; обращение к ПП
lea AX, Y ; загрузка параметров для массива Y
puah AX ;
mov AX, 50 ;
push AX ;
call zero_1 ; обращение к ПП
---------------------------
Использование локальных параметров.
Если локальных параметров немного, то их размещают в регистрах, но если их много, то возможны различные варианты: им можно отвести место в сегменте данных, но тогда большую часть времени эта область памяти не будет использоваться.
Лучший способ – разместить локальные параметры в стеке на время работы ПП, а перед выходом из ПП их удалить. Для этого после входных действий в процедуре нужно уменьшить значение указателя на вершину стека SP на количество байтов, необходимых для хранения локальных величин и затем записывать их в стек и извлекать их можно с помощью выражений вида: [BP – n], где n определяет смещение локального параметра относительно значения BP, а к фактическим параметрам – [BP + k], где k определяет положение фактического параметра.
Например, если предполагается, что ПП будет использовать 3 локальные параметра размером в слово, то стек графически можно представить так: SP Lz
BP - 4 Ly
BP - 2 Lx
BP BPct
BP + 2 av
BP + 4 ak
-------
a1
---------
SS
При выходе из процедуры перед выполнением завершающих действий нужно возвратить регистру SP его значение.
Если в стеке хранятся и фактические и локальные параметры, то начало процедуры и ее завершение должно выглядеть следующим образом:
PP proc
push BP ; сохранить старое значение BP
mov BP, SP ; (SP) в BP
sub SP, k1 ; отвести в стеке k1 байтов под лок пар - ы
push AX ; сохранить в стеке регистры,
-------------- ; используемые в ПП
<тело процедуры>
------------- ; восстановить регистры
pop AX ;
mov SP, BP ; восстановить SP, т.е. освободить место
pop BP ; в стеке от локальных параметров восстановить BP ret k2 ;очистка стека от фактических параметров и возврат в вызывающую программу
PP endp ; конец ПП
Подсчет количества различных символов в заданной строке.
Строка задана как массив символов. Начальный адрес ее передадим в ПП через регистр BX, длину строки через CX, а результат - через AX. Создадим процедуру, в которой выделяется 256 – ый локальный массив L по количеству возможных символов. K-ому элементу этого массива будем присваивать единицу, если символ, цифровой код которого равен K, в заданной строке существует. Затем подсчитаем количество единиц в этом массиве. Вначале весь массив обнуляется. К первому элементу этого массива можно обратиться так: L1 = [BP – 256]к K – омуLk = [BP – 256 + k].Работая со строками, эту задачу можно решить проще.
Count_s proc ;
; входные действия
Push BP
Mov BP, SP
Sub SP, 256
Push BX
Push CX
Push SI
; Обнуление локального массива
mov AX, CX ; сохранение длины исходной строки
mov CX, 256 ; возможное количество символов
mov SI, 0 ; индекс элемента массива
m1: mov byte ptr [BP – 256 + SI], 0 ;
inc SI
loop m1
; просмотр заданной строки и запись 1 в локальный массив
mov CX, AX ; длину строки в CX
mov AX, 0
m2: mov AL, [BX] ; код очередного символа в AL
mov SI, AX ; пересылаем его в SI
mov byte ptr [BP – 256 + SI], 1 ; пересылаем 1 в к –й элемент массива
inc BX
loop m2 ;
; подсчет количества 1 в локальном массиве
mov AX, 0 ; результат будет в AX
mov CX, 256 ; количество повторений цикла
mov SI, 0 ; индекс массива в SI
m3: cmp byte ptr [BP – 256 + SI], 1
jne m4
inc AX
m4: inc SI
loop m3
; выходные действия
pop SI ; восстановление
pop CX ; регистров
pop BX ;
mov SP, BP ; освобождение стека от локальных параметров
pop BP ; восстановить старое BP
ret
const_s endp
15) Команды пересылки безусловной и условной, команды загрузки адреса
К командам пересылки относят команду обмена значений операндов.
XCHG OP1, OP2; r«r Ú r«m
MOV AX, 10h;
MOV BX, 20h;
XCHG AX, BX; (AX) = 20h, (BX) = 10h
Для перестановки значений байтов внутри регистра используют BSWOP.
(EAX) = 12345678h
BSWOP EAX; (EAX) = 78563412h
Команды конвертирования:
CBW ; безадресная команда, (AL) ® AX. Конвертирует байт в слово
CWD ;( AX) ® DX:AX, конвертирует слово в двойное слово
CWE ; ( AX) ® EAX (для i386 и выше) из 16 в 32 разряда
CDF ; (EAX) ® EDX:EAX (для i386 и выше) из 32 в 64 разряда