рефераты

рефераты

 
 
рефераты рефераты

Меню

Реферат: Turbo C++ Programer`s guide рефераты

Подпрограммы управления палитрой в случае CGA

Поскольку палитра CGA является предопределенной, подпрограмму setallpaletteиспользовать в данном случае нельзя. Также не следует использовать setpalette(индекс, фактический _цвет), за исключением индекс=0. (Этоальтернативный способ установки фонового цвета CGA равным фактическому_цвету).

Управление цветом для EGA и VGA

В случае EGA палитрасодержит 16 элементов из общего количества 64 возможных цветов, причем каждый из элементов палитры можетбыть задан пользователем. Доступ к текущей палитре выполняется через getpalette, которая заполняет структуру, включающую всебя размер палитры (16) имассивфактических элементов палитры ("аппаратные номера цветов", хранимые в палитре). Элементы палитры можно изменять как по отдельностипри помощи setpalette, либо все сразу через setallpalette.

Палитра EGA по умолчанию соответствует 16 цветам CGA, которые были даны впредыдущей таблице цветов: черный равен элементу 0, голубой равен элементу 1, ... , белый равен элементу 15. В graphics.h определены константы, которые содержат соответствующие цветам аппаратные значения: это EGA_BLACK, EGA_WHITE и т.д.Эти значения могут быть также получены через getpalette.

Подпрограмма setbkcolor(цвет) на EGAработает несколько иначе, чем на CGA. На EGA setbkcolor копирует фактическое значение цвета, хранящееся в элементе #цвет, в элемент #0.

Что касается цветов, то драйвер VGA работает фактическитак же, как и драйвер EGA; он просто имеет более высокое разрешение (и меньшие по размеру пиксели).

Обработка ошибок в графическом режиме

Ниже приводитсякраткий обзорфункций обработки ошибок в графическом режиме:

grapherrormsg Возвращает строку с сообщением об ошибке для заданного кода ошибки.

graphresult Возвращает код ошибки для последней графической операции, в которой встретилась ошибка.

Если ошибка произошла при вызове графической библиотечной функции (например,не найден шрифт, запрошенный функцией settextstyle), устанавливается внутренний код ошибки. Доступ к коду ошибки для последней графической операции, сообщившей об ошибке, выполняется при помощи graphresult. Определены следующие коды возврата ошибки:

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

Код  Константа  Соответствующая строка

ошибки   графической_ошибки  с сообщением об ошибке

0 grOk No error Нет ошибки

-1 grNoInitGraph (BGI) graphics not installed (use initgraph)

(BGI) графика не инсталирована

(используйте initgraph)

-2 grNotDetected Graphics hardware not detected Графическое аппаратное обеспечение

не обнаружено

-3 grFileNotFound Device driver file not found Не найден файл драйвера устройства

-4 grInvalidDriver Invalid device driver file Неверный файл драйвера устройства

-5 grNoLoadMem Not enough memory to load driver Не хватает памяти для загрузки

драйвера

-6 grNoScanMem Out of memory in scan fill Кончилась память при сканирующем

заполнении

-7 grNofloodMem Out of memory in flood fill Кончилась память при лавинном

заполнении

-8  grFontNotFound  Font file not found

Файл шрифта не найден

-9 grNoFontMem Not enough memory to load font Не хватает памяти для загрузки

шрифта

-10 grInvalidMode Invalid graphics mode for selrcted driver

Недопустимый графический режим для выбранного драйвера

-11 grError Graphics error Графическая ошибка

-12 grIOerror Graphics I/O error Графическая ошибка ввода/вывода

-13 grInvalidFont Invalid font file Неверный файл шрифта

-14 grInvalidFontNum Invalid font number Неверный номер шрифта

-15 grInvalidDeviceNum Invalid device number Неверный номер устройства

-16 grInvalidVersion Invalid version of file Неправильная версия файла

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

Вызов grapherrormsg(graphresult()) возвращает строку сообщения об ошибке из вышеприведенной таблицы.

Код возврата ошибки накапливается, изменяясь только когда графическая функция сообщает об ошибке. Код возврата ошибки сбрасывается в 0 только при успешном выполнении initgraph, либо при вызове graphresult. Таким образом, если вы хотите знать, какая графическая функция возвратила ошибку, нужно хранить значение graphresult во временной переменной и затем проверять ее.

Функции запроса состояния

Ниже приводится краткое изложение функций запроса состояния графического режима:

getarccoords Возвращает информацию о координатах, заданных в последнем вызове arc или ellipse.

getaspectratio Возвращает коэффициент сжатия для графического экрана.

getbkcolor                   Возвращает текущий цвет фона.

getcolor                  Возвращает текущий цвет вычерчивания.

getdrivername Возвращает имя текущего графического драйвера.

getfillpattern Возвращает шаблон заполнения, определяемый пользователем.

getfillsettings  Возвращает информацию о текущем шаблоне

и цвете заполнения.

getgraphmode                  Возвращает текущий графический режим.

getlinesettings Возвращает текущие стиль, шаблон и толщину линии

getmaxcolor Возвращает максимально допустимое на текущий момент значение пикселя.

getmaxmode Возвращает максимально допустимый номер режима для текущего драйвера.

getmaxx               Возвращает текущее разрешение по оси x.

getmaxy               Возвращает текущее разрешение по оси y.

getmodename                  Возвращает имя данного режима драйвера.

getmoderange                  Возвращает диапазон режимов для данного

драйвера.

getpalette                    Возвращает текущую палитру и ее размер.

getpixel                   Возвращает цвет пикселя в (x,y).

gettextsettings Возвращает текущий шрифт, направление, размер и способ выравнивания текста.

getviewsettings Возвращает информацию о текущем графическом окне.

getx               Возвращает координату x текущей позиции (CP).

gety               Возвращает координату y текущей позиции (CP).

В каждой из категорий графических функций Turbo C++ имеется хотя бы одна функция запроса состояния. Эти функцииупоминались при рассмотрении соответствующих категорий и также рассматриваются здесьотдельно. Каждая из графических функций запроса состояния Turbo C++ имеет имя вида "getчто-то" (за исключением категории функций обработки ошибок). Некоторые из них не принимают никаких аргументов ивозвращают единственное значение, представляющее собой искомую информацию; прочие берут указатель структуры, определяемой в graphics.h, заполняют эту структуру соответствующей информацией и не возвращают никаких значений.

Функциями запроса состояния категории управленияграфической системы являются getgraphmode, getmaxmode и getmoderange. Первая из них возвращает целое число, определяющее текущийграфический драйвер и режим, вторая возвращает максимальный номер режима для этого драйвера, а третья возвращает диапазон режимов, поддерживаемых данным графическим драйвером. getmaxx и getmaxy возвращают соответственно максимальные экранные координаты x и y для текущего графического режима.

Функциями запроса состояниякатегории вычерчивания и заполнения являются getarccoords, getaspectratio, getfillpattern и getlinesettings. getarccoords заполняет структуру, содержащуу координаты, которые использовались при последнем вызове функций arc или ellipse; getaspectratio сообщает текущийкоэффициент сжатия, используемый графическойсистемой для того, чтобы окружности выглядели круглыми. getfillpatternвозвращает текущий определяемыйпользователем шаблон заполнения. getfillsettings заполняет некоторуюструктуру текущим шаюлоном и цветом заполнения. getlinesettings заполняет структуру текущим стилем линии(сплошная, пунктир и т.д.), толщиной (обычнаяили увеличенная), а также шаблоном линии.

Функциями запроса состояниякатегории манипулирования графическим окном являются getviewsettings, getx, gety и getpixel. После того, как графическое окно определено, вы можете найтиего абсолютные экранные координаты ивыяснить состояние режима отсечки, вызвав getwiewsettings, которая заполняет соответствующей информацией некоторую структуру. getx и gety возвращают (относительно графическогоокна) x- и y-координаты текущей позиции. getpixel возвращает цвет указанного пикселя.

Функция запросасостояния категориивывода текста в графическом режиме имеется только одна - gettextsettings. Эта функция заполняет структуруинформацией отекущем символьном шрифте, направлении вывода текста (по горизонтали или по вертикали)6 коэффициенте увеличениясимволов, а также виде выравнивания (как для горизонтально, так идля вертикально-ориентированных текстов).

Функциями запроса состоянии категорииуправления цветом являются getbkcolor,возвращающая текущий цвет фона, getcolor, возвращающая текущий цвет вычерчивания и getpalette,заполняющая структуру, которая включаетв себя размер текущей палитры и ее содержимое. getmaxcolor возвращает максимально допустимое значение пикселя для текущего графического драйвера и режима (размер палитры -1).

И наконец, 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

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40