Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Lektsia_12-14_2011_protsedury_SRC_slaydy.doc
Скачиваний:
9
Добавлен:
21.12.2018
Размер:
1 Mб
Скачать

1) Согласование имен,

2) Согласование параметров,

3) Согласование вызовов.

Согласование вызовов.

В ОС MS DOS вызываемая процедура могла находиться:

1) в том же сегменте, что и команда вызова, тогда вызов называется близким (NEAR) или внутрисегментным. Адрес возврата состоит из 2 байт;

2) в другом сегменте, тогда вызов назывался дальним (FAR) или межсегментным. Адрес возврата состоит из 4 байт.

Возврат из процедуры мог быть либо:

1) близким (RETN), адрес возврата формировался на основе двух байт, взятых из стека;

2) дальним (RETF), адрес формировался на основе четырех байт, взятых из стека.

Вызов и возврат должны быть согласованы друг с другом. В рамках единой программы это не вызывает больших проблем. Но при работе с двумя модулями могут возникнуть трудности.

Например: если в объектном модуле возврат осуществляется по RETN, то необходимо компоновать объектные модули так, чтобы сегмент, где находится процедура, был объединен с сегментом, откуда осуществляется вызов. Вызов в этом случае должен быть близким.

Если же возврат из процедуры осуществлялся по команде RETF, то и вызов этой процедуры должен быть дальним. При этом при компоновке вызов и сама процедура должны были попасть в разные сегменты.

С этим были связаны и так называемые модели памяти в языке Си.

При переходе к Windows (плоская модель памяти) все вызовы по типу являются близкими, т.е. осуществляющимися в рамках одного огромного сегмента. Тем самым была снята проблема согласования вызовов.

Согласование имен.

1) Транслятор MASM добавляет в конце имени процедуры @N, где N количество передаваемых в стек параметров. То же делает и компилятор Visual C++. Т.о. трудности возникают уже при согласовании двух ассемблерных модулей. ТASM является более гибким компилятором, так как в конце любого имени можно добавить @N, тем самым согласовав имена.

2) Подчеркивание перед именем. Транслятор MASM генерирует подчеркивание автоматически, если в начале программы устанавливается тип вызова stdcall (Standard Call, т.е. стандартный вызов). Транслятор TASM этого не делает, то есть, при необходимости это нужно делать в тексте программы, что является положительным моментом. Между фирмами Borland и Microsoft в этом вопросе полное разночтение.

4) Согласование заглавных и прописных букв. При трансляции с помощью TASM мы используем ключ /ml для того, чтобы различать буквы прописные и заглавные. Транслятор MASM делает это автоматически. В стандарте языка Си с самого начала предполагалось различие между заглавными и прописными буквами. В Паскале же прописные и заглавные буквы не различаются.

5) Уточняющие имена в Си++. В Си++ возможна так называемая перегрузка. Это значит, что одно и тоже имя может относиться к разным функциям. В тексте программы эти функции отличаются друг от друга по количеству и типу параметров и типу возвращаемого значения. Поэтому компилятор Си++ автоматически делает в конце имени добавку - так, чтобы разные по смыслу функции различались при компоновке. Фирмы Borland и Microsoft тут не пожелали согласовать свои позиции и делают в конце имени совершенно разные добавки. Обойти эту проблему не так сложно, нужно использовать модификатор EXTERN "С".

Согласование параметров

В таблице ниже представлены основные соглашения по передаче параметров в процедуру.

Ранее во всех ассемблерных программах указывался тип передачи параметров как stdcall. Однако, это никак и нигде не использовалось - так как передача и извлечение параметров делалась явно, без помощи транслятора.

Когда происходит взаимодействие ассемблерного модуля с языками высокого уровня, это необходимо учитывать и знать, как работают те или иные соглашения.

Таблица, представляющая соглашения о вызовах

Соглашение

Параметры

Очистка стека

Регистры

Pascal (конвенция языка Паскаль)

Слева направо

Процедура

Нет

Register (быстрый или регистровый вызов)

Слева направо

Процедура

Задействованы три регистра (EAX,EDX,ECX), далее стек

Cdecl (конвенция С)

Справа налево

Вызывающая программа

Нет

Stdcall (стандартный вызов)

Справа налево

Процедура

Нет

Тип возвращаемых функцией данных

В ассемблерном модуле в регистре EAX возвращается значение, которое может быть либо числом, либо указателем на некую переменную или структуру. Если возвращаемое число типа WORD, то оно содержится в младшем слове регистра EAX.

Встроенный ассемблер

Встроенные ассемблеры часто несколько отстают от обычных ассемблеров в части поддержки новых команд микропроцессоров. Это вполне объяснимо, так как разработка новой версии пакета, скажем C++ Builder, требует гораздо больше времени, чем пакета TASM.

Ассемблерные вставки (inline-ассемблер) используются в двух случаях:

  1. Если нужно оптимизировать критичные по скорости и небольшие по объему участки программы. Грамотно написанный ассемблерный код всегда быстрее кода, который генерируется компилятором С++ или Delphi.

  2. Нужен прямой доступ к памяти и портам. Чаще всего используется в драйверах, так как из третьего кольца защиты с портами не очень-то поработаешь.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]