|
Взаимосвязь языков C и ассемблера |
|
МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ЭКОНОМИКИ, СТАТИСТИКИ И ИНФОРМАТИКИ
КАФЕДРА МО ЭВМ
КУРСОВАЯ РАБОТА
на тему : “Взаимосвязь языков С и ассемблера”
Студент: Аплемах А.В.
Группа: ДП-202
Руководитель проекта:
Комлева Н.В.
Защищена “___” Мая 1997 г.
Москва 1997г.
СОДЕРЖАНИЕ
Введение3Раздел 1: Регистры и параметры51.1 Использование регистров51.2 Ассемблерные операторы Inline51.3 Размещение данных и операторов в программе6Раздел 2: Особенности данных72.1 Разделение данных72.2 Объявление ассемблерных данных72.3 Разделение кода8Раздел 3: Вызов ассемблерных функций из С93.1 Символы подчеркивания 93.2 Использование дальних данных93.3 Вызов ассемблерных функций из С103.4 Ассемблирование и компоновка внешних модулей11Раздел 4: Вызов функций С из ассемблера154.1 Вызов С и С++ из ассемблера154.2 Локальные переменные174.3 Передача аргументов18Раздел 5: Курсовая программа205.1 Постановка задачи205.2 Блоксхема программы205.3 Модуль на С++205.4 Модуль на ассемблере215.5 Анализ проведенной работы23Список использованной литературы24
Введение
В идеальном мире программирования компиляторы с языков высокого уровня должны генерировать самый быстрый, самый компактный и наилучший машинный код для любой программы. Если бы это было невозможно, то программирование много бы потеряло от этого, и наверняка не писался бы этот курсовик. Но это невозможно. Несмотря на множество усовершенствований при разработке компиляторов, ни один язык высокого уровня пока не в состоянии продублировать краткий, быстрый и изящный код, написанный опытным специалистом по ассемблеру.
В чем же дело? А в том, что компиляторы обобщают решаемые ими задачи. В C++ существует только один способ написания цикла FOR. В то же время с помощью ассемблера этот цикл можно организовать с помощью ассемблера этот цикл можно организовать десятками способов. Чтобы компилятор выбирал идеально подходящие в каждой конкретной ситуации методы реализации алгоритма и при этом учитывая их влияние на остальные части программы - он должен обладать интеллектом гения, вкусом художника и интуицией предсказателя. Сегодняшние компиляторы с языков высокого уровня достаточно сообразительны, но не до такой степени.
Среди всех существующих компиляторов С наиболее приблизился к идеалу С++. Порождаемый им машинный код работает достаточно быстро, занимает на диске немного места и в большинстве случаев может использоваться без каких-либо модификаций. Однако несмотря на все достоинства С++, все равно остается место для улучшений, благодаря чему даже небольшие участки программы, переписанные на ассемблере, могут значительно повысить скорость работы программы и уменьшить размер исполняемого файла. Кроме того, добавив ассемблер к С++, можно облегчить доступ к регистрам аппаратных средств и решение других задач низкого уровня, таких как запись символов непосредственно в видеопамять.
Во многих случаях единственный способ для прибавления программе скорости - немного дополнить совершенный “С”, используя один из двух методов:
· Использование встроенных операторов (операторов Inline)
· Использование внешних функций
Операторы Inline вставляют язык ассемблера непосредственно в исходную программу на С и С++. Эта методика быстрая и простая, но имеет несколько недостатков, которые поясняться ниже. Внешние функции, хотя их и трудно использовать, чем операторы Inline, имеют то преимущество, что позволяют наиболее полно использовать
все возможности Turbo Assembler.
Раздел 1: Регистры и параметры
1.1 Использование регистров
В создаваемых ассемблерных программах можно использовать все регистры процессора. Но чтобы предотвратить путаницу с функциями С и С++, необходимо восстанавливать bp, cs, sp и ss, которые они имели до запуска созданной подпрограммы. Тогда можно быть совершенно уверенным, что обращение к другим функциям не изменит эти регистры. Также нельзя забывать, что С использует регистры si и di для регистровых переменных, поэтому при использовании встроенного ассемблера замедляется общая работа программы.
К регистрам ax, bx, cx, dx и es можно обращаться свободно и не нужно резервировать их значения до окончания подпрограммы. Эта свобода касается и других функций, поэтому надо помнить, что эти регистры изменяться, если вызываются функции С и С++ из ассемблерных подпрограмм.
1.2 Ассемблерные операторы Inline
Ассемблерные операторы inline начинаются словом asm, за которым следует инструкция и ее операнды. Например, чтобы синхронизировать программу с внешним сигналом прерывания, можно написать:
/* ожидание прерывания*/
asm sti
asm hlt
printf(“Прерывание получено\n”)
Когда ранние версии Turbo C компилируют программу со встроенными командами asm, компилятор сперва создает ассемблерный текст для всей программы, вставляя в текст наши ассемблерные инструкции вместе с откомпилированным кодом для остальных операторов С. Затем компилятор вызывает Turbo Assembler и Linker (компоновщик), чтобы провести ассемблирование и подключить программу к конечному файлу кода. Более поздние версии Turbo и Borland C++ могут компилировать операторы asm без вызова TASM. Полный синтаксис asm:
asm[метка] мнемоника/директива операнды [;] [/*С комментарий*/]
Точки с запятыми в конце строк asm и комментарии С, расположенные между /*и*/ удаляются из текста перед ассемблированием, поэтому их можно опускать в тексте программы.
1.3 Размещение данных и операторов в тексте программы
Каждая строка текста программы С и С++ находится либо внутри, либо снаружи функции, и операторы asm могут вставляться как в одном, так и в другом месте. Конкретное положение оператора asm влияет на то, куда ассемблируется код или директива. Если оператор asm появляется снаружи функции, то он ассемблируется в сегмент данных программы, если внутри функции - в кодовый сегмент. Обычно, чтобы создать переменные, операторы asm вставляются снаружи функций; для создания кода их следует вставлять внутрь функций. Например:
asm count db ?
int main()
{
asm shl [count], 1/*умножение count на 4*/
asm shl [count], 1
return 0;
}
Переменная count объявляется в сегменте данных программы (относительно ds). Операторы внутри функции main умножают count на 4, используя вместо mul быстрые инструкции сдвига shl. Если объявлять переменные внутри функции, данные ассемблируются в кодовый сегмент, требуя особого обхождения:
int main()
{
asm jmp OverThere
asm count db ?
OverThere:
asm shl [count], 1 /* умножение count на 4*/
asm shl [count], 1
return 0;
}
Поскольку теперь переменная count находится в кодовом сегменте, требуется инструкция jmp, чтобы избежать случайного восприятия значения count в качестве машинного кода и его исполнения.
Раздел 2: Особенности данных
2.1 Разделение данных
Inline операторы asm имеют свободный доступ к переменным и структурам С и C++ - одно из самых привлекательных преимуществ метода inline
1 2 3 4 ... последняя
|
|
|
|
На сайте: |
, ,
|