Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
12. Модульное программирование на ассемблере. С...doc
Скачиваний:
2
Добавлен:
01.07.2025
Размер:
947 Кб
Скачать
☆
      1. Передача параметров через таблицу адресов

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

Пример 1.4. Написать программу, подсчитывающую сумму элементов одномерного массива. Массив и его размер определяются в основной программе, суммирование элементов выполняет процедура. Результат сложения возвращается в основную программу. Данные передаем через таблицу адресов (см. рисунок 1.4).

; Template for console application

.586

.MODEL flat, stdcall

OPTION CASEMAP:NONE

Include kernel32.inc

Include masm32.inc

IncludeLib kernel32.lib

IncludeLib masm32.lib

.CONST

MsgExit DB "Press Enter to Exit",0AH,0DH,0

.DATA

ary SWORD 5,6,1,7,3,4 ; массив

count DWORD 6 ; размер массива

.DATA?

inbuf DB 100 DUP (?)

sum SWORD ? ; сумма элементов

tabl DWORD 3 dup(?) ; таблица адресов параметров

EXTERN masculc:near

.CODE

Start:

;

Рисунок 1.4 – Таблица

адресов параметров

формирование таблицы адресов параметров

mov tabl,offset ary

mov tabl+4,offset count

mov tabl+8,offset sum

mov EBX,offset tabl

call masculc

XOR EAX,EAX

Invoke StdOut,ADDR MsgExit

Invoke StdIn,ADDR inbuf,LengthOf inbuf

Invoke ExitProcess,0

End Start

Текст процедуры:

; Template for console application

.586

.MODEL flat, stdcall

OPTION CASEMAP:NONE

.CODE

masculc proc c

push AX ; сохранение регистров

push ECX

push EDI

push ESI

; использование таблицы адресов параметров

mov ESI,[EBX]

mov EDI,[EBX+4]

mov ECX,[EDI]

mov EDI,[EBX+8]

xor AX,AX

; суммирование элементов массива

cycl: add AX,[ESI]

add ESI,2

loop cycl

; формирование результатов

mov [EDI],AX

pop ESI ; восстановление регистров

pop EDI

pop ECX

pop AX

ret

masculc endp

END

      1. Передача параметров в стеке

Наиболее распространенным способом передачи данных в практике программирования принято считать передачу параметров в стеке. Именно этот способ используют языки высокого уровня. Параметры помещают в стек командой PUSH, после чего управление передается вызываемой процедуре. Доступ к параметрам в стеке из вызываемой процедуры осуществляют через регистр EBP, в который помещают адрес вершины стека, хранящийся в регистре указателя стека ESP. Для обеспечения корректного возврата в вызывающую процедуру старое значение регистра EBP помещают в стек первой командой процедуры. Параметры в стеке, адрес возврата и старое значение EBP вместе называют фреймом активации процедуры. Вызываемая процедура, зная структуру стека, извлекает параметры в соответствующие регистры, выполняет над ними операции и записывает результат, используя адрес, переданный в стеке.

Примечание – Следует помнить, что в стек можно поместить 2 или 4 байта. Если в стек надо поместить параметр размером 1 байт, то помещают 2 байта, но байт со старшим адресом не используется.

Пример 1.5. Программа суммирования элементов массива. Программа использует 3 параметра: два исходных и результат. Для первого параметра – массива в стек помещается адрес начала массива, второй параметр – адрес счетчика, содержащего количество элементов. В качестве третьего параметра в стек помещается адрес результата, куда процедура поместит полученное значение (см. рисунок 1.5).

; Template for console application

.586

.MODEL flat, stdcall

OPTION CASEMAP:NONE

Include kernel32.inc

Include masm32.inc

IncludeLib kernel32.lib

IncludeLib masm32.lib

.CONST

MsgExit DB "Press Enter to Exit",0AH,0DH,0

.DATA

ary SWORD 5,6,1,7,3,4 ; элементы массива

count DWORD 6 ; размер массива

.DATA?

inbuf DB 100 DUP (?)

sum SWORD ? ; сумма элементов

EXTERN masculc:near

.CODE

S tart:

; запись параметров в стек

push offset ary

push offset count

push offset sum

; вызов процедуры

Рисунок 1.5 – Состояние стека во время работы процедуры masculc

call masculc

XOR EAX,EAX

Invoke StdOut, ADDR MsgExit

Invoke StdIn,ADDR inbuf,LengthOf inbuf

Invoke ExitProcess,0

End Start

Модуль вычисления суммы элементов массива:

.586

.MODEL flat, stdcall

OPTION CASEMAP:NONE

.CODE

masculc proc c

push EBP ; сохранение регистра ebp

mov EBP,ESP ; запись в ebp адреса вершины стека

push AX

push ECX

push EDI

push ESI

; Извлечение параметров из стека

mov ESI,[EBP+16] ; адрес массива

mov EDI,[EBP+12] ; адрес количества элементов

mov ECX,[EDI] ; количество элементов

mov EDI,[EBP+8] ; адрес результата

xor AX,AX ; очистка регистра AX

cycl: add AX,[ESI]

add ESI,2

loop cycl

mov [EDI],AX ; сохранение результата

pop ESI

pop EDI

pop ECX

pop AX

pop EBP ; восстановление регистра еbp

ret 12 ; удаление параметров из стека

masculc ENDP

END

При передаче параметров через стек возникает два вопроса:

– в каком порядке записывать параметры в стек;

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

В обоих вариантах есть свои плюсы и минусы. Например, если стек освобождает вызываемая процедура по команде RET <Число байт>, то код программы получается более коротким. Если за освобождение стека отвечает вызывающая программа, то становится возможным вызов нескольких процедур с одними и теми же значениями параметров просто последовательными командами CALL. Первый способ более строгий, он используется в языке Pascal. Второй, дающий больше возможностей для оптимизации, – в языках C и C++. Вопрос о порядке записи параметров в стек для ассемблера не столь важен, так как и записывают и извлекают параметры подпрограммы на ассемблере. Главное – чтобы этот вопрос был между ними согласован. А вот при взаимодействии ассемблера с языками высокого уровня, следует знать особенности передачи параметров этих языков.