Интерфейс языка СИ с языком Ассемблер

Программирование со смешением языков. Методы программирования, необходимые для написания процедур на Ассемблере, пригодных для использования в СИ-программах. Написание ассемблерной процедуры. Резервирование значений регистров. Доступ к параметрам.

Рубрика Программирование, компьютеры и кибернетика
Вид контрольная работа
Язык русский
Дата добавления 29.07.2012
Размер файла 374,6 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Интерфейс языка СИ с языком Ассемблер

1. Смешанное программирование

смешение ассемблер язык процедура

Программирование со смешением языков - это процесс создания программ, использующих два или более исходных языка. Данное средство позволит вам использовать уникальные возможности языков BASIC, C, FORTRAN, Pascal и Macro Assembler (MASM) фирмы Microsoft. Любой из этих языков (в их последних версиях) может вызывать любой другой.

Фактически, все процедуры каждой из данных языковых библиотек доступны для программ со смешением языков. Например, смешанное программирование поможет вам эффективно использовать Макро Ассемблер (MASM). Вы можете быстро разработать большинство ваших программ с помощью Microsoft C или FORTRAN, а затем использовать MASM для тех нескольких процедур, которые часто выполняются и должны работать с большой скоростью.

Смешанное программирование, кроме того, облегчает переход от одного языка к другому. Например, вы можете иметь большую программу на языке FORTRAN, а затем конвертировать ее в СИ.

Вы можете заменить ваши процедуры на языке FORTRAN один к одному на соответствующие СИ-функции. СИ-код будет сгенерирован, как только каждая функция будет написана.

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

Подробно смешанное программирование для всех остальных языков описано в документе «Microsoft Mixed-Language Programming Guide». Данное руководство содержит описание смешанного программирования для языков Microsoft FORTRAN (версия 4.0 и выше), Microsoft Macro Assembler (Версия 5.0 и выше), Microsoft Pascal (Версия 3.3 и выше), Microsoft C (версия 5.0 и выше).

Данное же приложение в основном касается методов программирования необходимых для написания процедур на Ассемблере, пригодных для использования в СИ-программах. Подробности об интерфейсах между другими языками высокого уровня смотрите в документе «Microsoft Mixed-Language Programming Guide» («Руководство по программированию со смешением языков фирмы Microsoft»).

2. Определения

Терминологические соглашения, используемые в данном приложении совпадают с соглашениями, описанными в руководстве пользователя для каждого языка фирмы Microsoft. Однако, следующие термины используются в особом смысле:

3. Написание ассемблерной процедуры

Высокоуровневые языки фирмы Microsoft используют для процедурных вызовов приблизительно один и тот же интерфейс. Данный раздел описывает интерфейс, позволяющий вам вызывать ассемблерную процедуру с помощью тех же самых методов, которые вы применяли для кода, сгенерированного компиляторами фирмы Microsoft. Процедуры, написанные с помощью данных методов, могут вызываться рекурсивно и могут быть эффективно использоваться со средством Stack Trace многооконного отладчика Code View фирмы Microsoft. Стандартный метод получения интерфейса с языком Ассемблер состоит из следующих шагов:

1. Создание процедуры.

2. Ввод процедуры.

3. Размещение локальных данных (необязательно).

4. Резервирование значений регистров.

5. Параметры доступа.

6. Возвращение значения (необязательно).

7. Выход из процедуры.

1.1. Написание процедуры.

Компоновщик не сможет объединить ассемблерную процедуру с вызывающей процедурой, если используются несовместимые сегменты, либо сама процедура описана неправильно. Могут оказаться полезными следующие положения:

- Если вы имеете Macro Assembler версии 5.0, в начале исходного файла используйте директиву MODEL. Данная директива автоматически генерирует соответствующий тип возвращаемого значения («near» для малой или компактной модели, «far» - в противном случае). Если у вас более ранняя версия ассемблера, опишите процедуру с атрибутом «far» (либо «near», если вызывающая программа работает в малой или компактной модели Quick-C).

