46019 (665326), страница 36

Файл №665326 46019 (Turbo C++ Programer`s guide) 36 страница46019 (665326) страница 362016-07-31СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 36)

И наконец, getmodename и getdrivername возвращаютимя заданного режима драйвера и имя текущего графического драйвера, соответственно.

Глава 6

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

В данной главе рассказывается, как написать ассемблерный код, который будет хорошо работать с Turbo C++. Предполагается, что вы знаете, как пишутсяподпрограммы на языке ассемблера икак определяются сегменты, константы данных и т. д. Если вы не знакомы с этими концепциями, почитайте руководство по Turbo Assembler, особенно главу "Интерфейс Turbo Assembler с Turbo C" в Руководстве пользователя. TurboAssembler версии 2.0включает несколько средств, делающих интерфейс с Turbo C++ более простым и прозрачным для программиста.

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

Turbo C++ упрощает вызов из С-программ подпрограмм, написанных на языке ассемблера, и наоборот, вызов из ассемблерных программ подпрограмм на С. В данном разделе показано, насколько простинтерфейс между Turbo C++ и ассемблером; также приводится информация, помогающая на практике осуществить такой интерфейс.

Последовательности передачи параметров

Turbo C++ поддерживаетдва метода передачи параметров функции. Один из них является стандартным методом С, который мы рассмотрим первым; второй метод заимствован из Паскаля.

Последовательность передачи параметров в С

Предположим, вы объявили следующий прототип функции:

void funca(int p1, int p2, long p3);

По умолчанию Turbo C++ использует последовательность передачи параметров С, которая также называется соглашением о связях С. При вызове этой функции(funca) параметры помещаютсяв стек в последовательности справа-налево (p3,p2,p1), послечего в стек помещается адрес возврата. Таким образом, в случае вызова

main()

(*

int i,j;

long k;

...

i = 5; j = 7; k = 0x1407AA;

funca(i,j,k);

...

*)

то стек (непосредственно перед помещением в него адреса возврата) будет выглядеть следующим образом:

sp + 06: 0014

sp + 04: 07AA k = p3

sp + 02: 0007 j = p2

sp: 0005 i = p1

Вызываемой подпрограмме не требуется точно знать, сколько параметров помещено в стек. Она просто предполагает, что все нужные ей параметры находятся в стеке.

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

mov WORD PTR [bp-8],5;установка i =5

mov WORD PTR [bp-6],7;установка j = 7

mov WORD PTR [bp-2],0014h;установка k = 0x1407AA

mov WORD PTR [bp-4],07AAh

push WORD PTR [bp-2];помещение в стек старшего слова k

push WORD PTR [bp-4];помещение в стек младшего слова k

push WORD PTR [bp-6];помещение в стек j

push WORD PTR [bp-8];помещение в стек i

call NEAR PTR funca ;вызов funca (помещение в стек

;адреса возврата)

add sp,8;настройка стека

Обратите внимание на последнюю команду, add sp,8. К этому моменту компилятору известно, сколько параметров было помещено в стек; компилятор также знает, что адрес возврата был помещен в стек при вызове funca и уже был снят оттуда командой ret в конце funca.

Последовательность передачи параметров Паскаля

Другим методом передачи параметров является стандартный метод передачи параметров Паскаля (называемый также соглашением о связях Паскаля). Это не значит, что вы можете вызывать из TurboC++ функции Turbo Pascal. Это невозможно. Если funca объявлена как

void pascal funca(int p1, int p2, long p3);

то при вызове этой функции параметры помещаются в стек в последовательности слева-направо (p1,p2,p3), после чего в стек помещается адрес возврата. Таким образом, при вызове:

main()

(*

int i,j;

long k;

...

i = 5; j = 7; k = 0x1407AA;

funca(i,j,k);

...

*)

то стек (непосредственно перед помещением в него адреса возврата) будет выглядеть следующим образом:

sp + 06: 0005 i = p1

sp + 04: 0007 j = p2

sp + 02: 0014

sp: 07AA k = p3

Итак, в чем здесь различие? Дело в том, что помимо изменения очередности помещения параметров в стек, последовательность передачи параметров Паскаля предполагает, что вызываемая функция (funca) знает, сколько параметров будет ей передано и соответственно настраиваетстек. Другимисловами, теперь в ассемблированном виде данная функция будет иметь вид:

push WORD PTR [bp-8];помещение в стек i

push WORD PTR [bp-6];помещение в стек j

push WORD PTR [bp-2];помещение в стек старшего слова k

push WORD PTR [bp-4];помещение в стек младшего слова k

call NEAR PTR funca ;вызов funca (помещение в стек

;адреса возврата)

Отметим, что теперь после вызова отсутствует командаadd sp,8. Вместо нее funca использует при окончании команду ret 8, при помощи которой очищает стек перед возвратом к main.

По умолчанию все функции, создаваемые в Turbo C++, используют способ передачи параметров С. Исключение делается при наличии опциикомпилятора -p (опция Pascal в диалоговомполе Code Generation); в этом случае все функции используют метод передачи параметров Паскаля. Тем не менее, вы можете задать для любой функции метод передачи параметров С при помощи модификатора cdecl:

void cdeclfunca(int p1, int p2, long p3);

Данное объявление переопределит директиву компилятора - p.

И однако, почему может возникнуть необходимость использовать соглашение о связях Паскаля вообще? Для этого есть две главных причины.

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

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

Однако, использование соглашения о связях Паскаля может вызвать некоторые проблемы.

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

Во-вторых, при использовании опции компилятора вы обязательно включить файлы заголовка длявсех вызываемых вашей программой стандартных функций С. Почему? Дело в том, что в противном случае Turbo C++ будет использовать для каждой из этих функций соглашение о связях (и именах) - и ваша программа не будет компоноваться.

В файле заголовка каждая из этих функций объявлена как cdecl, поэтому включение файловзаголовка заставит компилятор использовать для этих функций соглашение С.

Резюме:если вы собираетесь использовать вС-программе соглашение освязяхПаскаля, не забывайте о необходимости использовать прототипы функций везде, где это возможно, а каждую функцию явно объявляйте pascal или cdecl. Полезно также разрешить выдачу сообщения "Function call with no prototype" ("вызов функции без прототипа"), чтобы гарантировать наличие прототипов всех функций.

Подготовка к вызову .ASM из Turbo C++

При написании подпрограмм на языке ассемблера нужно принимать во внимание определенные соглашения для того, чтобы (1) обеспечить компоновщик нужной ему информацией и (2) обеспечить соответствие формата файла и модели памяти, используемой в программе на С. Упрощенные сегментные директивы

Обычно модули на языке ассемблера состоят из трех разделов: кода, инициализированных данных и неинициализированных данных. Каждый из этих типов информации организован в отдельный сегмент с использованием определенных имен, которые зависят от используемой в вашей С-программе модели памяти.

Turbo Assembler (TASM) предлагает вам три упрощенных сегментных директивы (.CODE, .DATA и .DATA?), которыемогут быть использованыпри определении этих сегментов. Они говорят компилятору о необходимостииспользовать имена сегментов по умолчанию для модели памяти, заданной вами при помощи директивы .MODEL. Например, если ваша программа на С использует модель памяти small, вы можете организовать каждый ассемблерный модуль с упрощенными сегментными директивами,как показано в следующей таблице:

-----------------------------------------------------------

.MODEL SMALL

.CODE

...кодовый сегмент...

.DATA

...сегмент инициализированных данных...

.DATA?

...сегмент неинициализированных данных...

Стандартные сегментные директивы

В некоторых случаях вам может понадобиться использовать другие имена сегментов, нежели те, что являются умолчаниямидля данной модели памяти. Для этого вы должны использовать стандартные сегментные директивы, как показано в Таблице 6.1.

Формат файла языка ассемблера Таблица 6.1

code SEGMENT BYTE PUBLIC 'CODE'

ASSUME CS:code, DS:dseg

...........кодовый сегмент.............

code ENDS

dseg GROUP _DATA,_BSS

data SEGMENT WORD PUBLIC 'DATA'

...инициализированный сегмент данных...

data ENDS

_BSS SEGMENT WORD PUBLIC 'BSS'

...неинициализированный сегмент данных...

_BSS ENDS

END

Идентификаторы code, data и dseg в данном макете имеют специальные заменители, зависящие от используемой модели памяти; в таблице 6.2 показано, какое имя должно использоваться для тойили иной модели. имя_файла в Таблице 6.2 - это имя модуля: оно должно быть тем же в директиве NAME и при заменах идентификаторов.

Отметим,что вслучаемоделипамятиhuge сегмент _BSS отсутствует, а определение GROUP опускается полностью. В целом, _BSS представляет собой опцию; определение ее необходимо только в случае использования.

Лучший способ создания "заготовки" для будущей ассемблерной программы состоит в том, чтобы скомпилировать пустую программу в .ASM-файл (при помощи опции TCC -S) и затем изучить сгенерированный таким образом ассемблерный код.

Замены идентификаторов и модели памяти Таблица 6.2

Модель

Замены идентификатораУказатели кода

и

данных

Tiny,Small data dseg

code = _TEXTКод:DW _TEXT:xxx

_DATAДанные: DW DGROUP:xxx

DGROUP

Compact data dseg

code = _TEXTКод:DW _TEXT:xxx

_DATAДанные: DD DGROUP:xxx

DGROUP

Medium data dseg

code = имя_файла_TEXTКод:DD:xxx

_DATAДанные: DW DGROUP:xxx

DGROUP

Large

data

dseg

code = имя_файла_TEXTКод:DD:xxx

_DATAДанные: DD DGROUP:xxx

DGROUP

Huge code = имя_файла_TEXTКод:DD:xxx

data = имя_файла_DATAДанные: DD:xxx

Определение данных - констант и переменных

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

Некоторые определения используют DW (определение слова), а некоторые - DD (определение двойного слова), что означает размер результирующего указателя. Числовые и текстовые константы определяются нормальным образом.

Переменные, разумеется, определяются так же, как и константы. Если вам нужны переменные,не инициализированныеконкретными значениями, вы можете объявить ихв сегменте _BSS, введя вопросительный знак(?) втом месте, где обычно находится значение.

Определение глобальных и внешних идентификаторов

После того, как вы создали модуль, вашей программе на Turbo

C++ требуется знать, какие функции она может вызывать и на

какие переменные ссылаться. Аналогичным образом, вам может

потребоваться иметь возможность вызывать функции Turbo C++из

подпрограмм на языке ассемблера, либо ссылаться оттуда напе-

ременные, определенные в программе на Turbo C++.

При выполнении таких вызовов вы должны хорошо представлять себе работу компилятора и компоновщика Turbo C++. При объявлении внешнего идентификатора компилятор автоматически добавляет к этому именисимволподчеркивания (_), прежде чем сохранить его в объектном модуле. Это означает, что вы должны поместить символ подчеркивания перед любыми идентификаторами вашего модуля на языке ассемблера, на которые вы хотите ссылаться из С-программы. Идентификаторы Паскаля обрабатываются иначе, чем идентификаторы С, - они состоят только из заглавных символов не имеют ведущего символа подчеркивания.

Символы подчеркивания в идентификаторах С необязательны, но по умолчаниюони помещаются передними. Их можно отменить при помощи командной строки -u-. Однако, при использовании стандартных библиотек Turbo C++ вы в таком случае столкнетесь с проблемами, и вам придется переделывать эти библиотеки. (Для этоговам понадобится другой продукт Turbo C++ - исходные тексты библиотек исполняющей системы;в этом случае за дополнительной информацией обращайтесь на фирму Borland).

Если какой-либоasm-код в исходном файле ссылается на идентификаторы С (данные или функции), эти идентификаторы должны начинаться знаком подчеркивания (если вы не используете один из описанных выше спецификаторов языка).

Turbo Assembler (TASM) не учитываетрегистры, которыми набраны символы идентификаторов; другими словами,при ассемблировании программы все идентификаторы записываются только заглавными буквами. Опция TASM /mx устанавливает учет регистра для общих и внешних имен. Компоновщик Turbo C++ также записывает идентификаторы extern заглавными буквами, поэтому тут все должно работать. В наших примерах ключевые слова и директивы записываются заглавными буквами, а все прочие идентификаторы и коды операций строчными; это соответствует стилю имен в справочном руководстве по TASM.Вам предоставляется свобода любых комбинаций заглавных и строчных букв в идентификаторах, по вашему усмотрению.

Характеристики

Тип файла
Документ
Размер
2,71 Mb
Тип материала
Учебное заведение
Неизвестно

Список файлов реферата

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6489
Авторов
на СтудИзбе
303
Средний доход
с одного платного файла
Обучение Подробнее