Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЯМП ответы.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
711 Кб
Скачать
☆

39.Процедуры в языке ассемблера. Передача параметров в процедуру.

Синтаксис процедуры Описание процедуры на языке ассемблера выглядит следующим образом:

<имя процедуры> PROC

<тело процедуры>

<имя процедуры> ENDP

Несмотря на то, что после имени процедуры не ставится двоеточие, это имя является меткой, обозначающей первую команду процедуры.

В языке ассемблера имена и метки, описанные в процедуре, не локализуются внутри неё, поэтому они должны быть уникальны.

Размещать процедуру в программе на языке ассемблера следует таким образом, чтобы команды процедуры выполнялись не сами по себе, а только тогда, когда происходит обращение к процедуре. Обычно процедуры размещают либо в конце секции кода после вызова функции ExitProcess, либо в самом начале секции кода, сразу после директивы .code.

Передача параметров процедуры Существуют несколько способов передачи параметров в процедуру.

Параметры можно передавать через регистры.Если процедура получает небольшое число параметров, идеальным местом для их передачи оказываются регистры. Существуют соглашения о вызовах, предполагающие передачу параметров через регистры ECX и EDX. Этот метод самый быстрый, но он удобен только для процедур с небольшим количеством параметров.

Параметры можно передавать в глобальных переменных. Параметры процедуры можно записать в глобальные переменные, к которым затем будет обращаться процедура. Однако этот метод является неэффективным, и его использование может привести к тому, что рекурсия и повторная входимость3 станут невозможными.

Параметры можно передавать в блоке параметров. Блок параметров – это участок памяти, содержащий параметры и располагающийся обычно в сегменте данных. Процедура получает адрес начала этого блока при помощи любого метода передачи параметров (в регистре, в переменной, в стеке, в коде или даже в другом блоке параметров).

Параметры можно передавать через стек. Передача параметров через стек – наиболее распространённых способ. Параметры помещаются в стек непосредственно перед вызовом процедуры.

Параметры можно передавать в потоке кода. В этом необычном методе передаваемые процедуре данные размещаются прямо в коде программы, сразу после команды CALL. Чтобы прочитать параметр, процедура должна использовать его адрес, который автоматически передаётся в стеке как адрес возврата из процедуры. Разумеется, процедура должна будет изменить адрес возврата на первый байт после конца переданных параметров перед выполнением командыRET.

40.Процедуры в языке ассемблера. Возврат результата. Локальные данные.

Передача результата процедуры Для передачи результата процедуры обычно используется регистр EAX. Этот способ используется не только в программах на языке ассемблера, но и в программах на языке С++. Объекты, имеющие размер не более 8 байт, могут передаваться через регистровую пару EDX:EAX. Вещественные числа передаются через вершину стека вещественных регистров. Если эти способы не подходят, то следует передать в качестве параметра адрес ячейки памяти, куда будет записан результат.

; Передача параметров через стек, возврат результата через регистр EAX

.686

.model flat, c

option casemap: none

include \masm32\include\windows.inc

include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

.data

a dd 76

b dd -8

c dd ?

.code

program:

push b ; Кладём параметры в стек

push a

call Procedure

add esp, 8 ; Освобождаем 8 байт стека

mov c, eax ; c = a – b

push 0

call ExitProcess

Procedure proc

mov eax, [esp + 4] ; Заносим в регистр EAX первый параметр

mov edx, [esp + 8] ; Заносим в регистр EDX второй параметр

sub eax, edx ; В регистре EAX получилась разность параметров

ret

Procedure endp

end program

; Передача параметров через стек, возврат результата по адресу

.686

.model flat, c

option casemap: none

include \masm32\include\windows.inc

include \masm32\include\kernel32.inc

includelib \masm32\lib\kernel32.lib

.data

a dd 76

b dd -8

c dd ?

.code

program:

push offset c ; Кладём в стек адрес переменной, куда будет записан результат

push b

push a

call Procedure

add esp, 8 ; Освобождаем 8 байт стека

push 0

call ExitProcess

Procedure proc

mov eax, [esp + 4] ; Заносим в регистр EAX первый параметр

mov edx, [esp + 8] ; Заносим в регистр EDX второй параметр

sub eax, edx ; В регистре EAX получилась разность параметров

mov edx, [esp + 12] ; Заносим в регистр EDX третий параметр – адрес результата

mov [edx], eax ; Записываем результат по адресу в регистре EDX

ret

Procedure endp

end program

Локальные данные процедур Процедуры часто нуждаются в локальных данных. Локальные переменные размещаются в стеке. Для того чтобы отвести место под локальные переменные в процедуре на языке ассемблера, достаточно просто вычесть из регистра ESP размер требуемой памяти. После этого все вызываемые процедуры будут «знать», что место в стеке занято, и размещать свои данные в незанятой части стека.

При вызове других процедур, а также в ходе выполнения текущей процедуры в стек могут быть положены другие данные. При этом значение регистра ESP изменится. Поэтому регистр ESP не является надёжной точкой отсчёта для адресов локальных переменных. Для того чтобы получить такую точку отсчёта, значение регистра ESP переписывают в регистр EBP, предварительно сохранив значение регистра EBP в стеке. В этом случае регистр EBP отмечает часть стека, занятую на момент начала работы процедуры (отсюда происходит название регистра EBP – указатель базы кадра стека). При таком подходе первый параметр процедуры всегда находится по адресу [EBP + 8]. Адреса локальных переменных отсчитываются от регистра EBP с отрицательным смещением. По окончании работы процедуры значение регистра ESP восстанавливается по регистру EBP, а значение регистра EBP – из стека.

P rocedure proc

var_104 = byte ptr -104h

var_4 = dword ptr -4

arg_0 = dword ptr 8

arg_4 = dword ptr 0ch

push ebp

mov ebp, esp

sub esp, 104h

mov edx, [ebp + arg_0]

mov eax, [ebp + arg_4]

push ebx

push esi

push edi

...

pop edi

pop esi

pop ebx

mov esp, ebp

pop ebp

ret

Procedure endp