- Если у вас Microsoft Macro Assembler версии 5.0 или выше, для объявления кодового сегмента используйте упрощенную директиву CODE и директиву DATA для объявления сегмента данных. (Если у вас нет объявлений данных, достаточно только кодового сегмента). Если вы используете более раннюю версию ассемблера, рассмотрите директивы SEGMENT, GROUP и ASSUME в Разделе С. 4 «Сегментная модель фирмы Microsoft».

- Метка процедуры должна быть объявлена, как «public» с помощью директивы PUBLIC. Данное объявление делает процедуру доступной для вызовов из других модулей. Кроме того, любые данные, которые вы хотите сделать доступными для других модулей, должны быть объявлены, как PUBLIC.

- Глобальные данные или процедуры, к которым осуществляется доступ из вашей процедуры, должны быть объявлены, как EXTRN. Наиболее безопасный путь использования EXTRN-это помещение директивы вне сегментоного определения (тем не менее, «ближние» д

Вход в процедуру.

Процедура начинается с двух инструкций:

push bp

mov bp, sp

Данная последовательность команд устанавливает регистр BP, как указатель на запись активации. Данный указатель используется для доступа к параметрам и локальным данным, расположенным в стеке. Регистр SP не может быть использован для данной цели, поскольку он не является индексным или базовым регистром. Кроме того, значение регистра SP может изменяться при добавлении данных в стек. Значение же регистра BP остается постоянным на протяжении всей процедуры, соответственно, каждый параметр может быть адресован, как фиксированное смещение, относительно значения BP.

Последовательность инструкций, приведенная выше, сначала сохраняет значение BP, поскольку оно потребуется вызывающей процедуре, как только закончится текущая процедура. Затем в регистр BP заносится значение SP, чтобы иметь значение указателя стека перед входом в процедуру.

Размещение локальных данных (необязательно).

Ассемблерная процедура использует для размещения локальных данных те же самые средства, что и высокоуровневые языки. Чтобы установить размеры памяти для размещения локальных данных, просто уменьшите содержимое регистра SP в третьей инструкции процедуры. (Для гарантии корректного выполнения вам следует всегда увеличивать или уменьшать содержимое SP на четное число). Уменьшение содержимого регистра SP резервирует пространство стека для локальных данных. Данная память должна быть в конце процедуры восстановлена.

В следующих инструкциях, «space» - это общий размер байтов локальных данных. Доступ к локальным переменным осуществляется посредством фиксированных отрицательных смещений BP.

Приведенный выше пример использует две локальные переменные, каждая из которых имеет размер 2 байта. SP уменьшается на четыре, поскольку для локальных данных требуется четыре байта. Позже, каждая из данных переменных инициализируется 0. Данные переменные никогда не объявляются формально какой-либо директивой ассемблера; программист должен отслеживать их самостоятельно

Локальные переменные называются также динамическими, стековыми или автоматическими переменные.

Резервирование значений регистров.

Ассемблерные процедуры, вызываемые из любого высокоуровнего языка фирмы Microsoft должны зарезервировать значение регистров SI, DI, SS и DS (в дополнение к регистру BP, который уже был сохранен). То есть, следует сохранить содержимое тех регистров, которые программа может изменить. Если программа не изменяет содержимое какого-либо регистра, этот регистр нет нужды запоминать.

Те регистры, которые вы запомнили перед входом в процедуру, следует затем восстановить перед выходом из процедуры (как объясняется в Разделе 1.7 «Выход из процедуры»).

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

Доступ к параметрам.

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

Запись активации процедуры устанавливается следующей последовательностью действий:

1. Вызывающая программа помещает каждый параметр в стек, после чего регистр SP указывает на последний размещенный параметр.

2. Вызывающая программа инициирует инструкцию CALL, которая устанавливает адрес возврата (место в вызывающей программе, на которое возвращается управление после окончания работы процедуры) и помещает его в стек. Данный адрес может быть либо дыа байта длинной (для «ближних» вызовов), либо четыре байта длинной (для «дальних» вызовов). Теперь регистр SP указывает на данный адрес.

3. Первая инструкция вызванной процедуры сохраняет старое значение BP (push bp). Регистр SP теперь указывает на сохраненную копию BP. 4. Используйте регистр BP для захвата текущего значения регистра SP с помощью инструкции mov bp, sp. Теперь BP указывает на старое значение BP.

5. Поскольку BP остается постоянным на протяжении всей процедуры, SP может быть уменьшено для того, чтобы освободить место в стеке для локальных данных или зарезервированных регистров.

В основном, смещение (относительно BP) для параметра X равно: 2 + размер адреса возврата

+ общий размер параметров между X и BP.

Например, предположим, что процедура FAR получает один параметр, двухбайтовый адрес. Смещение для этого параметра будет равно: смещение аргумента = 2 + размер адреса возврата

= 2 + 4

= 6

Аргумент может в таком случае быть загружен в регистр BP с помощью следующей инструкции:

mov bx, [bp+6]

Если вы однажды определили смещение для каждого параметра, вам могут понадобиться строковые уравнения или структуры, чтобы к параметру в вашем исходном ассемблерном коде можно было обратиться по единственному идентифицирующему имени. Например, к параметру, находящемуся по адресу BP+6 будет удобно обращаться, если в начале исходного ассемблерного файла вы поместите следующий оператор:

Arg1 EQU [bp+6]

После этого в любой инструкции на данный параметр можно ссылаться по идентификатору Arg1. Используйте это средство в качестве полезного дополнения.

Примечание:

Высокоуровневые языки фирмы Microsoft всегда размещают адреса сегментов перед адресами смещений. Поэтому, если в стек опускаются аргументы больше 2-х байтов, старшие слова всегда опускаются перед младшим словом.

Возврат значений (необязательно).

Высокоуровневые языки Microsoft для получения возвращаемых значений пользуются аналогичными соглашениями. Данные соглашения совпадают, если возвращаемый тип данных не является сложным (например массивом или структурой) и имеет длину не более четырех байтов. Это включает в себя все «ближнии» и «дальние» адреса (то есть все указатели и все параметры, передаваемые по ссылке).

Если возвращаемое значение больше четырех байтов, процедура вызываемая из языка СИ, должна отвести память для возвращаемого значения, а затем поместить этот адрес в DX:AX. Удобным способом распределения памяти для возвращаемого значения является простое объявление его в сегменте данных.

Выход из процедуры.

При завершении процедуры должны быть выполнены следующие шаги: 1. Если какие-либо из регистров SS, DS, SI и DI были сохранены, перед выходом из процедуры они должны быть извлечены из стека в порядке, обратном их размещению.

2. Если локальные данные размещены в начале процедуры, регистр SP должен быть восстановлен с помощью инструкции mov sp, bp.

3. Восстановите регистр BP с помощью pop bp. Данный шаг всегда необходим.

4. Наконец, вернитесь в вызывающую программу с помощью ret. Вызывающий модуль на языке СИ автоматически отрегулирует стек по отношению к параметрам, которые были опущены при вызове.

- Примеры:

Приведенный выше пример показывает простейшую последовательность выхода. Никакие регистры не были зарезервированы, не были размещены локальные данные, и использованы соглашения о связях языка СИ.

В данном примере показана последовательность выхода для процедуры, которая предварительно зарезервировала значения регистров SI и DI, разместила локальные данные и использовала соглашения о связях не относящиеся к языку СИ. Поэтому, процедура должна использовать инструкцию ret 6, чтобы восстановить 6 байтов, занятых параметрами в стеке.

4. Вызов процедур на языке Ассемблер из языка СИ

Программа на языке СИ может вызвать процедуру на языке Ассемблер, находящуюся в другом модуле, как и при вызове СИ-функции. В дополнение к шагам, описанным в Разделе1 «Написание процедуры на языке Ассемблер», могут оказаться полезными следующие правила:

1. Описывайте процедуры, вызываемые из СИ-программ с ключевым словом far, если СИ-модуль был скомпилирован в большой, сверхбольшой или средней модели памяти, и с ключевым словом near, если СИ-модуль был скомпилирован в малой или компактной модели. Ключевые слова far или near отменяют любые стандартные назначения. Если вы используете директиву MODEL, имеющуюся в Micro soft Macro Assembler версии 5.0, объявление модели памяти для процедуры делается явно.

2. Обзор соглашений о связях языка СИ. По соглашениям языка СИ параметры опускаются в стек в том порядке, в каком они находятся в исходном коде. Например, вызов функции СИ calc (a, b); опускает b в стек раньше a. В противоположность остальным высокоуровневым языкам, в соглашениях о связях языка СИ положено, чтобы вызывающая процедура всегда восстанавливала стэк непосредственно после возвращения управления из вызываемой программы. Соглашения о связях языка СИ делают возможным вызов переменным числом параметров. (Поскольку первый параметр всегда опускается в стек последним, он имеет относительно указателя на запись активации один и тот же адрес. Независимо от количества переданных числом параметров применяются следующие этапы:

а) Возврат производится посредством простой инструкцией ret. Не восстанавливайте стек посредством инструкции ret size, поскольку вызывающая СИ-процедура сама восстановит стек, как только ей будет передано управление.

б) Параметры помещаются в стек в порядке, обратном тому, как они появлялись в исходном коде на языке СИ. Первый параметр будет находиться по младшим адресам памяти (поскольку-это последний помещаемый в стэк параметр, то есть стэк растет вниз).

с) Стандартно, параметры языка СИ передаются значением, исключая массивы, передаваемые по адресной ссылке.

5. Обзор соглашений о наименованиях языка СИ

Наличие подчеркивания перед любым именем в языке СИ делает его глобальным. В языке СИ распознаются только первые восемь символов, поэтому не делайте имена, используемые СИ, длинной более восьми символов. Кроме того, если вы будете выполнять компановку с опцией /NOIGNORECASE, помните, что язык СИ чувствителен к буквенным регистрам, и не преобразуйте имена к верхнему регистру.

В следующем примере программа на языке СИ вызывает ассемблерную процедуру, которая вычисляет А*2**B, где А и В-первый и второй параметры, соответственно. Вычисления выполняются путем сдвига влево разрядов в А В раз.

Программа на языке СИ использует для создания интерфейса с ассемблерной процедурой описание extern. Не требуется никаких ключевых слов, поскольку ассемблерная процедура будет использовать соглашения о связях языка СИ.

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

Адрес возврата имеет в длину байта, предполагая, что СИ-модуль был скомпилирован в малой или компактной модели. Если же СИ-модуль компилируется в большой, сверхбольшой или средней модели, то адреса Arg<-1 и Arg<-2-каждый увеличиваются на 2 байта, то есть, соответственно становятся BP+6 и BP+8, поскольку адрес возврата здесь 4 байта длиной. Первый параметр Arg<-1 расположен по адресам более младшим, чем Arg<-2, поскольку язык СИ опускает аргументы в стек в обратном порядке. Каждый аргумент передается значением. Ассемблерная процедура может быть написана следующим образом:

Приведенный выше пример предполагает, что СИ-модуль компилируется в малой модели памяти. Смещение параметра и директива MODEL изменятся для других моделей памяти.

Обратите внимание, что инструкция ret используется без переменной size, поскольку вызывающая программа после возвращения из процедуры сама выравнивает стек.

6. Вызов языка СИ из языка Ассемблер

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

Для вызова высокоуровневых языков из языка Ассемблер вам следует соблюдать следующие правила:

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

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

- Выполняйте вызов. Вызов должен быть «дальним», если только высокоуровневая процедура не относится к малой модели памяти.

- Если процедура использовала соглашения о связях языка СИ, то непосредственно сразу после вызова очистите стек от параметров с помощью инструкции: add sp, size, где size-это общий размер в байтах всех параметров, опущенных в стек.

7. Сегментная модель фирмы Microsoft

Если вы применяете простейшие сегментные директивы, вам не потребуется знать имена, назначенные каждому сегменту. Однако, версии Macro Assembler предшествующие версии 5.0 не поддерживают данные директивы. В старших версиях ассемблера вам следует использовать директивы SEGMENT, GROUP, ASSUME, ENDS, эквивалентные упрощенным сегментным директивам.

В Таблице С. 1 показаны стандартные имена сегментов, создаваемые каждой директивой. Использование данных сегментов гарантирует совместимость с языками фирмы Microsoft и поможет вам получить доступ к внешним именам.

Размещено на Allbest.ru


Подобные документы

  • Ассемблер как символический аналог машинного языка. Архитектура микропроцессора: организация памяти, способы адресации операндов, правила использования регистров. Текст программы. Этапы программирования на ассемблере, алгоритмы выполнения задач.

    контрольная работа [515,1 K], добавлен 20.01.2016

  • Изучение некоторых аспектов языка Ассемблера и ЭВМ в целом. Построение алгоритмов решения поставленной задачи на языках программирования Си, Ассемблер УМ и IBM PC. Составление блок-схем решений и написание программ на каждом из перечисленных языков.

    курсовая работа [691,5 K], добавлен 20.10.2014

  • Команды, необходимые для организации разветвлений и циклических структур в программах, условных переходов, изменения признака переноса, изменения содержимого аккумулятора. Логические команды над аккумулятором и регистром. Программа на ассемблере.

    лабораторная работа [25,2 K], добавлен 03.03.2009

  • Рассмотрение общих сведений и уровней языков программирования. Ознакомление с историей развития, использования языков программирования. Обзор достоинств и недостатков таких языков как Ассемблер, Паскаль, Си, Си++, Фортран, Кобол, Бейсик, SQL, HTML, Java.

    курсовая работа [759,5 K], добавлен 04.11.2014

  • Моделирование цифровых узлов комбинационного и последовательностного типа electronic work bench. Основы программирования на Ассемблере: арифметические команды, манипуляции над битами, строковые операции. Программирование с использованием пакета MASM.

    отчет по практике [1,9 M], добавлен 10.01.2015

  • Характеристика языков программирования: краткая история, хронология. Основные виды языков программирования: ассемблер; бейсик. Создание и использование формул в Excel. Применение операторов в формулах. Использование функций в Excel. Сайт дома отдыха.

    отчет по практике [139,1 K], добавлен 03.06.2011

  • Характеристики и свойства языков программирования. Исследование эволюции объектно-ориентированных языков программирования. Построение эволюционной карты механизмов ООП. Разработка концептуальной модели функционирования пользовательского интерфейса.

    курсовая работа [2,6 M], добавлен 17.11.2014

  • Исследование возможностей и областей использования языка программирования JavaScript. Сравнительный анализ языков программирования JavaScript и PHP. Разработка интерактивного Web-приложения на примере теста по теме "Программирование на языке Delphi".

    практическая работа [26,0 K], добавлен 04.02.2015

  • Машинные коды и ассемблер. Первые языки программирования высокого уровня. Язык программирования FORTRAN. Достоинства и недостатки ALGOL. Научные и бухгалтерские программы. Основные принципы, которые соблюдались при создании языка программирования Basic.

    курсовая работа [407,4 K], добавлен 21.06.2014

  • Эволюция языков программирования от низкого уровня до современности. Языки программирования второго поколения - ассемблер. Императивные, функциональные, логические и объектно-ориентированные языки. Машинная независимость. Парадигмы программирования.

    презентация [353,5 K], добавлен 14.10.2013

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.