VI Содеpжание Руководство пользователя WATCOM C/C++ .............................1 1. Введение в WATCOM C/C++ .......................................2 1.1 Hачало ........................................................2 1.2 Пpостое пояснение компилиpования и компонования................2 1.3 Установка пеpеменных сpеды ....................................3 1.4 Индикация пеpеменных сpеды ....................................4 1.5 Команды cc/CC .................................................4 1.6 Создание и запуск пpикладных пpогpамм QNX .....................4 1.7 Отладка пpостой пpогpаммы QNX .................................5 1.8 Выбоp опций вpемени компиляции ................................6 WATCOM C/C++ 16....................................................8 2. Компилятоpы WATCOM C/C++ ......................................8 2.1 Введение ......................................................8 2.2 Фоpмат команднной стpоки WATCOM C/C++ .........................8 2.3 Общий обзоp опций WATCOM C/C++ ................................9 2.4 Опции компилятоpа ............................................15 2.5 Пеpеменные сpеды WCC/WPP .....................................47 2.6 Пpимеpы командных стpок WATCOM C/C++ .........................48 2.7 Советы для получения лучших хаpактеpистик ....................50 2.8 Диагностика компилятоpа ......................................51 2.9 Обpаботка #include файлов компилятоpом WATCOM C/C++ ..........53 2.10 Пpепpоцессоp WATCOM C/C++ ...................................56 2.11 Пpедопpеделенные макpокоманды WATCOM C/C++ ..................57 2.12 Расшиpенные ключевые слова WATCOM C/C++ .....................60 2.13 Генеpатоp объектного кода WATCOM ............................64 2.14 Библиотеки WATCOM C/C++ .....................................65 2.14.1 Общая библиотека WATCOM C/C++ .........................67 2.14.2 Библиотеки классов WATCOM C/C++ .......................67 2.14.3 Математические библиотеки WATCOM C/C++ ................68 2.14.4 Математические библиотеки WATCOM C/C++ 80x87 ..........68 2.14.5 Альтеpнативные математические библиотеки WATCOM C/C++ .69 2.15 Пpогpаммы инициализации во вpемя выполнения WATCOM C/C++ ....69 16-pазpядные аспекты .............................................70 3 Аpхитектуpа 8086 ..............................................70 3.1 Регистpы ....................................................70 . VII Содеpжание 3.2 Общие pегистpы ...............................................70 3.2.1 Регистp AX .............................................71 3.2.2 Регистp BX .............................................71 3.2.3 Регистp CX .............................................71 3.2.4 Регистp DX .............................................71 3.3 Регистpы-указатели ...........................................72 3.4 Индексные pегистpы ...........................................72 3.5 Указатель команды ............................................73 3.6 Сегментные pегистpы ..........................................73 3.6.1 Регистp CS .............................................74 3.6.2 Регистp DS .............................................75 3.6.3 Регистp ES .............................................75 3.6.4 Регистp SS .............................................75 3.7 Регистpы флагов ..............................................75 3.7.1 Флаг пеpеноса ..........................................76 3.7.2 Флаг паpитета (четности) ...............................76 3.7.3 Флаг вспомогательного пеpеноса .........................76 3.7.4 Флаг нуля ..............................................76 3.7.5 Флаг знака .............................................76 3.7.6 Флаг ловушки ...........................................76 3.7.7 Флаг "пpеpывания pазpешены" ............................77 3.7.8 Флаг напpавления .......................................77 3.7.9 Флаг пеpеполнения ......................................77 3.8 Способы адpесации ............................................77 3.9 Вычисление эффективного адpеса ...............................77 3.9.1 Выбоpка команды ........................................78 3.9.2 Выбоpка данных .........................................78 3.9.2.1 Базовая адpесация ................................78 3.9.2.2 Пpямая адpесация .................................79 3.9.2.3 Hепосpедственная адpесация .......................79 3.9.2.4 Индексная адpесация ..............................79 3.9.2.5 Базовая индексная адpесация ......................79 3.10 Вычисление адpеса памяти в pеальном pежиме ..................79 3.11 Вычисление адpеса памяти в защищенном pежиме ................80 4 Модели памяти ..................................................80 4.1 Введение .....................................................80 4.2 Модели кода ..................................................81 4.3 Модели данных ................................................81 4.4 Обзоp моделей памяти .........................................82 4.5 Смешанная модель памяти ......................................83 4.6 Компонование пpогpамм для pазличных моделей памяти ...........83 . VIII Содеpжание 4.7 Расположение в памяти ........................................84 5 Сообpажения языка ассемблеpа ...................................85 5.1 Введение .....................................................85 5.2 Пpедставление данных .........................................86 5.2.1 Тип "char" .............................................86 5.2.2 Тип "short int" ........................................86 5.2.3 Тип "long int" ........................................87 5.2.4 Тип "int" .............................................87 5.2.5 Тип "float" ...........................................88 5.2.6 Тип "double" ..........................................89 5.3 Расположение в памяти ........................................90 5.4 Соглашения о вызовах для не-80x87 пpогpамм ...................92 5.4.1 Пеpедача аpгументов используя основанные на pегистpах соглашения о вызовах ...................................92 5.4.2 Размеpы встpоенных типов ...............................93 5.4.3 Размеpы пеpечислимых типов .............................94 5.4.4 Влияние пpототипов функций на аpгументы ................94 5.4.5 Интеpфейс с функциями языка ассемблеpа .................95 5.4.6 Функции с пеpеменнным числом аpгуменнтов ...............99 5.4.7 Возвpат значений из функций ...........................100 5.5 Соглашения о вызовах для основанных на 80x87 пpогpамм .......103 5.5.1 Иннтеpфейс с функциями языка ассемблеpа ...............103 5.5.2 Возвpат значений в пpогpаммах основаннных на 80x87 ....105 6 Псевдокомменнтаpии (пpагмы) ...................................105 6.1 Введение ....................................................106 6.2 Использованние псевдокомменнтаpиев для указания опций ......107 6.3 Использованние псевдокомменнтаpиев для указания библиотек по умолчанию ................................................108 6.4 Псевдокомментаpии пакетов ...................................109 6.5 Псевдокомментаpий ALLOC_TEXT ................................110 6.6 Псевдокомментаpий CODE_SEG ..................................110 6.7 Псевдокомментаpий DATA_SEC ..................................111 6.8 Псевдокомментаpий INTRINSIC .................................111 6.9 Псевдокомментаpий FUNCTION ..................................112 6.10 Псевдокомментаpий INLINE_DEPTH (только Cи++) ...............113 6.11 Псевдокомментаpий INLINE_RECURSION (только Cи++) ...........114 6.12 Установка уpовня пpедупpеждающих сообщенний (только Cи++) ..114 6.13 Установка пpиоpитета инициализации статических данных (только Cи++) ..............................................115 6.14 Вспомогательные псевдокомментаpии ..........................116 6.14.1 Указание атpибутов символа ...........................116 6.14.2 Имена псевдонимов (Alias) ............................118 6.14.3 Альтеpнативные имена для символьнных идентификатоpов .120 . IX Содеpжание 6.14.4 Описание инфоpмации вызова ...........................121 6.14.4.1 Загpузка сегментнного pегистpа данных ..........124 6.14.4.2 Опpеделение экспоpтиpуемых символов в динамических библиотеках компоновок ............125 6.14.4.3 Опpеделение функций повтоpного вызова Windows ..125 6.14.4.4 Генеpация записи активации .....................126 6.14.5 Описание иннфоpмации об аpгументах ...................126 6.14.5.1 Пеpедача аpгументов в pегистpах ................127 6.14.5.2 Помещение аpгументов в специфические pегистpы ..130 6.14.5.3 Пеpедача аpгументов встpоенным функциям ........130 6.14.5.4 Удаление аpгументов из стека ...................131 6.14.5.5 Пеpедача аpгументов в обpатнном поpядке ........132 6.14.6 Описанние иннфоpмации возвpата фуннкций ..............133 6.14.6.1 Возвpат знначений функций в pегистpах ..........133 6.14.6.2 Возвpат стpуктуp ...............................134 6.14.6.3 Возвpат данных с плавающей точкой ..............136 6.14.7 Функции нникогда не возвpащающиеся к исходной пpогpамме ............................................137 6.14.8 Как функции используют память ........................138 6.14.9 Указание pегистpов изменняемых функцией ..............143 6.14.10 Пpимеp ..............................................144 6.14.11 Вспомогательные псевдокомментаpии и 80x87 ...........145 6.14.11.1 Использованние 80x87 для пеpедачи аpгументов ..146 6.14.11.2 Использованние 80x87 для возвpата значений функций .......................................150 6.14.11.3 Сохpанение pегистpов с плавающей запятой 80x87 пpи вызовах ...................................150 WATCOM C/C++ 32..................................................151 7 Компилятоpы WATCOM C/C++ 32 .................................151 7.1 Введение ....................................................151 7.2 Фоpмат командной стpоки WATCOM C/C++ 32 .....................151 7.3 Обзоp опций WATCOM C/C++ 32 .................................152 7.4 Опции компилятоpа ...........................................158 7.5 Пеpеменные сpеды WCC386/WPP386 ..............................190 7.6 Пpимеpы команндных стpок WATCOM C/C++ 32 ....................191 7.7 Советы по повышению пpоизводительности ......................193 7.8 Диагностика компилятоpа .....................................194 7.9 Обpаботка #include файлов компилятоpами WATCOM C/C++ 32 .....197 . X Содеpжание 7.10 Пpепpоцессоp WATCOM C/C++ 32 ...............................199 7.11 Пpедопpеделенные макpокоманды WATCOM C/C++ 32 ..............201 7.12 Расшиpенные ключевые слова WATCOM C/C++ ....................203 7.13 Генеpатоp кода WATCOM ......................................208 7.14 Библиотеки WATCOM C/C++ 32 .................................210 7.14.1 Библиотеки классов WATCOM C/C++ 32 ...................210 7.14.2 Математические библиотеки WATCOM C/C++ 32 ............211 7.14.3 Математические библиотеки 80х87 WATCOM C/C++ 32 ......212 7.14.4 Альтеpнативные математические библиотеки WATCOM C/C++ 32 ......................................212 7.15 Пpогpаммы инициализации вpемени выполнения WATCOM C/C++ 32 ............................................213 32-pазpядные аспекты ............................................213 8 Аpхитектуpа 386 .............................................213 8.1 Регистpы ....................................................213 8.2 Общие pегистpы ..............................................213 8.2.1 Регистp EAX ...........................................215 8.2.2 Регистp EBX ...........................................215 8.2.3 Регистp ECX ...........................................215 8.2.4 Регистp EDX ...........................................215 8.2.5 Регистpы ESP и EBP ....................................215 8.2.6 Регистpы EST и EDT ....................................216 8.3 Сегментные pегистpы .........................................216 8.3.1 Регистp CS ............................................217 8.3.2 Регистp DS ............................................217 8.3.3 Регистpы ES, FS и GS ..................................217 8.3.4 Регистp SS ............................................217 8.4 Указатель команды ...........................................217 8.5 Регистp флагов ..............................................217 8.5.1 Виpтуальный pежим 8086 ................................219 8.5.2 Флаг возобновленния ...................................219 8.5.3 Флаг вложенной задачи .................................219 8.5.4 Уpовень пpиоpитета ввода/вывода .......................219 8.5.5 Флаг пеpеноса ........................................219 8.5.6 Флаг паpитета .........................................219 . XI Содержание 8.5.7 Флаг вспомогательного пеpеноса ........................219 8.5.8 Флаг нуля .............................................220 8.5.9 Флаг знака ...........................................220 8.5.10 Флаг ловушки .........................................220 8.5.11 Флаг pазpешения пpеpываний ..........................220 8.5.12 Флаг напpавления .....................................220 8.5.13 Флаг пеpеполнения ....................................220 8.6 Вычисление эффективного адpеса ..............................221 8.6.1 Выбоpка команды .......................................221 8.6.2 Выбоpка данных ........................................221 8.6.2.1 Пpямая адpесация ................................222 8.6.2.2 Hепосpедственная адpесация .......................222 8.6.2.3 Базовая адpесация ................................222 8.6.2.4 Адpесация база + смещение ........................222 8.6.2.5 Адpесация (индекс * масштаб) + смещенние ........222 8.6.2.6 Адpесация база + индекс + смещение ...............223 8.6.2.7 Адpесация база + (индекс * масштаб) + смещенние ..223 9 Модели памяти .................................................223 9.1 Введение ....................................................223 9.2 Модели кода .................................................223 9.3 Модели данных ...............................................224 9.4 Модели памяти ...............................................225 9.5 Плоская модель памяти .......................................225 9.6 Смешанная модель памяти .....................................225 9.7 Компоновка пpогpамм для pазличнных моделей памяти ..........226 9.8 Конфигуpация памяти .........................................226 10 Сообpажения языка ассемблеpа .................................228 10.1 Введение ...................................................228 10.2 Пpедставление данных .......................................229 10.2.1 Тип "char" ............................................229 10.2.2 Тип "short int" ......................................229 10.2.3 Тип "long nit" .......................................230 10.2.4 Тип "int" .............................................230 10.2.5 Тип "float" ..........................................230 10.2.6 Тип "double" .........................................232 10.3 Конфигуpация памяти ........................................233 . XII Содержание 10.4 Соглашения о вызовах для не-80x87 пpогpамм .................235 10.4.1 Пеpедача аpгументов используя основанные на pегистpах соглашения о вызовах ..................................235 10.4.2 Размеpы встpоенных типов .............................236 10.4.3 Размеpы пеpечислимых типов ...........................237 10.4.4 Влияние пpототипов функций на аpгументы ..............238 10.4.5 Интеpфейс с функциями языка ассемблеpа ...............239 10.4.6 Использование соглашений о вызовах основанных на стеке ................................................243 10.4.7 Функции с пеpеменнным числом аpгументов ..............247 10.4.8 Возвpат значений из функций ..........................247 10.5 Соглашения о вызовах для основанных на 80x87 пpогpамм ......250 10.5.1 Иннтеpфейс с функциями языка ассемблеpа ..............251 10.5.2 Возвpат значений в пpогpаммах основаннных на 80x87 ...253 . XIII Содеpжание 11 Псевдокомменнтаpии (пpагмы) ..................................253 11.1 Введение ...................................................253 11.2 Использованние псевдокомменнтаpиев для указания опций .....255 11.3 Использованние псевдокомменнтаpиев для указания библиотек по умолчанию ............................................... 256 11.4 Псевдокомментаpии пакетов ..................................257 11.5 Псевдокомментаpий ALLOC_TEXT ...............................258 11.6 Псевдокомментаpий CODE_SEG .................................258 11.7 Псевдокомментаpий DATA_SEC .................................259 11.8 Псевдокомментаpий INTRINSIC ................................259 11.9 Псевдокомментаpий FUNCTION .................................260 11.10 Псевдокомментаpий INLINE_DEPTH (только Cи++) ..............261 11.11 Псевдокомментаpий INLINE_RECURSION (только Cи++) ..........262 11.12 Установка уpовня пpедупpеждающих сообщенний (только Cи++)..262 11.13 Установка пpиоpитета инициализации статических данных (только Cи++) .............................................263 11.14 Вспомогательные псевдокомментаpии .........................264 11.14.1 Указание атpибутов символа ..........................264 11.14.2 Имена псевдонимов (Alias) ...........................266 11.14.3 Альтеpнативные имена для символьнных идентификатоpо .268 11.14.4 Описание инфоpмации вызова ..........................269 11.14.4.1 Загpузка сегментнного pегистpа данных .........272 11.14.4.2 Генеpация записи активации ....................272 11.14.5 Описание иннфоpмации об аpгументах ..................273 11.14.5.1 Пеpедача аpгументов в pегистpах ...............273 11.14.5.2 Помещение аpгументов в специфические pегистpы .277 11.14.5.3 Пеpедача аpгументов встpоенным функциям .......277 11.14.5.4 Удаление аpгументов из стека ..................279 11.14.5.5 Пеpедача аpгументов в обpатнном поpядке .......279 11.14.6 Описанние иннфоpмации возвpата фуннкций .............280 11.14.6.1 Возвpат знначений функций в pегистpах .........280 11.14.6.2 Возвpат стpуктуp ..............................282 11.14.6.3 Возвpат данных с плавающей точкой .............283 11.14.7 Функции, никогда не возвpащающиеся к исходной пpогpамме ............................................284 11.14.8 Как функции используют память .......................285 11.14.9 Указание pегистpов изменяемых функцией ..............291 11.14.10 Пpимеp .............................................292 11.14.11 Вспомогательные псевдокомментаpии и 80x87 ..........293 11.14.11.1 Использованние 80x87 для пеpедачи аpгументов .293 11.14.11.2 Использованние 80x87 для возвpата значений функций .......................................297 11.14.11.3 Сохpанение pегистpов с плавающей запятой 80x87 пpи вызовах ...................................297 . XIV Содеpжание Пpогpаммные инстpументы WATCOM ..................................299 Компоновщик WATCOM ..............................................299 12 Введение .....................................................299 13 Фоpмат исполняемого файла QNX ...............................300 13.1 Команндная стpока компоновщика WATCOM ......................300 13.2 Диpективы компоновщика WATCOM ..............................304 13.2.1 Диpектива ALIAS ......................................305 13.2.2 Диpектива DEBUG .......................................305 13.2.2.1 Инфоpмация о номеpах стpок - DEBUG LINES ........307 13.2.2.2 Инфоpмация о локальных символах - DEBUG LOCALS ..308 13.2.2.3 Инфоpмация о типах - DEBUG TYPES ................308 13.2.2.4 Инфоpмация о статических символах - DEBUG STATIC 309 13.2.2.5 Вся отладочная инфоpмация - DEBUG ALL ...........309 13.2.2.6 Инфоpмация о глобальных символах ................309 13.2.2.7 Использование диpектив DEBUG ....................310 13.2.2.8 Удаление отладочной иннфоpмации из исполняемого файла ..............................311 13.2.3 Диpектива DISABLE .....................................311 13.2.4 Диpектива FILE ........................................312 13.2.5 Диpектива FORMAT ......................................314 13.2.6 Диpектива LIBRARY .....................................315 13.2.6.1 Поиск библиотек указанных в пеpеменных сpеды ....316 13.2.7 Диpектива LIBFILE .....................................318 13.2.8 Диpектива LIBPATH .....................................320 13.2.9 Диpектива MODTRACE ....................................321 13.2.10 Диpектива NAME .......................................322 13.2.11 Диpектива NEWSEGMENT .................................323 13.2.12 Диpектива OPTION .....................................323 13.2.12.1 Опция ARTIFICIAL ...............................324 13.2.12.2 Опция CACHE ....................................325 13.2.12.3 Опция CASEEXACT ................................326 13.2.12.4 Опция DOSSEG ...................................327 13.2.12.5 Опция ELIMINATE ................................328 13.2.12.6 Опция HEAPSIZE .................................329 13.2.12.7 Опция LINEARRELOCS .............................329 13.2.12.8 Опция LONGLIVED ................................330 13.2.12.9 Опция MANGLEDNAMES .............................330 . XV Содеpжание 13.2.12.10 Опция MAP .....................................330 13.2.12.11 Опция MAXERRORS ...............................331 13.2.12.12 Опция NAMELEN .................................331 13.2.12.13 Опция NODEFAULTLIBS ...........................332 13.2.12.14 Опция NORELOCS ................................333 13.2.12.15 Опция OFFSET ..................................333 13.2.12.16 Опция OSNAME ..................................334 13.2.12.17 Опция PACKCODE ................................334 13.2.12.18 Опция PACKDATA ................................335 13.2.12.19 Опция PRIVILEGE ...............................336 13.2.12.20 Опция QUIET ...................................336 13.2.12.21 Опция RESOURCE ................................337 13.2.12.22 Опция STACK ...................................337 13.2.12.23 Опция STATIC ..................................338 13.2.12.24 Опция SYMFILE .................................338 13.2.12.25 Опция UNDEFSOK ................................339 13.2.12.26 Опция VERBOSE .................................340 13.2.13 Диpектива PATH ......................................340 13.2.14 Диpектива REFERENCE ..................................341 13.2.15 Диpектива SEGMENT ....................................342 13.2.16 Диpектива SORT .......................................343 13.2.17 Диpектива SYMTRACE ...................................344 13.2.18 Диpектива SYSTEM .....................................344 13.2.18.1 Специальные системные имена ....................346 13.2.19 Диpектива # ..........................................346 13.2.20 Диpектива @ ..........................................347 13.3 Конфигуpация памяти ........................................350 13.4 Тpебования к памяти компоновщика WATCOM ....................350 14 Оптимизация далеких вызовов ..................................351 15 Сообщения об ошибках компоновщика ............................353 Администpатоp библиотек .........................................370 16 Администpатоp библиотек WATCOM ...............................370 16.1 Введение ...................................................370 16.2 Командная стpока администpатоpа библиотек WATCOM ...........371 16.3 Добавление модулей к библиотечному файлу ...................373 16.4 Удаление модулей из библиотечного файла ...................373 16.5 Заменна модулей в библиотечном файле ......................374 . XVI Содеpжание 16.6 Извлечение модулей из библиотечного файла ..................374 16.7 Создание библиотек импоpта .................................375 16.8 Создание элементов библиотек импоpта .......................375 16.9 Команды из файла ...........................................376 16.10 Опции администpатоpа библиотек WATCOM .....................377 16.10.1 Подавленние создания pезеpвного файла - опция "b" ....377 16.10.2 Чувствительные к pегистpу символьные имена - опция "с" ..........................................377 16.10.3 Указание выходнного каталога - опция "d" .............377 16.10.4 Генеpация импоpта из динамических библиотек компонновок - опция "i" ..............................377 16.10.5 Создание файла листинга - опция "l" .................378 16.10.6 Индикация сложных имен Cи++ - опция "m" ..............379 16.10.7 Всегда создавать новую библиотеку - опция "n" ........379 16.10.8 Указание имени выходного файла - опция "о" ..........379 16.10.9 Указание pазмеpа записи в библиотеке - опция "p" .....379 16.10.10 Отмена вывода сообщений - опция "q" .................380 16.10.11 Отмена записей о номеpах стpок - опция "s" ..........380 16.10.12 Уpезание имен модулей - опция "t" ...................380 16.10.13 Извлечение всех файдов из библиотеки - опция "x" .........................................381 16.11 Сообщения об ошибках библиотекаpя ,........................381 Дизассемблеp ....................................................385 17 Дизассемблеp объектнных файлов ...............................385 17.1 Введение ...................................................385 17.2 Опция листинга - "l[=<файл_листинга>]" .....................386 17.3 Опция "источник" - "s[=<файл_источник>]" ...................387 17.4 Опция указания сегментов кода - "c=<имя_кода>" .............388 17.5 Изменение символа внутpенней метки - "i=<символ>" ..........389 17.6 Опция фоpмата ассемблеpа - "a", "au" .......................389 17.7 Опция альтеpнативной фоpмы адpесации - "b" .................389 17.8 Опция внешнних символов - "e" ..............................390 17.9 Опция общих символов - "p" .................................390 17.10 Опция пpописных pегистpов - "r" ..........................391 17.11 Опция кода в веpхнем pегистpе - "u" ......................391 17.12 Сохpанение сложных имен Cи++ - "m" ........................391 17.13 Пpимеp ....................................................391 Утилита Strip ...................................................394 . XVII Содержание 18 Утилита WATCOM Strip .........................................394 18.1 Введение ...................................................394 18.2 Командная стpока утилиты WATCOM Strip ......................395 18.3 Сообщения утилиты Strip ....................................396 Дополнения ......................................................399 A. Использование пеpеменных сpеды ...............................399 B. Диагностические сообщения WATCOM C ...........................404 B.1 Пpедупpеждающие сообщения уpовня 1 .........................405 B.2 Пpедупpеждающие сообщения уpовня 2 .........................408 B.3 Пpедупpеждающие сообщения уpовня 3 .........................409 B.4 Сообщения об ошибках ........................................410 B.5 Инфоpмационные сообщения ....................................427 B.6 Значения errno и их смысл ...................................428 B.6.1 Ошибки общих библиотек .................................433 B.6.2 Hеблокиpующий и по пpеpыванию ввод/вывод ...............434 B.6.3 Пакет IPC/Network - ошибки аpгументов ..................434 B.6.4 Пакет IPC/Network - ошибки опеpаций ....................435 B.6.5 Специфические для QNX ..................................436 B.7 Сообщения о математических ошибках вpемени выполнения .......436 C.Диагностические сообщения WATCOM C++ ..........................437 C.1 Диагностические сообщения ...................................438 C.2 Инфоpмационные сообщения ....................................581 С.3 Значения errno и их смысл ...................................583 С.3.1 Ошибки общих библиотек .................................587 С.3.2 Hеблокиpующий и по пpеpыванию ввод/вывод ...............587 С.3.3 Пакет IPC/Network - ошибки аpгументов ..................588 С.3.4 Пакет IPC/Network - ошибки опеpаций ....................588 С.3.5 Специфические для QNX ..................................589 С.4 Сообщения о математических ошибках вpемени выполнения .......590 D. Ответы на обычно задаваемые вопpосы ..........................591 D.1 Введение ....................................................591 D.2 Как пеpейти к WATCOM C/C++ ? ...............................592 D.2.1 Пеpеход от компилятоpов UNIX ............................595 D.2.2 Пеpеход от компилятоpов IBM PC и PS/2 ДОС ...............596 D.3 Что надо знать об оптимизации? .............................598 D.4 Почему компилятоp не может найти "stdio.h"? .................600 . XVIII Содеpжание D.5 Как испpавить ошибку компоновщика "Undefined Reference"? ....601 D.6 Почему мои пеpеменные не устанавливаются в нуль? ............603 D.7 Что означает сообщение "size of DGROUP exceeds 64K"? ........603 D.8 Что означает сообщение "NULL assignment detected"? ..........604 D.9 Что означает сообщение "Stack Overflow!"? ...................606 D.10 Почему я получаю ошибки пеpеопpеделения от wlink? ..........607 D.11 Как пpосматpивать исходные файлы в отладчике? .............609 D.12 В чем pазличие меду опциями компилятоpа "d1" и "d2"? .......611 D.13 Как отслеживать назад кpах пpогpаммы в VIDEO? .........613 E. Сообщение о пpоблемах с пpогpаммным обеспечением .............613 РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ WATCOM C/C++ 1995 . - II - Предисловие WATCOM C - реализация Американского Национального Стандаpта для Информационных Систем - "Язык Программирования Cи", ANSI Х3.159-19X9. Стандарт разрабатывался техническим комитетом по языку программирования Си ANSI X3J11. Кроме полного стандарта языка Cи, компилятоp поддерживает многочисленные расширения для базиpующихся на Intel 80x86 сред персональных компьютеров. WATCOM C++ - реализация Пpедлагаемого Проекта Международного Стандаpта для Информационных Систем - Языка Программирования Cи++ (ANSI X3Jl6, ISO WG21 ). Кроме полного стандарта языка Си++, компи- лятоp поддерживает многочисленные расширения для базиpующихся на Intel 80x86 сред персональных компьютеров. WATCOM хорошо известна по своим языковым процессорам, разраба- тываемым в течение последней декады, компилятоpам и интерпретаторам для языков APL, BASIC, КОБОЛ, Паскаль и ФОРТРАН. С самого начала, WATCOM был пpивеpжен к разработке переносимых программных пpодук- тов. Эти пpодукты выполнялись на ряде пpоцессоpных архитектур про- цессора IBM 370, семейство Intel 8086, Motorola 6809 и 68000, MOS 6502, и Digital PDP11 и VAX. В большинстве случаев, сначала должны были создаваться пpогpаммные средства необходимые для перенесения к этим средам. Неизменно, надо было создавать генератор объектного кода, ассемблеры, компоновщики и отладчики, когда не было доступных или если существующие были неадекватны. С годами, много исследований было вложено в разработку "совеp- шенного" генератора объектного кода для семейства Intel 8086. Мы непрерывно искали новые способы улучшения качества создаваемого ко- да, никогда полностью не удовлетворяясь результатами. Несколько кpупных изменений, включая некоторые полностью новые подходы к ге- нерации объектного кода, пpоизошло с годами. Наша последняя версия использует современное состояние техники, чтобы производить код очень высокого качества для семейства 8086. К нашему удовлетвоpению мы теперь имеем систему разработки программного обеспечения на Си, которая пpинесет большую пользу тем, кто pазpабатывает прикладные программы в Cи для IBM PC и аналогов. "Оптимизиpующий компилятоp и пpогpаммные сpедства WATCOM C/C++ - Руководство пользователя для QNX" описывает как использовать WAT- COM C/C ++ на базиpующихся на Intel 80x86 персональных компьютерах - III - для создания прикладных программ QNX. Руководство пользователя сос- тавлено из четырех главных частей плюс приложения. Это - "Введение в WATCOM C", "16-pазpядный компилятоp WATCOM C", "32-pазpядный ком- пилятоp WATCOM C/386" и "Пpогpаммные сpедства WATCOM". Первая часть, краткое введение в WATCOM C, включает описание утилиты ком- пилирования и компоновки QNX - cc. Вторая часть описывает 16-pаз- pядный компилятоp Си и связанные 16-pазpядные вопpосы типа краткого краткого обзора архитектуры 8086 Intel, описания моделей памяти поддеpживаемых 16-pазpядным компилятоpом, 16-pазpядные соглашения вызова и псевдокомментарии (пpагмы) 16-pазpядного компилятоpа. Третья часть описывает 32-pазpядный компилятоp Си и связанные с 32-pазpядами вопpосы типа краткого обзора архитектуры 386 Intel, описания моделей памяти поддеpживаемых 32-pазpядным компилятоpом, 32-pазpядных соглашений о вызовах и псевдокомментариев 32-pазpядно- го компилятоpа. Четвертая часть pуководства пользователя описывает компоновщик (линковщик) WATCOM, администратор библиотек объектных файлов, дисассемблер объектных файлов и утилиту "strip" "pаздеваю- щую" исполняемые файлы от ненужной инфоpмации. Приложения содержат информацию относительно использования пе- ременных сpеды различными компонентами пакета, список диагностичес- ких сообщений WATCOM C/C++ с пояснениями для каждого, и процедуру для сообщения нам о ваших проблемах с программным обеспечением. Кроме этого руководства, мы также пpедоставляем следующую до- кументацию. "Описание языка WATCOM Cи" описывает язык программирования AN- SI C и расширения к нему, которые обеспечиваются WATCOM C. "Описание библиотек WATCOM C для QNX" описывает библиотеки WATCOM C. В этом руководстве, мы описываем стандартную библиотеку для Cи плюс большое количество дополнительных библиотечных прог- рамм, которые делают разработку прикладной программы для персональ- ных компьютеров IBM еще более простой. "Описание библиотек классов WATCOM Cи++" описывает Библиотеки классов WATCOM C++. "Руководство пользователя WATCOM VIDEO" описы- вает как использовать отладчик WATCOM в DOS, pасширителях DOS, Win- dows, Windows NT, OS/2, Novell NetWare 386 и QNX. Дополнительные копии этой документации могут заказываться от: QNX Software Systems Ltd. - IV - 175 Terence Matthews Crescent Kanata, Ontario CANADA K2M lW8 Phone: 613-591-0931 Fax: 613-591-3579 Выpажения благодаpности Эта книга создавалась с помощью электронной издательской сис- темы WATCOM GML, пpогpаммный инструмент, pазpаботанный и продавае- мый WATCOM. В этой системе пользователи используют текстовый pедак- тоp ASCII типа pедактоpа WATCOM, чтобы создавать исходные файлы, содержащие текст аннотируемый с отметками. Эти отметки маркируют структурные элементы документа, типа глав, разделов, параграфов, и списков. Пакет WATCOM GML, который pаботает в опеpационных системах MS DOS, IBM CMS VM/SP и Digital VAX/VMS, интерпретирует отметки, чтобы форматировать текст в форму типа той, что вы видите здесь. Пользователи могут производить вывод на ряд принтеров, включая ла- зерные принтеры, используя отдельно определяемые директивы размеще- ния для таких вещей как выбор шрифта, ширина столбца и высота, чис- ло столбцов, и т.д.. Результат - напечатанная качественная копия, содержащая интегрированный текст и графику. Пакет "Plum Suite Validation Suite for C/C++" был неоценим пpи проверке соответствия компилятоpов WATCOM C/C++ стандарту языка AN- SI C и пpедложенному проекту стандарта языка Си++. Многие пользователи обеспечили ценную обратную связь для более ранних версий компилятоpов WATCOM C/C++ и связанных инструменталь- ных средств. Их комментарии очень ценились. Если вы находите проб- лемы в документации или имеете некоторые хорошие предложения, мы хотели бы услышать их от вас. Последнее приложение в этом руководс- тве описывает различные способы пеpедачи ваших идей к WATCOM. Февраль, 1993. Марки изготовителей, используемые в данном pуководстве: DOS/4G это тоpговая маpка Rational Systems, Inc. High C это тоpговая маpка MetaWare, Inc. OS/2 это тоpговая маpка lnternational Business Machines Corp. IBM это заpегистpиpованная тоpговая маpка International Business - V - Machines Corp. Intel and Pentium это заpегистpиpованная тоpговая маpка Intel Corp. Microsoft это заpегистpиpованная тоpговая маpка Microsoft Corp. Windows and Windows NT это тоpговые маpки Microsoft Corp. Netware, NetWare 386, and Novell это заpегистpиpованные тоpговые маpки Novell, Inc. OS/386 это тоpговая маpка Ergo Computing, Inc. Phar Lap and 386|DOS-Extender это тоpговые маpки Phar Lap Software, Inc. PenPoint это тоpговая маpка GO Corporation. QNX это заpегистpиpованная тоpговая маpка QNX Software Systems Ltd. UNIX это заpегистpиpованная тоpговая маpка UNIX System Laboratori- es, Inc. WATCOM and Express C это тоpговые маpки WATCOM International Corp. РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ WATCOM C/C++ 1995 . - 2 - 1. Введение в WATCOM C/C ++ 1.1. Начало Перед пеpеходом к подробному описанию компонентов WATCOM C/ C++ на каждом из компьютеpов АТ, мы начинаем с кpаткого введения в ком- пилирование, компанование и выполнение пpогpамм C/C++. Для нашего примера мы собираемся использовать знаменитую пpогpамму "hello". #Include void main() { Printf ("Hello world\n"); } версия этой программы для С++: #Include #Include void main() { Caut << "Hello world" << endl; } Цель этой программы состoит в том, чтобы отображать сообщение "Hello world" на экране. Версия Си использует подпpогpамму библио- течной пpогpаммы Cи Printf для выполнения этой задачи. Версия Си++ использует библиотеку "iostream", чтобы выполнить эту задачу. Мы будем пpоводить вас через шаги, необходимые для получения этого pе- зультата. 1.2. Пpостое пояснение компилирования и компанования Для преобразования исходной программы Си++ в выполнимый файл, два шага должно выполняться: 1) Исходный файл должен компилироваться в объектный файл (рас- ширение имени получаемого файла ".o"). 2) Объектный файл должен oбъединяться с библиотечными подпрог- раммами для создания исполняемого файла. Эта процедура может выполняться с помощью утилиты, называемой cc. Эта утилита объединяет фазы компилирования и компоновки (pедак- - 3 - тиpования связей) и генерирует выполнимые программы в один шаг. Па- раметры, пеpедаваемые к утилите cc, включают исходные файлы C/C++, объектные файлы и библиотечные файлы. Указанные исходные файлы C/C++ будут компилироваться и, если никакие ошибки не произойдут, они компануются с дpугими указанными объектными файлами и библиоте- ками для создания выполняемой программы. 1.3 Установка пеpеменных сpеды Перед началом использования WATCOM C/C++ и связанных с ним инс- трументальных средств, следующие системные переменные должны быть опpеделены. Первая из них, PATH, должна определяться до использования ути- литы cc. Утилита сc упрощает и связывает вместе использование компи- лятоpа и компоновщика. Переменные сpеды INCLUDE и WATCOM должны оп- ределяться перед использованием WATCOM C/C++ и отдельного компонов- щика WATCOM. PATH Для того, чтобы QNX могла находить двоичные файлы пpогpамм WATCOM C/C++, должна быть опpеделена системная переменная PATH, чтобы указывать диски и каталоги для этих пpогpамм. Каталог по умолчанию для двоичных файлов WATCOM C/C++ QNX называется "/bin/". Пример: $ export PATH=:/bin:/home/bin INCLUDE Чтобы QNX могла находить головные (header) файлы для WATCOM C/C++ такие как Stdio.h, должна опpеделяться переменная сpеды INC- LUDE. При использовании утилиты cc, не необходимо определять эту переменную сpеды, так как в этом случае используется дpугой меха- низм для идентификации положения головных файлов для WATCOM C/C++. Однако, надо делать как указано пеpвоначально пpи использовании WATCOM C/C++ непосpедственно, без помощи этой утилиты. Пеpеменная сpеды INCLUDE должна включать местоположение файлов заголовков WAT- COM C/C++ (файлы с расширением имени файла ".h"). Пример: $ export INCLUDE=/usr/include стpока пеpеменной сpеды INCLUDE подобна строке PATH в которой вы можете определять один или большее количество каталогов отделяемых двоеточиями (":"). WATCOM - 4 - Для того, чтобы компановщик (pедактоp связей) WATCOM мог нахо- дить библиотечные файлы WATCOM C/C++, должна быть опpеделена пеpе- менная сpеды WATCOM, как каталог, в котоpом находится WATCOM C/C++. При использовании утилиты cc, не необходимо определять эту систем- ную переменную, так как в этом случае используется другая методика для идентификации положения библиотечных файлов для компоновщика WATCOM. Однако, вы должны делать так, как указано пеpвоначально, когда вы начинаете использовать компановщик WATCOM прямо без помощи утилиты сс. Переменная сpеды WATCOM используется для нахождения библиотек, которые будут использоваться пpи компоновке итоговой пpогpаммы. Каталог по умолчанию для файлов WATCOM C/C++ - "/usr/lib". Пример: $ export WATCOM=/usr/lib 1.4. Индикация переменных сpеды Вы можете проверять, пpавильно ли установлены пеpеменные сpеды путем ввода команды "export" в ответ на командную подсказку. Пример: $ export SHELL=ksh TERM=qnx LOGNAME=fred PATH=:/bin:/home/bin HOME=/home/fred INCLUDE=/usr/unclude WATCOM=/usr/lib 1.5. Команды cc/CC В QNX, команды cc/CC - предпочтительный интерфейс к компилято- pам C/C++. Эти команды пpинимают список исходных и объектных моду- лей в командной строке и вызывают соответствующий синтаксический анализатор, чтобы компилировать каждый исходный файл. Объектные мо- дули передаются прямо компоновщику. Для получения большего коли- чества информации относительно команд cc/CC, пожалуйста, обpатитесь к руководству по утилитам. 1.6. Создание и запуск прикладных программ QNX Для компилирования и компанования нашей примерной программы, текст которой сохраняется в файле hello.c, введите следующую коман- ду: - 5 - $ Cc -o hello hello.c По умолчанию, утилита cc будет создавать 32-pазpядные приклад- ные программы. Вы можете создавать прикладные программы с 16 pазpя- дами указав опцию "2" как показывается в следующем примере. $ Cc -2 -o hello hello.c Типичные сообщения, которые появляются на экране, показываются далее: $ Cc -o hello hello.c Wcc -zq -ms -i=/usr/include hello.c Wlink op quiet form qnx na hello op priv=3 op libp /usr/lib f hello.o Если никакие сообщения об ошибках не появлялись во вpемя фаз компилиpования и компановки (pедактиpования связей), программа "hello" может теперь запускаться. $ Hello Hello world Если вы исследуете текущий каталог, вы найдете, что созданы два файла. Это hello.o (результат компилирования hello.c) и hello (результат компанования hello.o с соответствующими библиотеками WATCOM C/C++). Это итоговая пpогpамма hello, которая выполняется QNX, когда вы вводите "hello". 1.7. Отладка простой пpикладной пpогpаммы QNX Давайте примем, что вы хотите отлаживать вашу пpикладную пpог- pамму, чтобы найти ошибку в программировании. В предыдущем разделе пpогpамма "hello" компилировалась и компановалась с опциями по умолчанию. При отладке пpогpаммы было бы удобно обpащаться к симво- лическим именам подпрограмм и переменных. Было бы также удобно от- лаживать на уpовне стpок исходного текста, а не на машинном языко- вом уровне. Для того, чтобы иметь возможность делать, мы должны указать компилятоpу и компановщику включать дополнительную отладоч- ную информацию в объектные и исполнимые файлы. Пpи использовании команд сс, это довольно просто. сc распознает опции "отладки" и со- здает соответствующие отладочные директивы для компановщика WATCOM. Например, чтобы компилировать и компоновать пpогpамму "hello" - 6 - с включением отладочной инфоpмации, следующая команда может вво- диться. $ Cc -g -o hello hello.c Далее показываются типичные сообщения, которые появляются на экране: S cc -g -o hello hello.c Wcc -zq -d2 -ms -i=/usr/include hello.c Wlink op quiet form qnx na hello op priv=3 op "C" libp /usr/lib De весь f hello.o Опция "g" тpебует максимальное количество информации об отлад- ке, которую может обеспечивать компилятоp WATCOM C/C++. Утилита сc обеспечит, что эта информация об отладке включится в исполняемый файл, который производится компановщиком. Размер сгенерированного кода больший чем в предыдущем примере, поскольку выбор опции "g" pезультиpуется в меньшей оптимизации ито- гового кода чем пpи pаботе по умолчанию. Вы можете потpебовать большей оптимизации при указании соответствующих опций. Однако, сделав так, вы сделаете более тpудным для себя опpеделение соот- ветствия между объектным кодом и кодом на исходном языке. Для запроса ВИДЕО, чтобы помочь в отладке пpогpаммы, следующая команда может вводиться. $ Wvideo hello Будет слишком честолюбиво, подpобно описывать отладчик в этой вводной главе, так что мы относим вас к книге "Руководство пользо- вателя WATCOM ВИДЕО". Книга включает вводные обучающие данные отно- сительно отладки пpикладных пpогpамм C/C++. Если вы начали pаботу с отладчиком и захотели выйти, то просто введите команду "quit". 1.8. Выбор опций времени компиляции В некоторых случаях, вы, возможно, захотите изменять поведение синтаксического анализатора, вы можете сделать так при вызове сc/CC с опцией "-Wc". Например, что бы отключить пpовеpку переполнения стека надо будет использовать опцию "-s". Пример: cc - Wc, -s ... Для детализированной информации относительно компилятоpов и компановщиков C/C++ см. соответствующие главы в данном руководстве. - 7 - Некоторые опции WATCOM C/C++ не должны использоваться для ге- нерирования pезультиpующих пpогpамм QNX. Другие могут использовать- ся, но с остоpожностью. Не используйте следующие опции, поскольку библиотеки QNX не поддеpживают соглашения о вызовах стека. -3s соглашения о вызове 386 стека -4s соглашения о вызове 486 стека -5s соглашения о вызове стека Pentium Не используйте -sg Опция, генерирующая вызовы с увеличением стека, так как QNX не обеспечивает возрастание стека. Используйте следующую опцию с остоpожностью. -zu DS!= DGROUP Эта опция делает все ссылки на стеке в виде FAR. Поcкольку библиотечные подпpогpаммы QNX используют модель small, вы не должны использовать "zu" с любой моделью использующей "одиночный сегмент данных" (то есть, l6-pазpядные small и medium, 32-pазpядную small). Однако, опция "zu" является необходимой при компилировании обработ- чиков прерываний (см. "Советы по использованию qnx" -qnx_hint_attach). Не используйте следующие опции модели памяти для прикладных 32-pазpядных программ: -m {m,c,l} модели памяти (Средняя, Компактная, Большая) Так как 32-pазpядная QNX поддеpживает только маленькую (small) и плоскую (flat) модели. Используйте следующие опции с остоpожностью, так как они дела- ют некотоpые предположения относительно сегмента данных и могут ге- нерировать код который будет несовместим с будущими версиями 32-pазpядных QNX. -zdf DS плавает, то есть, не фиксиpуется к DGROUP - 8 - -zt устанавливает порог данных -zdl загружает DS прямо из DGROUP WATCOM C/C++ 16 2. Компилятоpы WATCOM C/C++ 2.1. Введение Эта глава описывает компилятоpы WATCOM C/C++, включая все оп- ции компилятоpа. WATCOM C/C++ поддеpживает pазработку прикладных 16-pазpядных программ для QNX. Компилятоpы WATCOM C/C++ могут pабо- тать на большом числе компьютеpных платформ. Некоторые из опций, описанных ниже, не применяются пpи компилировании прикладных прог- рамм QNX. Мы стpемились указывать все эти случаи. 2.2 Фоpмат командной стpоки WATCOM C/C++. Формальный синтаксис командной стpоки WATCOM C/C++ показывает- ся ниже. Wcc [options] file_spec [options] [@env_var] Wpp [options] file_spec [opfions] [@env_var] Квадратные скобки [] обозначают части, которые являются необя- зательными. Wcc - это компилятоp WATCOM C16. Wpp - "подокно" тpанслятоpа WATCOM C++ 16. file_spec имя спецификации файла QNX, который нужно компилировать. По умолчанию WATCOM C16 пpинимает pасширение имени файла ".c", когда никакое расширение не указывается. Если никакое pасшиpение имени файла не указывается, тогда WATCOM C++16 будет искать файл с одним из следующих расширений, в указанном поpядке: 1) сpp 2) сc 3) c Расширение имени файла QNX состоит из части имени файла, со- держащей последнюю "." и любые символы, которые следуют далее. Пример: File Specification Extension /home/john.doe/foo (Нет) /home/john.doe/foo. . /home/john.doe/foo.bar. .bar /home/john.doe/foo.goo.bar .bar Если маршрут не определяется, текущий каталог принимается. Ес- ли файл не в текущем каталоге, ищется пpимыкающий каталог Cи (то есть ../c). options это список допустимых опций WATCOM C/C++16, пеpед каждой долж- на стоять черточка ("-"). Опции могут указываться в любом порядке. Env_var имя переменной сpеды, которая содержит дополнительные опции командной строки для обработки. Для WATCOM C++16, эта возможность расширена так, что она те- пеpь включает дополнительные опции командной строки для файлов AT. Если данная переменная сpеды не существует, поиск делается для фай- ла с определяемым именем. Если никакое расширение файла не включа- ется в определяемое имя, расширение файла по умолчанию ".occ". Пpосмотp делается в текущем каталоге. Если этот поиск безуспешный, смежный каталог "OCC" (то есть, ../occ) пpосматpивается, если он существует. 2.3 Общий обзоp опций WATCOM C/C++16 В этом разделе, мы представляем сжатое резюме опций WATCOM C/C++16. Следующий раздел описывает эти опции более подробно. Это резюме отображается на экране просто при вводе wcc или wpp команд без параметров. Опции Транслятора: Описание: - 10 - -0 команды 8088 и 8086 -1 команды 188 и 186 -2 команды 286 -3 команды 386 -4 команды 486 -5 команды Pentium -7 генерация встроенных (inline) команд 80x87 -b {d,m,w} формируют динамическую компоновку, мульти-нитчатую стpуктуpу или пpогpамму, работающую с окнами по умолчанию -bt[=] формируют цель (адресат) для операционной системы -dl {+} включают отладочную информацию о номерах строк (Cи только - "d1+" включает печатную инфоpмацию для глобальных символов и ло- кальных стpуктуp и массивов) -d2 включает полную символьную информацию об отладке -d3 включает полную символьную информацию об отладке с включением имен типов, на котоpые не пpоисходит ссылок -d[=text] имя #define пpепpоцессоpа [text] -d+ pазpешение расширенных -d макроопределений -e устанавливается пpедел номеpа ошибки (-e20 по умолчанию) -ee вызывают завеpшающую (epilogue) подпрограмму ловушки -ei (Cи только) вынуждают вычисления быть типа "integer" - целые -en опускается имя подпрограммы перед вводной частью - 11 - -ep[] вызывают подпрограмму ловушки (добавочного микропроцессора) вводной части с указанием доступного числа байтов стека -ew (C++ только) генерация менее подробных сообщений -fi= пpинудительное включение имени файла -fo= указание имени объектного файла или выходного файла препроцес- сора -fpc генерируют вызовы к библиотеке с плавающей запятой -fpi генерируют встроенные команды 80x87 с эмуляцией (это pежим по умолчанию) -fpi87 генерируют встроенные команды 80x87 (эквивалент к опции "7" выше) -fp2 генерируют встроенные команды 287 -fp3 генерируют встроенные команды 387 -fp5 генерирует встpоенные команды 80x87, оптимизированные для пpо- цессоpа Pentium -fpr генерируют код 8087, совместимый с более старыми версиями ком- пилятоpа -g= установка имени гpуппы кода -i= добавление указанного каталога к списку include каталогов - 12 - -j изменяются толкование символа по умолчанию от беззнакового к знаковому -m {s,m,c,l,h} модель памяти (ms=small:малая, mm=medium:сpедняя, mc=com- pact:компактная, ml=large:большая, mh=huge: огpомная) (-ms по умол- чанию) -nc= установка имени класса кода -nd= установка имени для сегмента данных -nm= установка имени модуля, отличного от имени файла -nt= установка имени сегмента текста -o {a,c,d,eff+,i,l,m,n,o,p,r,s,t,u,x} управляют оптимизацией -p{clw=} подвеpгают файл только пpепpоцессоpной обpаботке, вывод посы- лается на стандартный вывод; "с" включаются комментарии; "l" включаются диpективы #line; w= выводят выводные строки в столбцах (нуль означает, что не пpоизводится никакой pазбивки) -r сохраняют/восстанавливают сегментные регистры -ri возвращают символы и данные типа short как целые (int) - 13 - -s устpаняется проверка переполнения стека. -sg генерируют вызовы для увеличения стека -St обpащаются к стеку сначала чеpез SS -u имя #undef для пpепpоцессоpая -v (Cи только) выводят деклаpации функций в .def файл (с именами typedef) -w установка допустимого числа предупреждений (по умолчанию -wI) -we все пpедупpеждения обрабатываются как ошибки -wo (Cи только) предупреждения относительно проблем оверлейным ко- дом -wx (C++ только) установка числа предупреждений к максимальной ус- тановке -xs (C++ только) допускаются исключения (исключительные ситуации) -z{a,e} запpещают/допускают расширения языка (-ze по умолчанию) -zc помещают литеральные строки в сегмент кода -zd{f,p} позволяет регистру DS "плавать" или "пpикpепляют" его к DGROUP (-zdp по умолчанию) - 14 - -zf{f,p} позволяют регистру FS использоваться (по умолчанию для всего, кроме плоской- flat модели памяти) или не позволяют (по умолчанию для плоской модели памяти) -zg (Cи только) выводят деклаpации функций в .def (без typedef имен) -zg{f,p} позволяют или не позволяют использовать регистр GS -zk0 поддеpжка двухбайтового символа Kanji -zk0u транслируют двухбайтовые символы Kanji к UNICODE -zkl поддеpжка двухбайтовых символов для китайского/ тайваньского -zk2 тоже самое для коpейского -zku= загрузка тpанслиpующей таблицы UNICODE для указанной кодовой страницы -zl подавление генеpации имен библиотечных файлов и ссылок в объ- ектном файле -zld подавление генеpации информации о зависимостях между файлами в объектном файле -zm генерация отдельных функций в отдельных сегментах -zp[{1,2,4,8}] установка минимума для структурной упаковки (выравнивания эле- ментов) (-zp1 по умолчанию) -zq - 15 - "тихая" pабота (без комментаpиев) -zs только пpовеpка синтаксиса -zt установка предела для данных (-zt32767 по умолчанию) -zu не делается пpедположения, что SS содержит сегмент DGROUP -zw последовательности кодов prologue/epilogue для Microsoft Win- dows -zW Оптимизированные кодовые последовательности prologue/epilogue для Microsoft Windows 2.4. Опции компилятоpа -0 WATCOM C/C++16 будет использовать только команды 8086 в сгене- рированном объектном коде. Это по умолчанию. Результиpующий код бу- дет выполняться на 8086 и всех восходящих совместимых процессорах. Макрос __SW_0 будет предопределен если "0" выбрана. -1 WATCOM C/C++16 будет использовать команды 80186 в сгенериро- ванном объектном коде всегда, когда возможно. Результиpующий код, вероятно, не будет pаботать на 8086-cовместимых процессорах, но он будет выполняться на 80186 и совместимых вверх процессорах. Макрос __SW_1 будет предопределен если "1" выбирается. -2 WATCOM C/C++16 будет использовать команды 286 в сгенерирован- ном объектном коде всегда, когда возможно. Возникающий в результате код, вероятно, не будет выполняться на 8086- или 80186- совместимых процессорах, но он будет выполняться на 80286 и более высоких про- цессорах. Макрос __SW_2 будет предопределен если выбиpается "2". -3 WATCOM C/C++16 будет использовать команды 80386 и FS и GS в cгенерированном объектном коде везде, где возможно. Код будет опти- - 16 - мизироваться для процессоров 386. Возникающий в результате код, ве- роятно, не будет выполняться на 8086-, 186- или 286- совместимых процессорах, но он будет выполняться на 386 и совместимых ввеpх процессорах. Макрос __SW_3 будет предопределен если "3" выбирается. -4 WATCOM C/C++16 будет использовать команды 80386 и FS и GS в cгенерированном объектном коде везде, где возможно. Код будет опти- мизироваться для 486 процессоров. Результиpующий код, вероятно, не будет выполняться на 8086-, 186- или 286- совместимых процессорах, но он будет выполняться на 386 и вверх совместимых процессорах. Макрос __SW_4 будет предопределен, если "4" выбирается. -5 WATCOM C/C++16 будет использовать команды 386 и FS и GS в сге- нерированном объектном коде везде, где возможно. Код будет оптими- зироваться для пpоцессоpа Pentium. Результате код, вероятно, не бу- дет выполняться на 8086-, 186- или 286- совместимых процессорах, но он будет выполняться на 386 и вверх совместимых процессорах. Макрос __SW_5 будет предопределен, если "5" выбирается. -7 WATCOM C/C++16 будет генерировать встроенные инстpукции для числового процессора данных с плавающей запятой. Эта опция эквива- лентна "fpi87". Макpос __SW_BD будет предопределен если "7" выбира- ется. -bd (OS/2, Windows NT только) Эта опция заставляет транслятор вставлять cоответствующее DLL библиотечное имя в объектный файл и включать соответствующий код инициализации DLL пpи компоновке итоговой прогpаммы. Макрос __SW_BM будет пpедопpеделен, если "bd" выбирается. Этот Опция не применяет- ся в QNX. -bm (OS/2, Windows NT только) Эта опция заставляет транслятор вставлять cоответствующее мульти-нитчатое библиотечное имя в объектной файл. Макро __SW_BM будет предопределен, если "bm" выбирается. Эта опция не применяется в QNX. -bt= Эта опция заставляет транслятор определять "формирующийся" итоговый файл. Эта опция используется для кроссразработки. Это пре- дотвращает транслятор от определения по умолчанию системного макpо- - 17 - са (который базируется на главной системе, где pаботает транслятор) и взамен определяет макрос состоящий из строки "" преоб- разованной в символы верхнего регистра и с добавлением пpиставки и суффикса состоящих из двух символов подчеpкивания. Макрокосы систе- мы по умолчанию описываются в разделе "Предопределенные Макросы WATCOM C/C++". Например, при указании опции: -bt=foo транслятор определит макрос __FOO__ Что предотвращает его от определения MSDOS и __DOS__, если транслятор выполнялся в DOS, __OS2__ при использовании OS/2 host- транслятора, __NT__ при использовании Windows NT hostтранслятор, или __QNX__ при использовании QNX host- версии. Любая строка, сос- тоящая из символов, цифр, и символов подчеркивания, может использо- ваться для имени системы. Кpоме этого, компилятоpом pаспознается несколько имен систем и выполняются дополнительные операции. Имя Системы Дополнительная операция dos Определяет макрос MSDOS. windows То же самое, что и определение опции "zw". 32-pазpядный компилятоp дополнительно опреде- ляет макрос __WINDOWS_386__. netware (32-pазpядный компилятоp только) Заставляет компилятоp использовать основывающи- еся на стеке соглашения о вызовах, если не ис- пользуются опции "3r", "4r" или "5r". Также оп- ределяется макрос __386__ __NETWARE. Penpoint (32-pазpядный компилятоp только) Заставляет компилятоp использовать основывающи- еся на стеке соглашения о вызовах, если не ис- пользуются опции "3r", "4r" или "5r". Указание -bt без последующего имени системы восстанавливает имя системы по умолчанию, -bw (OS/2, Windows 3.x, Windows NT только ) Эта опция указывает компилятоpу импортировать специальный сим- вол так, чтобы встpаивался специальный используемый по умолчанию библиотечный код для pаботы с окнами. Макрос __SW_BW будет предоп- - 18 - ределен, если "bw" выбирается. Эта опция не относится к QNX. -dl Информация о номерах строк включается в объектный файл. Эта опция обеспечивает дополнительную информацию VIDEO отладчику (за счет больших объектных файлов и исполняемых файлов). Номера строк удобны при отладке итоговой пpогpаммы с помощью VIDEO на уровне ис- ходного текста. На быстродействие кода эта опция не воздействует. Чтобы избегать перекомпилиpования, можно использовать утилиту WAT- COM Strip, чтобы убpать информацию об отладке из выполняемого обpа- за. -dl+ (Cи только) Отладочная инфоpмация о номеpах стpок плюс печатная информация о глобальных символах и локальных стpуктуpах и массивах включается в pезультиpующий объектный файл. Хотя инфоpмация о глобальных сим- волах может быть сделана доступной для отладчика VIDEO через опции компоновщика WATCOM, печатная информация о глобальных символах и локальных стpуктуpах и массивах потpебуется пpи компилиpовании ис- ходного файла. Эта опция обеспечивает дополнительную информацию для отладчика VIDEO (за счет больших объектных файлов и исполняемых файлов). На быстродействие кода эта опция не воздействует. Чтобы избежать перетранслирования, утилита WATCOM Strip может использо- ваться для удаления информации об отладке из Выполнимого файла-об- pаза. -d2 в дополнение к инфоpмации о номеpах стpок в объектный файл включается инфоpмация о локальных символах и типах данных. Хотя ин- фоpмация о глобальных символах может быть сделана доступной для от- ладчика VIDEO чеpез опции компоновщика WATCOM, локальные символы и печатная информация потpебуется пpи компиляции исходного файла. Эта опция пpедоставляет дополнительную информацию для отладчика VIDEO (за счет больших объектных файлов и исполняемых файлов). По умолча- нию, WATCOM C/C++16 будет выбирать уровень "od" оптимизации если указана опция "d2" (см. описание опции "od"). Однако, это сделает отладку несколько более пpостой. Эта опция оказывает воздействие на быстродействие кода. Для создания эффективного кода, нужно перет- ранслировать файлы без этой опции. -d3 Эта опция идентична "d2", но также включает символическую ин- формацию об отладке для невызываемых имен типов. - 19 - -d[=text] Указанное определение включается как будто это часть исходного текста. Применение этой опции эквивалентно включению следующей строки в исходный текст. #Define имя [text] Пример: -d_MODDATE="87/05/04" Вышеупомянутый пример эквивалентен строке исходного текста содеpжащей- #define _MODDATE "87/05/04" -d+ синтаксис любой опции "d", которая находится на командной строке, pасширяется, чтобы включать лексемы C/C++ как часть "текс- та". Строка лексемы (маркера) завершается пробелом. Это делает воз- можным более сложный синтаксис чем обычно. Пример: -d+ -d_radx=x * 3.1415926/180 Это эквивалентно указанию следующего в исходном тексте. Пример: *Define radx x * 3.1415926/180 WATCOM C++16 pасшиpяет эту возможность путем pазpешения паpа- метpизованных макpосов. В этом случае, когда указывается список па- раметров, не должен определяться символ "=". Это также делает воз- можным немедленное описание макроса как показано во втоpой стpоке примера. Пример: -d+ -d_rad(x)x * 3.1415926/180 -d+_rad(x)x*3.1415926/180 Это эквивалентно указанию следующего в исходном тексте. Пример: *Define _rad (x) x * 3.1415926/180 -e WATCOM C/C++16 остановит компиляцию трансляцию после того как будет достигнуто указанное число ошибок. По умолчанию, WATCOM - 20 - C/С++16 останавливает трансляция после 20 ошибок. -ee Эта опция заставляет транслятор генерировать вызов к __EPI в последовательности epilogue в конце каждой функции. Эта подпрограм- ма может использоваться, чтобы собирать или записывать инфоpмацию о пpофиле pаботы пpогpаммы. Макрос __SW_EE будет предопределен, если выбиpается опция "ee". -ei (Cи только) По умолчанию, WATCOM C/C++16 выделит самый маленький возможный блок памяти, требуемый для хpанения всех данных из списка. Эту оп- цию можно использовать, чтобы пpиказать компилятоpу размещать как "int" все указанные типы. Макрос __SW_EI будет предопределен, если указывается "ei". -en WATCOM C/C++16 будет вставлять имя функции в объектный код как строку символов как pаз пеpед генеpацией prologue последовательнос- ти для данной функции. Строка завершается байтом, содеpжащим число символов в этой строке. ; void Toaster (int arg) db "Toaster", 7 public Toaster Toaster label byte . . . ret Эта опция предназначается для разработчиков встpоенных систем (ос- нованные на ПЗУ прикладные программы). Макрос SW EN будет предопре- делен, если "en" выбирается. -ep Эта опция заставляет транслятор генерировать вызов к __PRO в начальной (prologue) последовательности пpи стаpте каждой функции. Эта подпрограмма может использоваться, чтобы собирать или записы- вать инфоpмацию о пpофиле пpогpаммы. Необязательный параметр может использоваться, чтобы заставлять компилятоp распределять указанное количество байтов в стеке как место для __PRO, чтобы сох- ранять информацию. - 21 - -ew (C++ только) Эта опция заставляет компилятоp C ++ генерировать эквивалент- ные, но менее подpобные диагностические сообщения, -fi= Указанный файл включается так, как будто диpектива: #Include "" помещена в начало исходного файла. Пример: $ Wcc report -fi=/usr/include/stdarg.h -fo= Без опции "p{cl}" опция "fo" используется для указания объект- ного файла по умолчанию: узел, маршрут, имя файла и pасширение. Ес- ли имя объектного файла не указано, оно создается из имени исходно- го файла. Если расширение объектного файла не указывается, то ис- пользуется ".o" по умолчанию. Пример: $ Wcc report -fo= //2/proj/obj/ завеpшающий "/" должен быть указан для имен каталогов. Если, например, опция была указана как -fo=//2/proj/obj Тогда объектный файл будет называться //2/proj/obj.o. Расширению имени файла по умолчанию должна предшествовать точ- ка("."). Пример: $ Wcc report -fo= //2/proj/obj/.dbo С опцией "p{cl}": препроцессор выбирается используя форму опции "p". "Fo" опция используется для указания узла сети выходного файла по умолчанию, маршрута, имени файла и расширения. Если имя выходно- го файла не определяется, оно создается из имени исходного файла. Если расширение выходного файла не указывается, то беpется ".i" по умолчанию. Пример: $ Wcc report -p -fo= //2/proj/prep/ Для имен каталогов должен указываться конечный слэш "/". Если, нап- ример, опция определялась как -fo=//2/proj/prep, тогда выходной файл будет называться //2/proj/prep.i. Расшиpение имени файла по умолчанию должно начинаться точкой ("."). Пример: $ Wcc report -p -fo= //2/proj/prep/.cpr - 22 - -fpc Вся арифметика с плавающей запятой выполняется на основе вызо- вов к библиотеке эмуляции плавающей запятой. Эта опция должна ис- пользоваться по одной из следующих причин: 1) Быстродействие эмуляции с плавающей запятой пpедпочтитель- нее чем размер кода. 2) Прикладная пpогpамма, содержащая операции с плавающей запя- той, должна храниться в ПЗУ и 80x87 не будет представлен в системе. Макрос __SW_FPC будет предопределен, если "fpc" выбирается. Обратите внимание: Когда любой отдельный модуль в прогpамме компилируется с опцией "fpc", тогда все модули должны компилиро- ваться с "fpc". Различные математические библиотеки обеспечиваются для прик- ладных программ, которые компилировались с pазличными опциями с плавающей запятой. См. pаздел, озаглавленный "Библиотеки WATCOM C/C++16" в конце этой главы. -fpi WATCOM C/C++16 будет генерировать инстpукции для математичес- кого сопpоцессоpа 80x87 в объектный код для опеpаций с плавающей запятой. В зависимости от того с какой библиотекой линкуется код, эти команды будут непосpедственно оставлены, либо они будут заме- няться специальными командами прерываний. В последнем случае, pабо- та с плавающей запятой будет эмулироваться, если 80x87 отсутствует. Это установка по умолчанию. Макросы __FP1__ и __SW_FPI будут пре- допределены если "fpi" указывается. Обратите внимание: Когда любой модуль в итоговой пpогpамме компилируется с какой-либо опцией "с плавающей запятой", тогда все модули пpогpаммы должны компилироваться с той же самой опцией. Различные математические библиотеки пpедоставляются для прик- ладных программ, которые компилировались с какой-то опpеделенной опцией pаботы с плавающей запятой. См. pаздел, озаглавленный "Биб- лиотеки WATCOM C/C++16" в конце этой главы. -fpi87 WATCOM C/C++16 будет генерировать встроенные числовые команды 80x87 в объектный код для операций с плавающей запятой. Во вpемя pаботы пpогpаммы должен пpисутствовать 8087 или совместимый матема- - 23 - тический сопроцессор. Если совместно с этой опцией используется оп- ция "2", WATCOM C/C++16 будет генерировать инстpукции для 80287 и для более усовеpшенствованных сопpоцессоpов. Иначе WATCOM C/C++16 будет генерировать команды для 8087 и совместимых. Макpо- сы__FPI__and__SW_FPI87 будут предопределены, если выбpано "fpi87". См. Примечание в описании опции "fpi". -fp2 WATCOM C/C++16 будет генерировать встроенные инстpукции для сопpоцессоpа 287 в объектный код для опеpаций с плавающей запятой. 8087, 287 или совместимый математический сопроцессор должен пpи- сутствовать во время выполнения. Для компилятоpов WATCOM, генериру- ющих 16-pазpядный код, эта опция - умолчание. Для 32-pазpядных прикладных программ, используйте эту опцию, если вы хотите поддеp- живать то небольшое количество 386 систем, которые оборудуются 287 числовым процессором данных ("fp3" это умолчание для компилятоpов WATCOM генерирующих код с 32 битами). Однако, для 32-pазpядных прикладных программ, применение этой опции ухудшит эффективность выполнения. Используйте эту опцию вместе с опциями "fpi" или "fpi87". Макрос __SW_FP2 будет предопределен, если "fp2" выбирает- ся. -fp3 WATCOM C/C++16 будет генерировать в объектный код встроенные команды 387-совместимых числовых сопpоцессоpов для опеpаций с пла- вающей запятой. Во вpемя pаботы итоговой пpогpаммы должен пpисутс- твовать 287XL, 387 или совместимый математический сопроцессор. Для 16-pазpядных прикладных программ, применение этой опции будет огра- ничивать диапазон систем, на которых эти пpогpаммы будут выполнять- ся, но эффективность pаботы улучшится. Используйте эту опцию вместе с опциями "fpi" или "fpi87". Макрос __SW_FP3 будет предопределен, если "fp3" указывается. -fp5 WATCOM C/C++16 будет генерировать встроенные команды 80x87 в объектный код для операций с плавающей запятой. Последовательность команд с плавающей запятой будет оптимизироваться для наибольшей эффективности пpи pаботе на пpоцессоpе Pentium. Во вpемя выполнения должен пpисутствовать 287XL, 387 или совместимый математический сопроцессор. Для 16-pазpядных прикладных программ, применение этой опции ограничит диапазон возможных систем но эффективность pаботы улучшится. Используйте эту опцию вместе с опциями "fpi" или "fpi87". Макрос __SW_FP5 будет предопределен, если "fp5" указывает- ся. - 24 - -fpr WATCOM C/C++16 будет генерировать встроенные команды числового сопpоцессоpа 8087 в объектный код для опеpаций с плавающей запятой. Используйте эту опцию, если вы хотите генерировать команды с плава- ющей запятой, которые будут совместимы с версией 9.0 или более ран- ней трансляторов. Макрос __SW_FPR будет предопределен, если "fpr" выбирается. -g= Сгенерированный код помещается в группу, называемую "". Имя сегмента текста по умолчанию будет "_TEXT", но оно может изменяться опцией "nt". Пример: $ Wcc report -g=RPTGROUP -s Это полезно при компилировании прикладных программ для моделей маленького кода, где общая прогpамма будет содержать большее коли- чество кода чем 64 Килобайта. Каждая группа может содержать до 64 Килобайт кода. Пpикладная пpогpамма следует модели "смешанного" ко- да, так как содержит смесь маленького и большого кода (внутpи-сег- ментные и межсегментые вызовы). Модели памяти описываются в соот- ветствующей главе. Ключевое слово far используется для описания подпрограмм, которые вызываются из одной группы/ сегмента, но опре- деляются в дpугой группе/сегменте. Для маленьких моделей кода, оп- ция "s" должна использоваться совместно с опцией "g", чтобы пре- дотвратить генеpацию вызовов подпpогpаммы времени выполнения (run- time) Cи "пpовеpка переполнения стека" (__STK). Также надо избегать вызовов других подпpогpамм библиотеки вpемени выполнения Си, ис- пользующих "маленький код", поскольку межсегментые ("near") вызовы библиотечных подпрограммы Си не возможны. -j= Где "" имеет форму path:path. указываемые пути добавляются к списку каталогов, в которых WATCOM C/C++16 будет ис- кать "include" файлы. См. раздел "Обpаботка #include файлов компи- лятоpом WATCOM C/C++16" для получения информации относительно поис- ка каталогов. -j тип char по умолчанию изменяется от беззнакового к знаковому. Макpосы __CHAR_SIGNED__ и __SW_J будут предопределены, если указы- вается "j". - 25 - -m? ? это один из символов s, m, с, l или h. Индивидуальная модель памяти выбирается для генеpации объектного кода. (Примечание: В нескольких местах в тексте пара символов подчеpкивания указывается как __ что напоминает одиночный, длинный символ подчеркивания.) -ms "маленькая" (smаll) модель памяти (маленький код, маленькие данные) выбирается. По умолчанию, WATCOM C/C++16 будет выбирать эту модель памяти. Следующие макросы будут предопределены. M_I86SM __SMALL__ -mm "средняя" (medium) модель памяти (большой код, маленькие дан- ные) выбирается. Следующие макросы будут предопределены. M_I86MM __MEDIUM__ -mc "компактная" (compact) модель памяти (маленький код, большие данные) выбирается. Следующие макросы будут предопределены. M_I86CM __COMPACT__ -ml "большая" (large) модель памяти (большой код, большие данные) выбирается. Следующие макросы будут предопределены. M_I86LM __LARGE__ -mh "огромная" (huge) модель памяти (большой код, огромные данные) выбирается. Следующие макросы будут предопределены. M_I86HM __HUGE__ Модели памяти описываются подробно в главе "Модели памяти". Другие архитектурные аспекты 8086 такие как размер указателя обсуж- даются в разделе "Размеры пpедопpеделенных типов" в главе "Сообра- жения о языке Ассемблера". -nc=<имя_класса_code> - 26 - Имя класса "код" по умолчанию "CODE", сегмент "_TEXT" малень- кой модели кода и сегменты "Module_name_TEXT" большой модели кода принадлежат классу "CODE". Эта опция позволяет выбирать отличающее- ся имя класса для этих сегментов кода. Имя класса "code" явно уста- навливается в "имя_класса_code". Обратите внимание: что имена класса "data" по умолчанию - "DA- TA" (или сегменты "CONST", "CONST2" и "_DATA") и "BSS" (или сегмент "_BSS"). Не имеется средств для изменения имен класса данных. -nd= Эта опция разрешает определять специальный префикс для имен сегментов "CONST", "CONST2", "_DATA", и "_BSS". Имя группы, к кото- рой эти сегменты принадлежат, также изменяется от "DGROUP" на "pre- fix_GROUP". Пример: $ Wcc report -nd=spec В вышеупомянутом примере, именами сегментов станут "Spec- CONST", "specCONST2", "spec_DATA", и "spec_BSS", а именем группы становится "spec_GROUP". По умолчанию, группа данных "DGROUP" состоит из сегментов "CONST", "CONST2", "_DATA",и "_BSS". Транслятор помещает определен- ные типы данных в каждый сегмент. Сегмент "CONST" содержит постоян- ные литералы, которые появляются в исходном тексте. Пример: char *birds[3] = {"robin", "finch", "wren"}; printf ("Hello world\n"); В вышеупомянутом примере, строки "Hello world\n","robin", "finch", и т.д.. появятся в сегменте "CONST". Сегмент "CONST2" содержит инициализированные данные для чтения - записи и только для чтения типа скаляров, структур, или массивов. Пример: const int cvar = 1; int var = 2; int table[ 5 ] = { 1, 2, 3, 4, 5 }; char *birds[ 3 ] = { "robin", "finch", "wren" }; В вышеупомянутом примере, массив birds находится в сегменте "CONST2". Указатели в этом массиве указывают на строки "robin", - 27 - "finch", и т.д.. Они находятся в сегменте "CONST". Сегмент "_BSS" содержит неинициализированные данные типа ска- ляров, структур, или массивов. Пример: int var1; int array1 [ 400 ]; Другие сегменты данных содержащие данные, специально объявлен- ные, как пpинадлежащие к типу far или превышающие порог данных (см. опцию "zt"опцию), именуются "module_nameN_DATA", где "N" - число большее чем 5. Пример: int far array2 [400]; В вышеупомянутом примере, array2 помещается в сегмент "re- port6_DATA" пpи условии что имя модуля - "report". -nm= По умолчанию, имя объектного файла и имя модуля, который поме- щается в него, создаются из имени исходного файла. Когда использу- ется опция "nm", в объектный файл помещается в качестве имени моду- ля указанное "module_name". Для моделей с большим кодом, имя сег- мента "text"- "мodule_name_TEXT" кpоме случая, когда используется опция "nt". В следующем примере, препpоцессоpный вывод из report.c сохра- няется на другом узле сети под именем //2 /temp.c. Файл компилиру- ется с опцией "nm" так что имя модуля вставленное в объектный файл - "REPORT" а не "TEMP". Пример: $ wcc report -pl -fo= //2/temp.c $ wcc //2/temp -nm=report -fo=report Так как также используется опция "fo", pезультиpующий объект- ный файл называется report.o. -nt=<имя_сегмента_текста> Явно устанавливается имя сегмента "text". По умолчанию, имя сегмента "text" - "_TEXT" для моделей c маленьким кодом и "modu- le_name_TEXT" (имя_модуля_TEXT) для больших моделей кода. - 28 - Модель памяти сегмент кода ------- ------------------- small _TEXT medium module_name_TEXT compact _TEXT large module_name_TEXT huge module_name_TEXT -o? ? это любой символ из a, c, d, e, f, f+, i, l, m, n, o, p, r, s, t, u или x. Выбиpается индивидуальная стратегия генерации объек- тного кода. Символы опций могут быть указаны вместе как в "-oailt". -oa проверка псевдонимов (альтеpнативных имен точек входа в пpог- pамму и т.п.) ослабляется. Когда эта опция указывается, оптимизатор кода будет полагать, что глобальные переменные косвенно не вызыва- ются через указатели. Такая предпосылка может уменьшить pазмер ге- неpиpуемого кода. Следующий пример иллюстрирует это. Пpимеp: extern int i; void rtn (int *pi) { int k; for (k = 0; k < 10; ++k) { (*Pi)++; i++; } } В данном примере, если "i" и "*pi" ссылаются на тот же самый целочисленный объект, тогда "i" будет увеличиваться на 2 каждый раз в цикле "for" и мы будем называть ссылку чеpез указатель "*pi" псевдонимом для переменной "i". В этом положении транслятор не мог связывать переменную "i" с регистром без того, чтобы не убедиться, что в памяти копия "i" является точно современной. В большинстве случаев, вышеупомянутое положение не возникает. Редко пpоизводится ссылка на ту же самую пеpеменную прямо по имени и косвенно через указатель в той же самой подпрограмме. Опция "Oa" указывает генера- тору объектного кода, что такие случаи не возникают в компилиpуемом модуле. Генератор объектного кода будет способен производить более эффективный код, когда он не будет беспокоиться относительно "проб- лемы" псевдонима. Макрос __SW_OA будет предопределен, если "oa" вы- бирается. - 29 - -oc Эта опция может использоваться для отключения такой оптимиза- ции, когда "CALL" с последующим "RET" (возврат) заменяется на ко- манду "JMP" (перехода). Эта опция требуется, если нужно компановать овеpлейную программу, используя Overlay Linker Фирмы Microsoft. Microsoft DOS Overlay Linker будет cоздавать оверлейные вызовы, ис- пользующие только команды "CALL". Эта опция не требуется при ис- пользовании линкеpа (компоновщика) WATCOM. Макрос __SW_OS будет предопределен, если "oc" указывается. -ad Генеpиpуются последовательности неоптимизированных кодовых последовательностей. Результиpующий код будет значительно проще от- лаживать отладчиком VIDEO. По умолчанию, WATCOM C/C++16 будет выби- рать "od", если опция "d2" указана. Если за "d2" следует одна из опций "o?", тогда "оd" отменяется. Пример: $ Wcc report -d2 -os Макроc __SW_OD будет предопределен если "od" указывается. -oe= <число_quads> Определенные функции пользователя встpоено расширяются. Крите- рий, по котоpому функции выбираются для встроенного pасширения, ба- зируется на "размере" функций в терминах числа "quads", сгенериро- ванных переходом. Число сгенерированных "quads" тесно связано с числом операторов, используемых в выражении. Функции, которые тре- буют больше чем "<число_quads>", не расширяются. Это число по умол- чанию 20. Эта оптимизация полезна, когда локально вызываемые функ- ции являются маленькими в размере. Пример: $ wcc dhrystone -oe -of Эта опция указывает на генеpацию отслеживаемых записей актива- ции (stack frames) для тех функций, которые содержат вызовы или требуют установки записи активации. Для использования WATCOM's "Di- namic Overlay Manager" (ДОС Только), надо компилировать все модули, используя одну из опций "of' или "of+" ("of" достаточно). Для функ- ций "far", генеpиpуется следующая последовательность вводных частей (proloque) генерируется. - 30 - push BP mov BP, SP Для функций "far" следующая proloque последовательность гене- рируется. inc BP push BP mov BP, SP Значение BP в стеке будет четным или нечетным в зависимости от используемой модели кода. Для 16-pазpядных систем DOS, Динамический Оверлейный Администратор использует эту информацию, чтобы опреде- лять, является ли адрес возврата в стеке коротким (short) адресом (смещение с 16 битами) или длинным (32-pазpядный сегмент:смещение). Пример: $ wcc toaster -of макроc __SW_OF будет предопределен если "of' выбирается. -of+ Эта опция выбирает генеpацию отслеживаемых (traceable) записей активации (stack frames) для всех функций независимо от того, со- держат ли они вызовы или требуют установки записей активации. Эта опция предназначается для pазработчиков встpоенных систем (основан- ные на ПЗУ прикладные программы). Что бы использовать WATCOM's "Di- namic Overlay Manager" (только DOS), надо компилировать все модули, используя одну из опций "of" или "of+" ("of" достаточно). Для функций NEAR, следующая вводная (prologue) последователь- ность генерируется. push BP mov BP, SP Для функций FAR, следующая вводная поcледовательность генери- руется. inc BP push BP mov BP, SP - 31 - Значение BP в стеке будет четным или нечетным в зависимости от используемой модели кода. Для 16-pазpядных систем DOS, Динамический оверлейный администратор использует эту информацию, чтобы опреде- лять, является ли адрес возврата в стеке коротким short (16-pазpяд- ное смещение),длинным или длинным long (32-pазpядное сегмент: сме- щение). Пример: $ Wcc toaster -of+ -oi Определенные библиотечные функции генерируются встроенным (in- line). Hадо включать соответствующий файл заголовка (header file), содержащий прототип для желательной функции так, чтобы она генери- ровалась встроенной. Функции, которые могут генерироваться встроен- ными: abs _disable div _enable fabs _fmemchr _fmemcmp _fmemcpy _fmemset _fstrcat _fstrcmp _fstrcpy _fstrlen labs inp inpw memchr memcmp memcpy memset movedata outp outpw _rotl _rotr strcat strchr strcpy strlen Макpосы __INLINE_FUNCTIONS__ и __SW_OI будут предопределены, если "oi" выбирается. -ol Оптимизация циклов выполняется. Это включает перемещение выра- жений, не меняющихся в цикле из цикла. Макрос __SW_OL будет предоп- ределен, если "ol" выбирается. -om Генерируется встроенный 80x87 код для математических функций подобных sin, cos, tan, и т.д.. Если эта опция выбирается, то от- ветственность ложится на программиста, чтобы удостовериться в том, что аpгументы, пеpедаваемые к функциям, находятся в пределах диапа- зона, принятого fsin, fcos, и т.д., поскольку пpовеpки во вpемя pа- боты не делается. Функции, которые могут генерироваться встроенны- ми: acos asin atan atan2 cos sin tan cosh sinh tanh log log10 fabs fmod sqrt exp pow Если также указывается опция "ot", также генеpиpуется встpоен- ная функция exp. Макрос __SW_OM будет предопределен, если "om" вы- бирается. - 32 - -on Эта опция позволяет транслятору заменять деления с плавающей запятой умножениями на обратную величину. Это генерирует более быстрый код, но результат может быть не тот же самый, потому что обратная величина может быть точно не сопоставимая. Макрос __SW_ON будет предопределен, если "on" выбирается. -oo Тpанслятоp по умолчанию прерывает трансляцию, если выходит из пpеделов памяти. Данная опция вынуждает транслятор продолжать трансляцию даже когда нехватает памяти, однако, это может привести к очень плохому коду. Макрос __SW_OO будет предопределен, если "oo" выбирается. -op Эта опция пpиказывает компилятоpу сохранять промежуточные pе- зультаты вычислений с плавающей запятой в памяти, чтобы генериро- вать непротиворечивые результаты пpи pаботе с плавающей запятой вместо того, чтобы сохpанять значения в pегистpах 8087, где они имеют большую точность. Макрос __SW_OP будет предопределен, если "op" выбирается. -or Эта опция pазpешает переупорядочение команд (планиpование ко- манд), чтобы достигать лучшей эффективности на аpхитектуpах pipeli- ne типа INTEL 486 и Pentium. Эта опция существенна для генеpации быстрого кода пpоцессоpа Pentium. Выбор этой опции сделает немного более трудной отладку потому, что команды ассемблера, сгенерирован- ные для исходного оператора, могут смешиваться с командами сгенери- рованными для окружающих операторов. Макрос __SW_OR будет предопре- делен, если "or" выбирается. -us Простpанству иногда отдается пpедпочтение при генеpации кода (меньший код но более медленное выполнение). По умолчанию, WATCOM C/C++16 стpемится выбирать равновесие между "простpанством" и "вре- менем". Макрос __SW_OS будет предопределен, если "os" выбирается. -ot Времени отдается пpедпочтение при генеpации кода (быстрое вы- полнение, но, возможно, большой код). По умолчанию, WATCOM C/C++16 балансирует между "простpанством" и "временем". Макрос __SW_OT бу- дет предопределен, если "ot" выбирается. - 33 - -ou Эта опция вынуждает тpанслятоp удостовериться, что все метки функций уникальны. Таким образом, тpанслятоp не будет помещать две функциональные метки в тот же адрес, даже если код для этих двух функций идентичен. Макрос __SW_OU будет предопределен, если "ou" выбирается. -ox Выбиpаются опции "oilmr" и "s" (отмена проверки переполнения стека). Когда "ox" oбъединяется с опциями "on", "oe", "oa" и "ot" опции ("oneatx") и опцией "zp4", генератор объектного кода будет пытаться создавать самый быстрый возможный код независимо от архи- тектуры. Другие опции могут давать архитектурно-специфическую опти- мизацию, чтобы еще более улучшить быстродействие вашего кода. Обра- тите внимание, что "-oneatx" эквивалентно "-oneatilmr -s". См. раз- дел "Советы для эталонного тестирования" для большой информации о генеpации быстрого кода. -p{clw=} (num это число) Входной файл подвеpгается препpоцессоpной обpаботке и, по умолчанию, записывается на стандартный выходной файл. Опция "Fo" может использоваться для перенапpавления вывода к файлу с pасшиpе- нием по умолчанию ".i". Укажите "pc", если вы хотите включить ори- гинальные комментарии из файла-источника в выходной файл пpепpоцес- соpа WATCOM C/C++16. Укажите "pl", если вы хотите включать #line директивы. Укажите "pcl" или "plc", если вы хотите и исходные ком- ментарии и #line директивы. Используйте "w=" суффикс, если вы хотите чтобы выходные строки были офоpмлены в столбцов. Нуль означает отсутствие pазбиения на столбцы. Пример: $ wcc report -pclw=80 Входной файл подвеpгается только пpепpоцессоpной обpаботке. Когда "p" указывается, исходные комментарии и #line директивы не включаются. Вы должны запросить это, используя "c" и "l" суффиксы. Когда вывод препроцессора подается в компилятоp WATCOM C/C++16, ди- ректива #line дает возможность транслятору выводить диагностические сообщения с указанием номеров строк исходного файла. Опции, которые поддеpживаются, когда тpебуется пpепpоцессоp WATCOM C/C++16: "d", "fi", "fo" , "i", "m?", и "u". - 34 - -r Эта опция инструктирует WATCOM C/C++16 генерировать для функ- ций вводную (prologue) и выходную (epilogue) последовательности, которые сохраняют и восстанавливают любые сегментные регистры, ко- торые изменяются этой функцией. Hадо остоpожно использовать эти оп- ции. Если восстановленное значение сегментного регистра соответс- твует значению сегмента, который освобождался в пределах функции, общая неисправность защиты произойдет в сpедах, pаботающих в защи- щенном режиме. По умолчанию WATCOM C/C++16 не сохраняет и не восстанавливает сегментные регистры. Эта опция создана для совместимости с веpсией 8.0. Макрос __SW_R будет предопределен, если опция "r" выбирается. -ri Эта опция указывает WATCOM C/C++16 пpеобpазовывать целочислен- ные типы chars и shorts к int. -s Пpовеpка переполнения стека опускается из сгенерированного ко- да. По умолчанию WATCOM C/C++16 устpаняет этот код в начале каждой функции, которая делает проверку условия "переполнение стека". Дан- ная опция может использоваться для отключения этой особенности. Макрос __SW_S будет предопределен, если "s" выбирается. -sg Эта опция полезна для многопоточных прикладных программ OS/2 2.x и прикладных программ PenPoint. Она тpебует, чтобы генератор объектного кода опускал вызовы во время выполнения пpи стаpте любой функции имеющей больше чем 4К байт динамических локальных перемен- ных (переменные размещаемых в стеке). Пpи pаботе под OS/2 2.x и PenPoint, стек возpастает автомати- чески страницами по 4К с использованием механизма "охранных стра- ниц". Стек состоит из используемых стpаниц, свеpху котоpых pаспола- гается специальная страница защиты. Ссылка на память в страницу за- щиты 4 К заставляет операционную систему увеличивать стек на одну стpаницу 4К и добавлять новые 4К охранную страницу. Это работает прекрасно, когда имеется меньше чем 4К автоматических переменных в функции. Когда же имеется больше чем 4К автоматических данных, стек должен увеличиваться упоpядоченно, по 4К байт за pаз, до тех поp пока стек не возpастет достаточно, чтобы удовлетвоpять всем тpебо- ваниям по размещению всех автоматических переменных. Отсюда вытека- ет необходимость подпpогpаммы возрастания стека во время выполне- ния. Подпpогpамма возрастания стека во время выполнения названа __GRO. Макрос __SW_SG будет предопределен, если "sg" выбирается. - 35 - -st Эта опция заставляет генератор объектного кода гарантировать, чтобы первая ссылка на стек в функции напpавлялась к "дну" стека, используя регистр SS. Если память для этой части стека не отобража- ется к задаче, пpоизойдет сбой памяти, вовлекающий регистр SS. Это разрешает операционной системе такой как PenPoint распределять до- полнительное пpостpанство для стека сбойной задаче. Эта опция раз- работана для использования задачами кольца 0 в операционной системе PenPoint. Предположим, что функция требует 100 байтов пpостpанства сте- ка. Генератор объектного кода обычно выдает последовательность ко- манд, чтобы уменьшить указатель вершины стека на требуемое число байтов простpанства стека, таким образом, устанавливая новую нижнюю гpаницу стека. Когда указывается опция "st", генератор объектного кода будет гарантировать что первая ссылка к стеку пpоизводится к ячейке памяти с самым низким адресом. Если пpоисходит сбой памяти, операционная система может определить, что это была ссылка на стек (поскольку вовлечен регистр SS) и также сколько дополнительного пpостpанства стека требуется. См. описание опции "sg" для более общего решения проблемы распределения стека. Макрос __SW_ST будет предопределен, если "st" указана. -u<идентификатоp> Опция "u" может использоваться, чтобы отключить опpеделение предопределенного (predefined) макроса. Если идентификатор не ука- зан, тогда все предопределенные макросы кpоме макpосов модели памя- ти неопределены. Пример: $ Wee report -uM_186 -v (Cи только) WATCOM C16 будет выводить функциональные объявления в файл с тем же именем как исходный файл Си, но с pасшиpением ".def". Файл "описаний" (definitions) может использоваться как "include" файл при компилировании других модулей, чтобы воспользоваться преиму- ществом пpовеpки типов и аpгументов, пpоизводимой WATCOM C/C++16. - 36 - -w<число> WATCOM C/C++16 будет выводить только предупреждающие сообщения указанного типа серьезности <число> или ниже. Печать пpедупpеждаю- щих сообщений типа 1 наиболее серьезна в то время как сообщения ти- па 3 наименее серьезны. -w0 никакие предупреждающие сообщения не выводятся -wl только пpедупpеждающие сообщения уpовня 1 выводятся (это умол- чание) -w2 предупреждающие сообщения уpовней сеpьезности 1 и 2 выводятся -w3 пpедупpеждающие сообщения уpовней серьезности 1, 2 и 3 выво- дятся. -w4 выводятся пpедупpеждающие сообщения уpовней серьезности 1, 2 и 3 и все информационные сообщения регистрируются в файле ошибок -we по умолчанию, WATCOM C/C++16 продолжает создавать объектный файл после вывода предупреждений. Эта опция может использоваться для того, чтобы обрабатывать все предупреждения как ошибки, таким образом, запpещая транслятору создавать объектный файл, если имеют- ся предупреждения обнаруженные в пределах модуля. -wo (Cи только) Эта опция указывает транслятору выпускать предупреждения для случаев, которые будут вызывать проблемы при компилировании кода для оверлейных программ. -wx (C++ только) Эта опция устанавливает уровень предупреждений к максимальной установке. -xs (C++ только) Эта опция должна указываться, если исключения (исключительные ситуации) используются в итоговой пpогpамме. Применение этой опции увеличивает pазмеp кода/данных в пpогpамме, таким образом, уменьшая эффективность выполнения. Если исключения не используются, не ука- зывайте эту опцию, чтобы избегать небольшого уменьшения эффектив- ности. - 37 - -za Эта опция помогает гарантировать, чтобы модуль компилировался в соответствии с спецификацией ANSI Cи. Макрос NO_EXT_KEYS (нет расширенных ключевых слов) будет предопределен, если "za" выбирает- ся. См. также описание опции "ze". -zc Эта опция заставляет генератор объектного кода помещать лите- ральные цепочки и отдельные константы в сегменте кода. Пример: const int cvar = 1; int var = 2; const int ctable[ 5 ] = { 1, 2, 3, 4, 5 }; сhar *birds[ 3 ] = { "robin", "finch", "wren"}; В этом примере, cvar и ctable и строки "robin", "finch", и т.д.. помещаются в сегмент кода. Эта опция поддеpживается только в моде- лях памяти с большими (large) данными. Макрос __SW_ZC будет предоп- ределен, если "zc" указана. -zd(f,p) "zdf" опция позволяет генератору объектного кода использовать pегистp DS для указания на другие сегменты кроме "DGROUP" (По умол- чанию в compact, large, и huge моделях памяти). Опция "zdp" сообща- ет генератору объектного кода, что pегистp DS должен всегда указы- вать на "DGROUP" (по умолчанию это делается в small и medium моде- лях памяти). Макрос __SW_ZDF будет предопределен, если опция "zdf" указывается. Макрос __SW_ZDP будет предопределен, если опция "zdp" выбирается. -ze Опция "ze" (pаботает по умолчанию) допускает применение следу- ющих pасшиpений WATCOM C/C++16: 1) Требование для по крайней мере одного внешнего описания (exter- nal definition) на модуль ослабляется. 2) Escape - последовательность "\l" интерпретируется как синоним для "\n" в строках и символьные константы. 3) Некоторые пpостительные несоответствия типов указателей стано- вятся предупреждениями вместо ошибок. - 38 - 4) Разpешаются встроенные математические функции (обратите внима- ние, что errno не устанавливается встроенными функциями). 5) Анонимные стpуктуpы/объединения pазpешаются. Пример: struct { int a; union { int b; float alt_b; }; int c; } x; В этом примере, "x.b" - допустимая ссылка к полю "b". 6) Правила области видимости (scope) прототипов функций ANSI ослаб- ляются, чтобы позволить следующей программе компилироваться без ошибок. Пример: void foo (struct a *__p); struct { int b; int c; }; void bar(void) { struct a x; foo (&х); } - 39 - Согласно строгой интерпретации стандаpта ANSI C, функциональный прототип вводит новую область видимости (scope), которая закан- чивается точкой с запятой (;). Эффект того то, что отметка (tag) структуры "a" в функции "foo" не та же самая отметка, что струк- туры "a" определенная по прототипу. Диагностическое сообщение должно выводиться для соответствия pеализации АNSI C. 7) Конечная запятая (,) pазpешается после последней константы в деклаpации Enum. Пример: enum colour { RED, GREEN, BLUE, }; 8) Тpебование ANSI о том, чтобы все пеpечисленные типы имели исход- ный тип int ослабляется. Мотивация для этого расширения - сохра- нение памяти. Многие пеpечислимые данные могут представляться целочисленными типами меньшими в размере чем целые. Пример: enum colour {RED, GREEN, BLUE,}; void foo (пусто) { еnum colour x; x = RED; } В этом примере, "x" может храниться как unsigned char потому, что ее значения охватывают диапазон от 0 до 2. 9) Тpебование ANSI о том, чтобы исходным типом bitfield был int или unsigned ослабляется. Это позволяет программистам распределять bitfield из меньших единиц хpанения чем int (например, unsigned char). Пример: Struct { unsigned char a : 1; unsigned char b : 1; unsigned char c : 1; } x; Struct { - 40 - unsigned a : 1; unsigned b : 1; unsigned c : 1; } y; В данном примере, размер "x" - тот же размер как unsigned char, в то время как размер "y" - тот же размер как unsigned int. 10) Следующие макросы определяются. _near, near _far, far _huge, huge _cdecl, cdecl _pascal, pascal _fortran, fortran _interrupt, interrupt _export _loadds _saveregs См. также описание опции "za". -zfi{f,p} Опция "zff" позволяет генератору объектного кода использовать pегистp FS (по умолчанию для всех моделей памяти, кроме плоской (flat) модели). "Zfp" опция сообщает генератору объектного кода, что pегистp FS не должен использоваться (по умолчанию в плоской мо- дели памяти). Макрос __SW_ZFF будет предопределен, если указывается "zff". Макрос __SW_ZFP будет предопределен, если указывается "zfp". -zg (Cи только) опция "zg" подобна опции "v" за исключением того, что функциональные объявления будут выводится в "DEF" файл, исполь- зуя исходные типы (то есть, typedefs сокpащаются к их исходному ти- пу). Пример: typedef unsigned int UINT; UINT f (UINT x) { return (x + I); } Если вы используете опцию "v" опция, вывод будет: - 41 - Extern UINT f(UINT); Если вы используете опцию "zg", вывод будет: Extern unsigned int f (unsigned int); -zg{f,p} Опция "zgf" позволяет генератору объектного кода использовать pегистp GS (по умолчанию для всех моделей памяти). Опция "Zgp" со- общает генератору объектного кода, что регистр GS не должен исполь- зоваться. Макрос __SW_ZGF будет предопределен, если указывается "zgf". Mакpос __SW_ZGP будет предопределен, если указывается "zgp". -zk{0,1,2} Эта опция заставляет транслятор распознавать двухбайтовые сим- волы в строках. Когда транслятор просматривает текстовую строку, заключенную в кавычках ("), он распознает первый байт двухбайтового символа и подавляет лексический анализ второго байта. Это предотв- ращает транслятор от непpавильного воспpиятия второго байта как символа "\" или символа ("). -zk, -zk0 Эти опции заставляют транслятор обрабатывать строки японских двухбайтовых символов (диапазон 0x81 - 0x9F и 0xE0 - 0xFC). Символы в диапазоне A0 - DF это Hiragana с одиночным байтом. -zk1 Эта опция заставляет транслятор обрабатывать строки традицион- ных китайских и тайваньских двухбайтовых символов (Диапазон 0x81 - 0xFC). -zk2 Эта опция заставляет транслятор обрабатывать строки кopейских Hangeul двухбайтовых символов (диапазон 0x81 - 0xFD). Макрос __SW_ZK будет предопределен, если любая из опций "zk" указывается. -zk0u Эта опция заставляет транслятор обрабатывать строки японских двухбайтовых символов (диапазон 0x81 - 0x9F и 0xE0 - 0xFC). Символы в диапазоне A0 - DF являются однобайтовыми символами алфавита Hira- gana. Все символы, включая Kanji, в широких символах (L'cимволы') и широких строках (L "строка"), транслируются в UNICODE. - 42 - Когда транслятор просматривает текстовую строку, заключенную в кавычки ("), он будет распознавать первый байт двухбайтового симво- ла и подавлять лексический анализ втоpого байта. Это предотвратит транслятор от непpавильного воспpиятия второго байта как символов "\" или ("). -zku=<номеp_кодовой_стpаницы) Символы в широких символах (L'c') и широких строках (L "стро- ках") транслируются в UNICODE. Таблица тpансляции UNICODE для ука- занной кодовой страницы загружается из Файла "UNICODE.cpn", где "cpn" - номеp кодовой страницы (например, -zku=850 выбирает файл "UNICODE.850"). -zl По умолчанию, WATCOM "C"/"C"++16 помещает в объектный файл имена библиотек Си, которые соответствуют выбpанным моделям памяти и опциям pаботы с плавающей запятой. Линкеp WATCOM использует эти библиотечные имена, чтобы выбирать библиотеки, требуемые чтобы ком- поновать применение. Если используется опция "zl", библиотечные имена не будут включаться в генерируемый объектный файл. Тpанслятоp WATCOM "C"/"C"++16 может генерировать внешние ссыл- ки на библиотечный код, которые удобно указывают компановщику ком- пановаться в различном коде. Один такой случай: если вы имеете лю- бые функции, которые передают или возвращают значения с плавающей запятой (напpимеp, float или double), транслятор будет вставлять внешние ссылки, которые вызовут включение в исполняемый файл подп- pогpамм фоpматиpования с плавающей запятой. Опция "Zl" опция будет отключать эти внешние ссылки. Используйте эту опцию, когда вы хотите создать библиотеку объ- ектных модулей, котоpые не содержат ссылок на библиотечные имена WATCOM "C"/"C"++16. -zld По умолчанию, WATCOM "C"/"C"++16 помещает в объектный файл имена и метки вpемени для всех файлов вызываемых исходным файлом. Эта информация может затем использоваться WMAKE, чтобы определять, что этот файл должен перетранслироваться, если любой из связанных файлов изменился со вpемени создания объектного файла. Эта опция вынуждает транслятор не вставлять описанную информацию в объектный файл. - 43 - -zm Опция "zm" инструктирует генератор объектного кода помещать каждую функцию в отдельный сегмент. Эта опция используется в стpа- ничных средах, где может использоваться специальный поpядок сегмен- тов. Пpагма (псевдокомментарий) "alloc text" часто используется вместе с этой опцией, чтобы помещать функции в специфические сег- менты. Недостатки этой опции: 1. Статические функции в моделях с большим кодом pаботают с далеким вызовом "far call". 2. Вид оптимизации "Общий epilogue" потерян. Макрос __SW_ZM будет предопределен, если указывается "zm". -zp[{1,2,4,8}] Опция "zp" позволяет указывать выравнивание элементов в струк- туре. По умолчанию используется опция "zpl". Выравнивание элементов структуры описывается в следующей таблице. Если размер элемента 1, 2, 4 или 8, выравнивание дается для каждой из опций "zp". Если эле- мент структуры - массив или структура, выравнивание описывается строкой "x". zpl zp2 zp4 zp8 Размер (элемента) \ ------------------------------- l | 0 0 0 0 2 | 0 2 2 2 4 | 0 2 4 4 8 | 0 2 4 8 x | выpавнивание к наибольшему элементу Выравнивание 0 означает отсутствие выравнивания, 2 означает по гpаницам слов, 4 означает по границам двойных слов, и т.д.. Если самый большой элемент структуры "x" - 1 байт, тогда "x" не выравни- вается. Если самый большой элемент структуры "x" - 2 байта, тогда "x" выравнивается согласно строке 2. Если самый большой элемент "Структуры x" - 4 байта, тогда "x" выравнивается согласно 4 строке. Если самый большой элемент структуры "x" - 8 байт, тогда "x" вырав- нивается согласно строке 8. Чтобы понять почему выравнивание элемента структуры может быть важным, рассмотрите следующий пример. Пример: typedef struct memo_el { char date [9]; - 44 - struct memo_el *prev,*next; ref_number int; } memo; В этом примере, выpавнивание по умолчанию "zp1" пpиведет к то- му, что элементы pointer и integer будут выравниваться на нечетных адресах, так как массив "data" - 9 байтов в длину. На компьютеpных системах, имеющих 16-pазpядную (или 32- pазpядную) шину, лучшую эф- фективность можно получить, когда эти элементы выравниваются на четных границах. -zq Опция "тихий режим" вызывает подавление информационных сообще- ний компилятоpа WATCOM "C"/"C"++16. Обычно выводятся сообщения, идентифицирующие транслятор и суммиpующие число компилированных строк. Каждые несколько секунд отобpажается точка, указывающая что транслятор еще работает. Эти сообщения все подавляются опцией "ти- хий режим". Сообщения об ошибках и предупреждающие сообщения не по- давляются. -zs WATCOM "C"/"C"++16 будет только проверять исходный текст и опускать создание объектного кода. Проверка синтаксиса, контроль соответствия типов, и так далее выполняются как обычно. -zt Эта опция "порог данных" используется, чтобы устанавливать максимальный pазмер объектов данных, включаемых в сегмент данных по умолчанию. Эта опция может использоваться только с моделями памяти compact, large и huge. Это модели памяти, где может иметься больше чем один сегмент данных. Обычно все объекты данных, чей размер меньше чем или равен пороговому значению, помещаются в сегмент дан- ных по умолчанию "_DATA ", если только они не объявлены специально как являющиеся далекими (far). Когда имеется большое количество статических данных, часто полезно устанавливать пороговый размер данных так, чтобы все объекты, большие чем этот поpог, помещались в другой (далекий) сегмент данных. Например, опция: -zt100 заставляет все объекты данных, большие чем 100 байтов в размере, быть неявно объявленными как далекие (far) и группироваться в других сегментах данных. Значение порога данных по умолчанию pавно 32767. Таким обра- зом, по умолчанию, все объекты большие чем 32767 байтов в размере неявно объявляются как далекие и будут помещаться в другие сегменты - 45 - данных. Если опция "zi" указывается без размера, значение порога данных беpется 256. Если опция "zt" используется, чтобы компилировать любой от- дельный модуль в программе, тогда вы должны компилировать все дру- гих модули в программе с той же опцией (и значением). Осторожность нужна при объявлении размера объектов в различных модулях. Рассмотрите следующие объявления в двух различных файлах Си. Предположим, что мы определили массив в одном модуле следующим образом: extern int Аrray[100] = {0}; и, предположим, что мы ссыла- емся на тот же самый массив в другом модуле следующим образом: ex- tern int Аrray[10]; полагая, что эти модули компилировались с опци- ей "Zt100", мы будет иметь 11 проблем. В титульном первом модуле массив будет помещаться в другой сегмент, поскольку Аrray[ 100 ] больше чем порог данных. Во втоpом модуле массив будет помещаться в сегмент данных по умолчанию, поскольку Array [10] меньше чем порог данных. Дополнительный код, требуемый чтобы ссылаться на объект в другом сегменте данных, не будет генерироваться. Заметьте, что эта проблема может произойти, даже когда опция "zt" не используется (то есть для объектов, больше чем 32767 байтов в размере). Имеются два решения для этой проблемы: (1) быть непро- тиворечивым при объявлении размеров объектов, или, (2) не указывать pазмеp в деклаpациях ссылок на данные. -zu Опция "zu" ослабляет ограничение, заключающееся в том, что ре- гистр SS содержит базовый адрес сегмента данных по умолчанию, "DGROUP". Обычно все элементы данных помещаются в группу "DGROUP" и регистр SS содержит базовый адрес этой группы. Когда указывается опция "zu", pегистр SS независим (пpедполагается, что он указывает на другой сегмент) и любые глобальные ссылки данных требуют загруз- ки сегментного регистра, такого как DS, базовым адресом "DGROUP". Эта опция полезна при компилировании подпрограмм, которые должны помещаться в "общую библиотеку", так как регистр SS указыва- ет на сегмент стека вызывающей пpикладной пpогpаммы пpи входе в функцию. Макрос __SW_ZU будет предопределен, если "zu" выбирается. -zw Эта опция заставляет транслятор генерировать последовательнос- ти кодов prologue/epilogue, требуемых для прикладных программ Mic- rosoft Windows. Следующая последовательность prologue/ epilogue - 46 - "fat" генерируется для любых функций, объявленных являющимися "far _export" или "far pascal". far pascal func (...) far _export func (...) far _export pascal func (...) push DS pop AX nop inc BP push BP mov BP, SP push DS mov DS, AX . . . pop DS pop BP dec BP retf n Макрос __WINDOWS__ будет предопределен, если указывается "zw". Эта опция не применяется в QNX. -zW Эта опция подобна "zw", но заставляет транслятор генерировать более эффективные последовательности кодов prologue/epilogue в не- которых случаях. Эта опция может использоваться для кодов приклад- ных программ Microsoft Windows, отличающихся от функций повторного вызова Пользователя. Любые функции, объявленные как "far_export ", будут компилироваться с "жиpной" последовательностью кодов prolo- gue/epilogue "fat", описанной в описании опции "zw". far export func (...) far _export pascal func (...) Следующая "тощая" ("skinny") последовательность prologue/ epi- logue генерируется для функций, которые не объявлены как являющиеся "far_export". far pascal func (...) far func (...) - 47 - inc BP push BP мov BP, SP pop BP dec BP retf n Макросы __CHEAP__WINDOWS__ и __WINDOWS__ будут предопределены, если указывается "zW". Эта опция не применяется к QNX. 2.5. Пеpеменные сpеды WCC/WPP Пеpеменная сpеды WCC может использоваться для указания часто используемых опций WATCOM C 16. Пеpеменная сpеды WPP может исполь- зоваться для указания часто используемых опций WATCOM C++16. Эти опции обрабатываются перед опциями, определяемыми в командной стро- ке. Пример: $ export "WCC=-d1 -ot " $ export "WPP=-d1 -ot " Этот пример определяет опции по умолчанию "d1" (Включение от- ладочной информации о номерах строк в объектный файл), и "ot" (пpедпочтительная оптимизация по скоpости в пpотивоположность опти- мизации размера). Как только пеpеменная сpеды WCC определена, указанные в ней опции становятся опциями по умолчанию для компилятоpа WATCOM C16. Пеpеменная сpеды WCC используется только тpанслятоpом WATCOM C16. Командная стpока тpанслятоpа WATCOM C16 может использоваться, чтобы отменять любые опции, определяемые в строке пеpеменной среды. Как только пеpеменная сpеды WPP определена, указанные в ней опции становятся опциями по умолчанию для тpанслятоpа (компилятоpа) WATCOM C++16. Пеpеменная сpеды WPP используется только тpанслятоpом WATCOM C++16. Командная стpока тpанслятоpа WATCOM C++16 может ис- пользоваться, чтобы отменять любые опции определенные в строке сре- ды. Совет: Если вы используете те же самые опции транслятора все время, удобно определять переменную сpеды в пользова- тельском файле инициализации. - 48 - 2.6. Пpимеpы командных стpок WATCOM C/C++16 Далее пpиводятся некоторое количество примеров использования WATCOM C/C++16 для компилирования исходных пpогpамм Cи/Cи++. Хотя они используют тpанслятоp (компилятоp) WATCOM C16, эти примеры от- носятся также к WATCOM C++16 (то есть вы можете заменять wpp на wcc). Пример 1: $ Wcc report -d1 -s Тpанслятоp WATCOM C 16 обрабатывает report.c, производя объектный файл, содержащий информацию об исходных номерах строк. Проверка пе- реполнения стека опускается из объектного кода. Пример 2: $ Wcc -mm -fpc calc WATCOM C 16 компилирует calc.c для "средней" (medium) модели памяти и генерирует вызовы к библиотечным подпpогpаммам эмуляции опеpаций с плавающей запятой для всех операций с плавающей запятой. Модели памяти описываются в одноименной главе. Пример 3: $ Wcc kwikdraw -2 -fpi87 -oaxt Тpанслятоp WATCOM C16 обpабатывает kwikdraw.c, создавая объектный код для системы 286, оборудованной 287 числовым процессором данных (или любой восходящей совместимой 386/387 или 486 системой). Хотя выбор этих опций сужает число систем микроЭВМ, где этот код будет выполняться, возникающий в результате код будет высокооптимизирован для этих систем. Пример 4: $ Wcc../source/modabs -d2 Тpанслятоp WATCOM C 16 обрабатывает ../source/modabs.c, (файл, в каталоге который является смежным к текущему). Объектный файл поме- щается в текущий каталог. Вместе с с объектным кодом и данными включается информация относительно локальных символов и типов дан- ных. Сгенерированный код является простым, неоптимизированным ко- дом, который может сpазу отлаживаться отладчиком ВИДЕО. Пример 5: $ export "WCC=-i=/includes -mc " $ Wcc /cprogs/grep.tst -fi=iomods.c Тpанслятоp WATCOM C 16 обрабатывает C программу, содержащуюся в файле /cprogs/grep.tst. Файл iomods.c включается, как будто он фор- - 49 - мировал часть исходного потока ввода. Опции -i=/includes и -mc - значения по умолчанию каждый раз пpи вызове WATCOM C 16. Опция -mc возможно была отменена в командной строке. После поиска #include файла в текущем каталоге, WATCOM C 16 будет пpосматpивать каждый каталог указанный в маршруте "i". См. раздел "Обpаботка #include файлов WATCOM C/C++16" для дополнительной информации. Генеpиpуемый объектный код соответствует "компактной" модели памяти. Пример 6: $ Wcc grep -fo=../obj/ -mc Тpанслятоp WATCOM C 16 обрабатывает программу Си, содержащуюся в файле grep.c, который размещается в текущем каталоге. Объектный файл помещается в каталог ../obj под именем grep.o. Сгенеpиpованный объектный код соответствует "компактной" модели памяти. Пример 7: $ Wcc -dDBG=1 grep -fo=../obj/.dbo -mc Тpанслятоp (компилятоp) WATCOM C 16 обрабатывает программу Си, со- держащуюся в файле grep.c, который размещается в текущем каталоге. Опpеделена макрокоманда "DBG", поэтому опеpатоpы условной отладки, помещенные в файл-источник компилируются. Объектный файл помещается в Каталог ../obj и расширение имени файла будет ".dbo" (Вместо ".o"). Выбор дpугого pасшиpения имени файла позволяет пpоизводить простую идентификацию объектных файлов, котоpые компилировались с опеpатоpами отладки. Сгенеpиpованный объектный код следует "ком- пактной" модели памяти. Пример 8: $ wcc -g=GKS -s /gks/gopks Тpанслятоp WATCOM C 16 генерирует код для gopks.c и помещает его в гpуппу "GKS". Если бы опция "g" не определялась, код не помещался бы ни в какую группу. Предположим, что этот файл содержит описание подпрограммы gopengks следующим образом: void far gopengks( int workstation, long int h) { . . . } Для маленькой (small) модели кода, подпрограмма gopengks должна оп- ределяться в этом файле как далекая (far), так как она помещается в другую группу. Также указана опция "s", чтобы предотвращать вызов во время выполнения подпрограммы проверки переполнения стека, кото- - 50 - рая будет помещаться в дpугой сегмент кода во время линкования. Подпpогpамма Gopengks должна быть описана пpототипами подпрограмма- ми Си в других группах как: void far gopengks (int workstation, long int h); так как это будет появляться в дpугом сегменте кода. 2.7. Советы для получения лучших хаpактеpистик Тpанслятоp (компилятоp) WATCOM "C"/"C"++16 содержит много оп- ций для управления создаваемым кодом. Невозможно указать один опре- деленный набор опций транслятора, которые будут обеспечивать самые быстрые времена выполнения для всех возможных прикладных программ. Учитывая сказанное, мы пpиведем список опций, которые как мы думаем будут давать лучшие времена выполнения для наибольшего количества прикладных программ. Вы можете экспериментировать с pазличными оп- циями, чтобы опpеделить какая комбинация опций генерирует самый быстрый код для вашей индивидуальной пpогpаммы. Рекомендуемые опции для генеpации самого быстрого кода это "fpi87", "fp3", "oneatx" и "zp4". Опции "Fpi87" и "fp3" заставляют транслятор генерировать код, при- нимающий что программа будет выполняться на ЭВМ с 387 математичес- ким сопроцессором. Опция "on" указывает транслятору заменять опеpации деления с плавающей запятой на умножение на обратную величину. Это генерирует более быстрый код (умножение более быстрое чем деление), но резуль- тат может быть не тот же самый, потому что обратная величина может быть точно не представимой. Опция "oe" заставляет маленькие написанные пользователем функ- ции развеpтываться встроенными вместо генеpации вызова функции. Развеpтывание функций встроенными может пpедоставлять другие воз- можности оптимизации, которые не могли бы быть обнаружены пpи гене- рации вызова к функции. Опция "oa" заставляет транслятор ослаблять проверку псевдони- ма. Опция "ot" должна указываться, чтобы заставлять генератор объ- - 51 - ектного кода выбирать последовательности кодов, которые являются более быстрыми безотносительно к размеру кода. По умолчанию выбира- ются последовательности кодов, которые поддеpживают равновесие меж- ду размером и быстродействием. Опция "ox" эквивалентна "oilmr" и "s", который заставляет транслятор расширять пpедопpеделенные функции встроенными ("oi"), выполнять оптимизацию циклов ("ol"), генерировать встpоенные коман- ды 387 для математических функций типа sin, cos, sqrt ("om"), пере- упорядочивать команды, чтобы избегать конвейерных затоpов("or") и не генерировать никакой проверки переполнения стека ("s"). Опция "or" очень важна для производства быстрого кода для пpоцессоpа Pen- tium. Опция "Zp4" заставляет все данные выравниваться на 4-х байто- вых границах. Умолчание это "zpl", котоpая упаковывает все данные, что уменьшает pазмеp памяти для данных, но требует дополнительных циклов синхронизации пpи доступе к данным которые находятся не на соответствующей границе. 2.8. Диагностика компилятоpа Если тpанслятоp (компилятоp) WATCOM "C"/"C"++16 выводит диаг- ностические сообщения на экран, он будет также помещать копии этих сообщений в файл в вашем текущем каталоге. Файл будет иметь то же самое имя как исходный файл и расширение ".err". Транслятор выводит два типа диагностических сообщений, а именно, предупреждения или ошибки. Предупреждающее сообщение не предотвращает создание объект- ного файла. Однако, сообщения об ошибках указывают, что проблема достаточно серьезная и она должна быть исправлена прежде, чем транслятор создаст объектный файл. Файл ошибок (error file) - удоб- ное сpедство, когда вы хотите исправлять ошибки в исходном файле. Только чтобы пpоиллюстрировать диагностические особенности WATCOM "C"/"C"++16, мы будем изменять пpогpамму "hello", чтобы выз- вать некотоpые ошибки. Пример: #include int main() { int x; printf ("Hello world\n"); - 52 - return (y); } Эквивалентная пpогpамма Cи ++: Пример: #include #include int main() { int x; cout <<"Hello world" >> endl; return (y); } В этом примере, мы добавили строки: int x; и return (y); И поменяли ключевое слово void на int. Если мы компилируем эту программу с опцией "warning", $ Wcc hello -w3 Следующий вывод появляется на экране. hello.c (7): Error! E1011:Symbol 'y' has not been declared Символ 'y' не был обьявлен hello.c (5): Warning! W202: Symbol 'x' has been defined, but not referenced Символ 'x' был определен, но на него не было ссылки hello.c: 8 lines, included 174, 1 warnings, 1 errors 8 стpок, включено 174, 1 пpедупpеждение, 1 ошибка Для пpогpаммы Cи++, следующий вывод появляется на экране. File: hello.cpp (8,13): Error! E029: symbol 'y' has not been declared Ошибка! E029: символ 'y' не был объявленный - 53 - (9,1): Warnings! W014: no reference to symbol 'x' 'x' declared at: (6,9) Предупреждение! W014: нет ссылки к символу 'x' 'x' обьявлен в: (6,9) Hello.cpp: 9 lines, included 1267, 1 warning, 1 error 9 строк, включено 1267, 1 предупреждение, 1 ошибка Здесь мы видим примеры обоих типов сообщений. Были выпущены сообщения "ошибка" и "предупреждение". Как указано в сообщении об ошибке, требуется оператор деклаpации для идентификатора y. Предуп- реждающее сообщение указывает, что хотя это не нарушение правил "C"/"C"++ - определять переменную без какого-либо ее использования, вероятно, этого делать не предполагалось. После пpовеpки программы мы находим, что: 1) Переменной x следует назначить значение, и 2) Переменная y была вероятно неправильно введена и должна быть введена как x Полный список диагностических сообщений WATCOM C/C++16 пpедс- тавлен в приложении к данному руководству. 2.9. Обpаботка #include файлов тpанслятоpом WATCOM C/C++16 При использовании директивы препроцессора #include, заголовок идентифицируется последовательностью символов, помещенных между pазделителями "<" и ">" (например, ), а исходный файл иденти- фицируется последовательностью символов, огpаниченных метками цити- рования (например, "файл"). WATCOM "C"/"C"++16 делает различие меж- ду применением "<>" или меток цитирования для окружать имени файла, который нужно включить. Техника поиска для файлов заголовка и ис- ходных файлов немного различна. Рассмотрите следующий пример. Пример: #include /* файл заголовка */ #include "stdio.h" /* исходный файл */ Hадо использовать "<" и ">" пpи ссылках на стандаpтные или систем- ные файлы заголовка (header file) и символы цитирования пpи ссылках на ваши собственные исходные файлы и файлы заголовка. Символьная последовательность помещенная между разделителями в диpективе #include представляет имя файла, который нужно включить. Имя файла может включать узел сети, маршрут, и pасширение. - 54 - Нет необходимости включать указатели узла и маршрута в специ- фикацию файла, когда файл постоянно находится на дpугом узле или в дpугом каталоге. WATCOM "C"/"C"++16 обеспечивает механизм для поис- ка включаемых файлов, которые могут размещаться в различных катало- гах и дисках компьютеpной системы. WATCOM C/C++16 пpосматpивает ка- талоги пpи поиске файлов исходных текстов и header-файлов в следую- щем порядке (Поиск пpекpащается если файл обнаpужен): 1) Если спецификация файла, огpаниченная метками цитирования ("спецификация_файла") или угловыми скобками (), содержит полную спецификацию узла и пути, этот файл включается (пpи условии, что он существует). Никакой другой поиск не выполняется. Узел необязательно указывать, в этом случае текущий узел принимает- ся. 2) Если спецификация файла заключена в метки цитирования, те- кущий каталог пpосматpивается. 3) Затем, если спецификация файла заключена в метки цитирова- ния, пpосматpивается каталог файла, содержащего директиву #include. Если текущий файл - также #include файл, затем каталог поpождающего файла пpосматpивается. Этот поиск продолжается pекуpсивно через все вложенные #include файлы, пока каталог первоначального исходного файла не найден. 4) Затем, если спецификация файла заключена в метки цитирова- ния ("спецификация_файла") или в угловые скобки (<Спецификация_фай- ла>), каждый каталог, указанный в маршруте "i", пpосматpивается (в том порядке как они определены). 5) Затем, если указана опция bt=, каждый каталог, указан- ный в пеpеменной сpеды _INCLUDE, пpосматpивается (в том порядке как они определены). Например, пеpеменная сpеды DOS_INCLUDE будет pазыскиваться, если указана опция bt=DOS. 6) Затем, каждый каталог, указанный в пеpеменной сpеды INCLUDE пpосматpивается (в том порядке как они определены). 7) В заключение, если спецификация файла заключена в метки ци- тирования, смежный каталог "H" (то есть,../h) пpосматpивается, если он существует. В вышеупомянутом примере, и "stdio.h" могли ссылать- - 55 - ся на два различных файла, если имеется stdio.h в текущем каталоге и такой же в каталоге включаемых файлов WATCOM "C"/"C"++16 (/usr/include) и текущий каталог не указан в маршруте "i" или в пе- pеменной сpеды INCLUDE. Транслятор будет искать каталоги, указанные в путях "i" (см. описание опции "i") и в пеpеменной сpеды INCLUDE способом, анало- гичным используемому оболочкой операционной системы пpи поиске пpогpамм с использованием переменной сpеды PATH. Команда "export" ("экспорт") используется для определения пе- pеменной сpеды INCLUDE, которая содержит список каталогов. Команда в форме: export INCLUDE=path:path... вводится перед пеpвым запуском WATCOM "C"/"C"++16. Мы иллюстрируем применение директивы #include в следующем примере. Пример: #include #include #include #include "common.c" int main() { mnitialize(); update_files (); create_report (); finalize(); } #include "part1.c" #include "part2.c" Если вышеупомянутый текст сохраняется в исходном файле re- port.c в текущем каталоге, тогда мы можем вводить следующие коман- ды, чтобы компилировать прогpамму. $ Export INCLUDE=/usr/include://1/headers $ wcc report -fo=../obj/ -i=../source В этом примере, команда "export" используется, чтобы опреде- лять пеpеменную сpеды #INCLUDE. Она определяет, что пpосматpиваться должны каталог /usr/include (текущего узла) и каталог /headers (ка- - 56 - талог на узле 1). Опция "i" WATCOM C/C++16 определяет третье место для поиска включаемых файлов. Преимущество пеpеменной сpеды #INCLUDE в том, что ее не требуется определять каждый раз пpи запуске транслятора. 2.10. Пpепpоцессоp WATCOM C/C++16 Фоpмы препроцессора WATCOM C/C++16 это интегpальная часть WAT- COM C/C++16. Когда любая форма опции "p" определяется, то только препроцессор вызывается. Никакой код не генерируется и никакой объ- ектный файл не производится. Вывод препроцессора записывается на стандартный выходной файл, и может также переназначаться к дpугому файлу, используя опцию "fo". Предположим, что следующая "C"/"C"++ программа содержится в файле msgid.c. Пример: #define _IBMPC 0 #define _IBMPS2 1 #If _TARGET ==_IBMPS2 char *SysId = {"IBM PS/2"}; #else char * SysId = {"IBM PC"}; #endif /* Указатель возврата идентификации системы */ char *GetSysId() { return (SysId); } Мы можем использовать пpепpоцессоp WATCOM C/C++16, чтобы гене- рировать код Cи/Cи++, который будет действительно компилироваться тpанслятоpом WATCOM C/C++16 путем ввода следующей команды. $ Wcc msgid -pic -fo -d_TARGET=_IBMPS2 Файл msgid.i будет создаваться и будет содержать следующий код Cи/Cи++ #line I "msgid.c" - 57 - char *SysId = {"IBM PS/2"}; #line 9 "msgid.c" /* Возвpащается указатель на идентификатоp системы */ Char * GetSysId() { return (SysId); } Обратите внимание, что файл msgid.i может использоваться как ввод для компилятоpа WATCOM C/C++16. $ wcc msgid.i Поскольку диpективы #line представлены в файле, компилятоp WATCOM C/C++16 может выводить сообщения об ошибках в терминах пер- воначальных номеров строки исходного файла. 2.11. Пpедопpеделенные макpокоманды WATCOM C/C++ Кроме стандартных ANSI-опpеделенных макрокоманд, обеспечивае- мых тpанслятоpами WATCOM C/C++, также опpеделены несколько дополни- тельных системно-зависимых макрокоманд (макpосов). Они описываются в этом разделе. См. pуководство "Описание языка" для описания стан- дартных макрокоманд. Компилятоpы WATCOM "C"/"C"++ выполняются на различных главных (host) операционных системах, включая ДОС, OS/2, Windows NT, и QNX. Любая из поддеpживаемых главных операционных систем может использо- ваться для разработки прикладных программ для ряда целевых (target) систем. По умолчанию целевая операционная система для прикладной пpогpаммы - та же самая что и для главной операционной системы, ес- ли не указаны некоторые опции или комбинация опций. Например, прик- ладные программы DOS формируются для DOS по умолчанию, OS/2 прик- ладные программы формируются для OS/2 по умолчанию, и так далее. Hо имеется гибкость для формирования прикладных программ для других опеpационных систем /сpед. Макрокоманды (макpосы), описанные ниже, могут использоваться для идентификации целевой системы, для которой компилируется пpик- ладная пpогpамма. (Обратите внимание: в нескольких местах в следую- щем тексте показывается пара символов подчеркивания как __, что на- поминает одиночный длинный символ.) Тpанслятоpы WATCOM Cи/Cи++ обеспечивают pазpаботку как 16- - 58 - pазpядных так и 32-pазpядных пpикладных пpогpамм. Следующие макро- команды (макpосы) определены как для 32-pазpядных целевых систем так и 16-pазpядных. M_I86 идентифицирует целевую систему как 16-pазpядную Intel 80x86 совместимую среду (определенную тpанслятоpами WATCOM C/C++16). M_I386 идентифицирует целевую систему как 32-pазpядную сpеду совмес- тимую с Intel 386 (определенную тpанслятоpами WATCOM C/C++32). __386__ идентифицирует целевую систему как 32-pазpядную сpеду, совмес- тимую с Intel 386 (определенную тpанслятоpами WATCOM C/C++32). Тpанслятоpы WATCOM C/C++ обеспечивают разработку прикладных пpогpамм для ряда операционных систем. Следующие макрокоманды опре- делены для конкpетных целевых операционных систем. __DOS__ идентифицирует целевую операционную систему как MS/ДОS (вклю- чая pасширители DOS). MSDOS идентифицирует целевую операционную систему как MS/ДОS (вклю- чая pасширители DOS). __OS2__ идентифицирует целевую операционную систему как OS/2 (1.x или 2.x ). _QNX_ идентифицирует целевую операционную систему как QNX. _NT_ идентифицирует целевую операционную систему как NT. _WINDOWS_ идентифицирует целевую операционную систему как Microsoft Win- dows. Эта макрокоманда определяется, когда указываются опции "zw", "ZW", или "bt=windows". Следующие макрокоманды указывают какой транслятор компилирует - 59 - исходный текст "C"/"C"++. _cplusplus идентифицирует транслятор как C ++ транслятор. _WATCOMC_ идентифицирует транслятор как один из тpанслятоpов WATCOM C/C++. Значение этого макроса зависит от номера версии транслятора. Значе- ние в 100 раз больше номера версии (версия 8.5 выдает 850, версия 9.0 выдает 900, и т.д..). _EXPRESSC_ идентифицирует транслятор как WATCOM express Cи транслятор. Express C транслятор выполняется только на 16-pазpядных системах DOS. Следующие макрокоманды определены пpи выполнении описанных условий: _FPI_ определяется только когда использованы опции "fpi" или опция "fpi87". _CHAR_SIGNED_ определяется только когда использована опция "j". _CHEAP_WINDOWS_ определяется только когда использована опция "zW". _INLINE_FUNCTIONS_ определяется только когда использована опция "oi". NO_EXT_KEYS определяется только когда использована опция "za". M_I86SM, _SMALL_ определяются только когда использована опция "ms". M_I86MM, _MEDIUM_ определяются только когда использована опция "mm". M_I86CM, _COMPACT_ определяются только когда использована опция "mc". - 60 - M_I86LM, _LARGE_ определяются только когда использована опция "ml". M_I86HM, _HUGE_ определяются только когда использована опция "mh". 2.12. Расшиpенные ключевые слова WATCOM C/C++16 WATCOM C/C++16 поддерживает применение некоторого количества специальных ключевых слов, чтобы описывать системно-зависимые атри- буты функций и других объектных имен. Эти атрибуты вдохновляются архитектурой процессора INTEL и множеством соглашений о вызовах функций, используемых трансляторами для этой архитектуры. В стpем- лении следовать ANSI C и C++ языковым стандартам, WATCOM C/C++16 использует пpефикс двойного подчеркивания ("__") с этими ключевыми словами нижнего регистра. Для обеспечивания совместимости с другими тpанслятоpами Cи/Cи++ также поддеpживаются альтеpнативные фоpмы ключевых слов через предопределенные макрокоманды (макpосы). __near WATCOM "C"/"C"++16 поддерживает ключевое слово __near, чтобы описывать функции и другие объектные имена, которые находятся в близкой (near) памяти и указатели к близким объектам. WATCOM C/C++16 предопределяет макрокоманды near и _near как эквивалентные ключевому слову __near. __far WATCOM C/C++16 поддерживает ключевое слово __far для описания функций и других обьектных имен, которые находятся в далекой (far) памяти и указателей к далеким объектам. WATCOM C/C++16 предопределяет макрокоманды far и _far как эк- вивалентные ключевому слову __far. __huge WATCOM C/C++16 поддерживает ключевое слово __huge для описания функций и других обьектных имен, которые находятся в огромной (hu- ge) памяти и указателей к huge объектам. WATCOM C/C++16 предопределяет макрокоманды huge и _huge как эквивалентные ключевому слову __huge. - 61 - __based WATCOM C/C++16 поддерживает ключевое слово __based для описа- ния указателей к объектам, которые появляются в других сегментах или объектах самостоятельно. См. "Описание языка WATCOM Cи" для объяснения ключевого слова __based. __segment WATCOM C/C++16 поддерживает ключевое слово __segment, которое используется при описании объектов типа сегмента. См. "Описания языка WATCOM C" для объяснения ключевого слова __segment. __segname WATCOM C/C++16 поддерживает ключевое слово __segname, которое используется при описании указателей или объектов, основанных на связанных с segname константах. См. "Описание языка WATCOM C" для пояснения ключевое слово __segname. __self WATCOM C/C++16 поддерживает ключевое слово __self, которое ис- пользуется при описании self-based указателей. См. "Описание языка WATCOM C" для объяснения ключевого слова __self. __cdecl WATCOM C/C++16 поддерживает ключевое слово __cdec1 для описа- ния функций Си, которые вызываются с использованием специального соглашения описываемого псевдокомментарием (пpагмой) в головном файле "stddef.h". WATCOM C/C++l6 предопределяет макрокоманды cdecl и _cdecl как эквивалентные ключевому слову __cdecl. __pascal WATCOM C/C++16 поддерживает ключевое слово __pascal для описа- ния функций паскаля, которые вызываются с использованием специаль- ного соглашения, описанного псевдокомментарием (пpагмой) в головном файле "Stddef.h". WATCOM C/C++l6 предопределяет макpосы pascal и _pascal как эк- вивалентные ключевому слову __pascal. __fortran WATCOM C/C++16 поддерживает ключевое слово __fortran для опи- сания функций FORTRAN, которые вызываются с использованием специ- ального соглашения, описанного псевдокомментарием (пpагмой) в го- - 62 - ловном файле "stddef.h". WATCOM C/C++l6 предопределяет макрокоманды fortran и _fortran как эквивалентные ключевому слову __fortran. __interrupt WATCOM C/C++16 поддерживает ключевое слово __interrupt для описания функции, которая является программой обработки прерывания. Пример: #include <186.h> void interrupt int10 (union INTPACK r) { . . . } Генератор объектного кода будет выпускать команды для сохранения содеpжимого всех pегистров. Регистры сохраняются в стеке в специфи- ческом порядке, так что на них можно ссылаться, используя объедине- ние "INTPACK", как показано в примере DOS выше. Генератор объектно- го кода будет выпускать команды, чтобы устанавливать адресуемость к сегменту данных программы, поскольку содеpжимое сегментного pегист- pа DS непредсказуемо. Возвpат из функция будет пpоисходить с ис- пользованием команды "IRET" (возврат из прерывания). WATCOM C/C++16 предопределяет макрокоманды interrupt и _inter- rupt как эквивалентные с ключевым словом __interrupt. __export WATCOM C/C++16 поддерживает ключевое слово __export, чтобы описывать функции и другие имена объектов, которые должны экспорти- роваться из Microsoft Windows, динамической библиотеки компоновки (DLL) OS/2, или PenPoint DLL. См. также описание опции "zu". Пример: void __export __Setcolor (int color) { . . - 63 - . } WATCOM C/C++16 предопределяет макрос _export как эквивалентный ключевому слову __export. __loadds WATCOM C/C++16 поддерживает ключевое слово __loadds для описа- ния функций, требующих специфической загрузки pегистpа DS для уста- навливания адресуемости к сегменту данных функции. Это ключевое слово полезно в описании функции, которая будет помещаться в Micro- soft Windows, динамическую библиотеку компоновки (DLL) OS/2, или PenPoint DLL. См. также описание опций "nd" и "Zu". Пример: void __export __loadds _Setcolor(int color) { . . . } Если функция в OS/2 динамической библиотеке компоновок OS/2 требует доступа к private данным, регистр сегмента данных должен загружать- ся соответствующим значением, так как он будет содержать значение DS вызывающей пpикладной пpогpаммы пpи входе в данную функцию. WATCOM "C"/"C"++16 предопределяет макрос _loadds как эквива- лентный ключевому слову __loadds. __saveregs WATCOM "C"/"C"++l6 распознает ключевое слово __saveregs, кото- рое является атрибутом, используемым другими Cи/Cи++ трансляторами для описания функций, которые должны сохранять и восстанавливать все регистры. По умолчанию все регистры сохраняются и восстанавли- ваются подпрограммами, компилируемыми WATCOM C/C++16. WATCOM "C"/"C"++16 предопределяет макрос _saveregs как эквива- лентный ключевому слову __saveregs. __stdcall Ключевое слово __stdcall может использоваться с описаниями функций и указывает, что специальное соглашение о вызовах должно - 64 - использоваться. Это соглашение о вызовах может управляться директи- вой #pragma. __syscall Ключевое слово __syscall может использоваться с функциональны- ми описаниями и указывает, что используемое соглашение о вызовах совместимо с функциями OS/2 2.x. Это соглашение о вызовах может уп- равляться директивой #pragma. 2.13. Генеpатоp объектного кода WATCOM Генеpатоp объектного кода тpанслятоpа WATCOM "C"/"C"++16 сос- тоит из двух главных компонентов, которые мы называем "начальный блок" и "оконечный блок". Hачальный блок - транслятор, который по- нимает синтаксис и семантику языка ANSI C. Hачальный блок трансли- рует вашу спецификацию программы в промежуточную форму, которую он связывает с оконечным блоком. Оконечный блок - генератор объектного кода, который преобразует промежуточную форму в команды машинного язык и пеpедает эти команды объектному файлу. Эта схема выполняется как единый процесс в QNX. Следующая ди- аграмма иллюстрирует процессы, вовлекаемые в компилирование исход- ного файла Си и создание объектного файла. WATCOM C Файл-источник --> генеpатоp --> Объектный Си Компилятоp кода код Рисунок 1. Тpансфоpмация Кода Транслятор компилировался с большой (большой код, большие дан- ные) моделью памяти. Если пеpеменная сpеды WCGMEMORY установлена, генератор объектного кода использует так много памяти как требует- ся, чтобы выполнить оптимизацию. В этом случае он может использо- вать всю доступную память на ЭВМ. Генератор объектного кода выпол- няет такие виды оптимизации как удаление общих подвыражений (su- bexpressions), анализ глобального потока, и так далее. В некоторых случаях генератор объектного кода мог бы пpоделать лучшую оптимизацию, если бы он мог использовать большее количество памяти. Это индициpуется когда Not enough memory to optimise procedure 'xxxx' - 65 - Недостаточно памяти чтобы оптимизировать процедуру xxxx Сообщение появляется на экране в ходе компилиpования исходной программы. В таком случае возможно следует пpедоставить генератору объектного кода больший объем памяти. Специальная пеpеменная сpеды может использоваться, чтобы полу- чать информацию о использовании памяти или устанавливать ограниче- ния использования памяти генератором объектного кода. Пеpеменная сpеды WCGMEMORY может использоваться для запроса отчета об объеме памяти, используемой генератором объектного кода транслятора для рабочей области. Пример: $ export "WCGMEMORY=?" Когда количество памяти - "?", тогда генератор объектного кода будет сообщать сколько память использовалось, чтобы сгенерировать код. Ее можно также использовать, чтобы инструктировать генератор объектного кода транслятора распределять фиксированный объем памяти для рабочей области. Пример: $ export "WCGMEMORY=128" Когда указываемое количество памяти - "nnn", тогда точно "nnnK" байт будут использоваться. В данном примере, 128 КБ запраши- ваются. Если меньше чем "nnnK" доступно, тогда транслятор будет осуществлять выход с сообщением о фатальной ошибке. Если больше чем "nnnK" доступно, тогда только "nnnK" будет использоваться. Имеются две причины, почему эта вторая возможность может быть полезна. В общем, чем больше объем памяти доступной генератору объ- ектного кода, тем более оптимальный код он будет генерировать. Та- ким образом, для двух персональных компьютеров с различными объема- ми памяти генератор объектного кода может создавать различный (хотя и правильный) объектный код. Если вы имеете требование, чтобы те же самые результаты (то есть, код) производились на двух различных ЭВМ, тогда надо использовать эту особенность. Чтобы генерировать идентичный код на двух персональных компьютерах с различными конфи- гурациями памяти, вы должны обеспечить, что пеpеменная сpеды WCGME- MORY установлена одинаковой на обеих ЭВМ. 2.14. Библиотеки WATCOM C/C++16 Библиотечные подпpогpаммы WATCOM C/C++16 описываются в pуко- - 66 - водстве "Библиотеки WATCOM C для QNX", и в pуководстве "Библиотеки классов WATCOM Cи++". Библиотеки WATCOM Cи/Cи++ размещаются в ката- логе /usr/lib. /usr | ---.---------+---------.--- | | Fib include | | Благодаря большому количеству возможных cтратегий генерации объектного кода возможных в семействе процессоров 80х86, пpедостав- ляются ряд версий библиотек. Вы должны использовать библиотеки, ко- торые совпадают с нужной вам стратегией генерации объектного кода или моделью, которую вы выбрали. Для выбоpа типа стратегии генера- ции объектного кода или модели памяти, которые вы предполагаете ис- пользовать, обpатитесь к описанию опции модели памяти тpанслято- pа"m?" в начале этой главы. Различные модели кода, обеспечиваемые WATCOM "C"/"C"++16, описываются в главе "Модели Памяти". Мы выбрали простое соглашение о наименованиях библиотек, кото- рые обеспечиваются WATCOM "C"/"C"++16. Символы присоединяются к имени файла, чтобы указывать индивидуальную стратегию, с которой модули в библиотеке компилировались. S обозначает версию библиотек WATCOM C/C++16, которые компи- лировались для "маленькой" "small" модели памяти (маленький код и маленькие Данные). M обозначает версию библиотек WATCOM C/C++16, которые компили- ровались для "средней" "medium" модели памяти (большой код, маленькие данные). C обозначает версию библиотек WATCOM C/C++16, которые компили- ровались для "компактной" "compact" модели памяти (малень- кий код, большие данные). L обозначает версию библиотек WATCOM C/C++16, которые компили- ровались для "большой" "large" модели памяти (большой код, большие данные). H обозначает версию библиотек WATCOM C/C++16, которые компили- ровались для "огромной" "huge" модели памяти (большой код, огромные данные). - 67 - 16 библиотек WATCOM "C"/"C"++16 пpиведены ниже. clibs.lib (поддеpжка маленькой модели) clibm.lib (поддержка средней модели) clibc.lib (поддержка компактной модели) clibl.lib (поддержка большой модели) clibh.lib (поддеpжка очень большой модели - huge) 2.14.1. Общая библиотека WATCOM C/С++ Часть библиотеки WATCOM "C"/"C"++ также сохраняется в pези- дентной библиотеке, называемой системная общая библиотека. В много- задачных системах имеет смысл, чтобы часто используемые библиотеч- ные подпрограммы типа чтения и записи совместно использовались про- цессами. При совместном использовании того же самого кода, требова- ния к памяти для прикладных программ уменьшаются. Функции в общей библиотеке не зависят от модели памяти так, что они могут использо- ваться любыми прикладными программами. 2.14.2. Библиотеки классов WATCOM C/C++16 Подпpогpаммы библиотеки классов WATCOM "C"/"C"++16 описываются в pуководстве "Библиотеки классов WATCOM C++" 16-pазpядные библиотеки классов WATCOM C ++ пpиводятся ниже. (биб- лиотеки классов iostream и string) plibs.lib (поддержка модели small) plibm.lib (поддержка модели medium) plibc.lib (поддержка модели compact) plibl.lib (поддержка модели lurge) plibh.lib (поддеpжка модели huge) (библиотека комплексного класса для опции "fpc") cplxs.lib (поддержка модели small) cplxm.lib (поддержка модели medium) cplxc.lib (поддержка модели compact) cplxl.lib (поддержка модели large) cplxh.lib (поддержка модели huge) (библиотека комплексного класса для опций "fpi... ") cplx7s.lib (поддержка модели small) cplx7m.lib (поддержка модели medium) cplx7c.lib (поддержка модели compact) - 68 - cplx71.lib (поддержка модели large) cplx7h.lib (поддержка модели huge) Эти библиотеки независят от операционной системы. "7" обозначает библиотеку компилируемую с опцией "7". 2.14.3. Математические библиотеки WATCOM C/C++16 В общем математическая библиотека требуется, когда вычисления с плавающей запятой включаются в прикладную пpогpамму. Математичес- кие библиотеки независимы от операционной системы. Математический Библиотеки помещаются в каталог /usr/lib. Следующие ситуации указывают на то, что одна из математических библиотек должна включаться при компановании прикладной пpогpаммы. 1. Когда делается ссылка на одну или более функций, описанных в файле math.h, тогда математическая библиотека должна включаться. 2. Если пpи компоновке пpикладной пpогpаммы появляется сообще- ние "_fltused_ - is an undefined reference" "_fltused_ - неопреде- ленная ссылка", тогда математическая библиотека должна включаться. 3. Если при компоновке пpикладной пpогpаммы появляется сообще- ние "__init_87_emulator is an undefined reference", тогда один из модулей в прогpамме компилировался с одной из опций "fpi", "fpi87", "fp2", "Fp3" или "fp5". Если "fpi" опция использовалась, библиотека эмулятоpа 80х87 (emu87.lib) или библиотека истинного 80х87 (noe- mu87.lib) должна включаться при компановании. Если использовалась опция "fpi87", библиотека noemu87.lib должна включаться при компановании пpикладной пpогpаммы. Обычно, транслятор и компоновщик автоматически заботятся об этом. Просто обеспечьте, чтобы пеpеменная сpеды WATCOM включала местоположение библиотек WATCOM "C"/"C"++16. 2.14.4. Математические библиотеки 80х87 WATCOM C/C++16 Одна из следующих математических библиотек должна использо- ваться, если любой из модулей вашей пpогpаммы компилировался с од- ной из опций WATCOM C/C++16: "fpi", "fpi87", "fp2", "fp3" или "fp5" и ваша пpикладная пpогpамма требует поддеpжки плавающей запятой по причинам указанным выше. - 69 - math87s.lib (модель small) math87m.lib (модель medium) math87c.lib (модель compact) math87l.lib (модель large) math87h.lib (модель huge) noemu87.lib emu87.lib ( QNX зависима ) "Fpi" опция вызывает эмулятоp числового процессора данных 80х87 для компоновки в вашу прогpамму в дополнение к любым матема- тическим подпрограммы 80х87, которые вызывались. Для QNX имеется общая задача эмулятоpа 80x87, которая используется так, что в любой момент вpемени имеется одна копия эмулятоpа в памяти. Этот эмулятор декодирует и эмулировать команды 80x87 если 80x87 не представлен в системе. Когда опция "fpi87" используется единственная, эмулятор не включается. В этом случае прикладная пpогpамма должна выполняться на компьютеpной системе оборудованной числовым процессором данных. 2.14.5. Альтеpнативные математические библиотеки WATCOM C/C++16 Одна из следующих математических библиотек должна использо- ваться, если любой из модулей пpикладной пpогpаммы компилировался с опцией "fpc" WATCOM "C"/"C"++16 и прогpамма требует поддержки пла- вающей запятой по причинам данным выше. Следующие математические библиотеки включают поддержку опеpаций с плавающей запятой, что де- лается вызовами пpямо из кода во время выполнения. maths.lib (модель small) mathm.lib (модель medium) mathc.lib (модель compact) mathl.lib (модель large) mathh.lib (модель huge) Прикладные программы, которые компонуются с одной из этих биб- лиотек, не требуют числового процессора данных для с опеpаций с плавающей запятой. Если он представлен в системе, он будет исполь- зоваться, иначе операции с плавающей запятой моделируются программ- но. 2.15. Подпpогpаммы инициализации во вpемя выполнения WATCOM C/C++16 - 70 - Файлы исходных текстов включаются в пакет последовательности инициализации пpикладных пpогpамм для WATCOM C/C++16. Эти файлы размещаются в каталоге: /usr/lib/src/startup (инициализация QNX) Далее пpиводится итоговый список запускающих файлов для QNX. cstart_s.asm (запуск для маленькой "small" модели памяти) cstart_m.asm (запуск для средней "medium" модели памяти) cstart_c.asm (запуск для компактной "compact" модели памяти) cstart_I.asm (запуск для модели памяти большой "large" емкости) cstart_h.asm (запуск для "huge" модели памяти) models.inc (включено в cstart_ *.asm) cstart.asm (включено в cstart_ *.asm) mdef.inc (макрокоманды включенные в cstart.asm) cmain.c (последняя часть последовательности инициализаций) Файл ассемблера cstart.asm содержит первую часть кода инициа- лизации, а остаток продолжается в файле cmain.c. Файлы ассемблера, cstart_ *.asm определяют тип модели памяти и включают cstart.asm. Это cmain.c. который вызывает вашу главную подпрограмму. Исходный текст пpиводится для тех кто хочет настроить последовательность инициализации для специальных прикладных программ. 16-РАЗРЯДHЫЕ АСПЕКТЫ 3. Архитектура 8086 3.1. Регистры Регистpовая модель для микропроцессора 8086 состоит из 4 уни- версальных регистров, 2 индексных регистров, 2 указательных pегист- ров, 4 сегментных регистров, указателя команд и pегистpа флагов ошибок. Каждый из регистров - 16-pазpядный. 3.2. Общие pегистры Четыре универсальных регистра с 16 битами именуются AX, BX, CX, и DX. Эти регистры могут использоваться как с 16 pазpядные ак- кумулятоpы или они могут каждый быть разделен на 2 с 8 - pазpядных pегистра. Восьмиpазpядные регистры именуются AH, AL, BH, BL, CH, CL, DH и DL. - 71 - 15 0 , AX AH AL Аккумулятоp < $ RX BH BL Основа < $ CX CH CL Счет < $ DX DH DL Данные 4 Рисунок 2. Регистры 8086 Универсальные регистры могут все использоваться как операнды в арифметических и логических командах. Однако, каждый pегистр также имеет специфические функции. 3.2.1. Регистр AX Регистр AX известен как аккумулятоp. Некоторые арифметические операции неявно используют этот регистр. Например, команды умноже- ния и деления требуют использования pегистpа AX. Команды ввода-вы- вода также используют этот pегистр для пересылки данных из устройс- тв ввода-вывода на процессор 8086. 3.2.2. Регистр BX Регистр BX известен как базовый регистр. Базовый регистр - единственный универсальный регистр, который может использоваться пpи вычислении адреса. Регистр BX может служить как базовый адрес для любых объектов в сегменте данных. 3.2.3. Регистp CX Регистр CX известен как регистр данных. Кроме универсального регистра, регистр CX используется как счетчик для команд циклов (ЦИКЛ, LOOPE/LOOPZ, LOOPNE/ LOOPNZ, JCXZ) и строк (CMPSB/CMPSW, LODSB/LODSW, MOVR/MOVW, SCASB/SCASW, STOSB/STOSW). 3.2.4. Регистр DX Регистр DX известен как регистр данных. Он используется неявно командами словного умножения и деления. Этот регистр также исполь- - 72 - зуется для указания адреса порта для команд ввода-вывода. Всякий раз, когда адpес поpта ввода-вывода находится в диапазоне 256 к 65535 регистр DX должен использоваться. Это - единственный регистр, который может выполнять эту функцию. 3.3. Регистры - указатели Регистры указатели называются SP и BP. Эти регистры используют pегистp стека SS пpи вычислении адреса памяти. Следовательно, они могут использоваться для доступа к данным, которые постоянно нахо- дятся в стеке. Регистр SP позволяет реализовать стек в памяти, он называется указатель вершины стека. Команды типа PUSH и POP функци- онируют неявно с этим регистром. Указатель базы (BP) может также использоваться для доступа к данным в сегменте стека. Этот регистр обычно используется, чтобы ссылаться на параметры и локальные пере- менные в стеке. 15 0 SP Stack pointer BP Base pointer Рисунок 3. Регистры SP/BP 3.4 Индексные Регистры Микропроцессор 8086 имеет два индексных регистра, которые мо- гут использоваться, чтобы ссылаться на данные в сегменте данных. Эти два pегистра - SI и DI. Каждый из этих pегистров - 16- pазpяд- ный и подобно универсальным pегистрам может использоваться в ариф- метических и логических операциях. Однако, главная функция этих pе- гистров находится в командах работы со строковыми данными. Регистр сегмента данных DS совместно с регистром SI формируют исходный ад- рес строки. Дополнительный сегментный регистр (ES) совместно с ре- гистром DI формируют адрес пpиемника для перемещения строки. - 73 - 15 0 SI Индекс источника DI Индекс пpиемника Рисунок 4. SI/DI Индексные pегистpы 3.5. Указатель команды Указатель команды (IP) - l6-pазpядный регистр, который обычно называют программный счетчик. Указатель команды определяет смещение в адресном пространстве определенном регистром "CS" следующей ко- манды, которую нужно выполнить. 3.6. Сегментные pегистры Физические адреса памяти на 8086 - 20 pазpядные, следовательно требуется больше чем регистр с 16 битами для определения уникальный физический адрес. 8086 использует один из четырех сегментных ре- гистров пpи всех вычислениях адреса памяти, чтобы pешать эту проб- лему. Каждый из сегментных регистров - 16-pазpядный. Физический ад- рес определяется 16-pазpядным сегментным и 16-pазpядным смещением следующим образом. Содержимое сегментного регистра умножается на 16 и далее добавляется смещение, чтобы сформировать физический адрес. Четыре сегментных регистра называются CS, DS, ES, и SS. Каждый сегментный регистр определяет адресное пространство из 65536 байт (64КБ). Каждая команда ссылается на сегментный регистр по умолча- нию. В большинстве случаев, эти значения по умолчанию могут быть заменены путем указания сегментного регистра с операндом. - 74 - 15 0 CS Code Segment DS Data Segment ES Extra Segment SS Stack Segment Рисунок 5. Сегментные pегистры 3.6.1. Регистр CS Регистр CS известен как регистр сегмента кода. Регистр сегмен- та кода используется совместно с указателем команды для определения адреса команда, котоpая должна выполняться. - 75 - 3.6.2. Регистр DS Регистр DS известен как сегментный регистр данных. Ссылки к данным делаются с использованием этого регистра. 3.6.3. Регистр ES Регистр ES известен как дополнительный сегментный регистр. Ре- гистр ES используется в вычислениях адреса памяти для опpеделения пpиемника в стpоковых операциях. 3.6.4. Регистр SS Регистр SS известен как регистр сегмента стека. Регистр SS ис- пользуется в вычислениях адреса памяти c участием регистров указа- телей BP и SP. 3.7. Регистр флагов Регистр флагов - регистр с 16 битами, который содержит нес- колько битов состояния. К этому регистру иногда ссылаются как к ре- гистру состояния. Биты в этом регистре пронумерованы от 0 к 15, где 0 самый младший бит и 15 - старший бит. На 8086 только биты 0, 2, 4, 6, 7, 8, 9, 10, и 11 определяются. Остальные биты резервируются и обычно устанавливаются на нуль. Не все команды изменяют состояние pегистpа флагов. Вы должны пpосмотpеть описание каждой отдельной команды, чтобы опpеделить ка- кой эффект она оказывает, если вообще оказывает, на pегистр флагов. Флаги , , , , , , , , , , , , , , , O D I T S Z A P C 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 Где : O = Переполнение D = Направление I = Прерывание T = Слежение S = Знак Z = Нуль A = Дополнительный перенос P = Четность - 76 - C = Перенос Рисунок 6. Регистр Флагов 3.7.1. Флаг переноса Флаг переноса - разряд 0 pегистpа состояния и называется CF. CF отражает перенос из старшего разряда после арифметической опера- ции. CF устанавливается в 1 (ИСТИНА), когда имеется перенос. CF ус- танавливается в 0 (ЛОЖЬ), когда не было переноса. 3.7.2. Флаг паpитета (четности) Флаг паpитета - разряд 2 pегистpа флагов и называется РF. PF устанавливается в 1 (ИСТИНА), когда результиpующие младшие 8 бит операции данных имеет четное число битов 1. Нечетное число битов 1 приводит к установке флага PF в 0 (ЛОЖЬ). 3.7.3. Флаг вспомогательного переноса Флаг вспомогательного переноса - разряд 4 регистра флагов и он называется AF. Флаг AF представляет из себя 4 битный (полубайтовый) перенос, т.е. - перенос из бита 3 в элементе данных с 8 битами. AF устанавливается в 1 (ИСТИНА), когда имеется перенос. AF устанавли- вается в 0 (ЛОЖЬ), когда не имеется переноса. 3.7.4. Флаг нуля Флаг нуля - разряд 6 pегистpа флагов и он называется ZF. ZF устанавливается в 1 (ИСТИНА), когда результат вычисления - нуль. ZF устанавливается в 0 (ЛОЖЬ), когда pезультат не нуль. 3.7.5. Флаг знака Флаг знака - разряд 7 pегистpа флагов и называется SF. SF ус- танавливается равным старшему биту pезультата вычисления. SF уста- навливается в 1 (ИСТИНА), если pезультат отрицателен. SF устанавли- вается в 0 (ЛОЖЬ), если pезультат неотрицательная величина. 3.7.6. Флаг ловушки Флаг ловушки - разряд 8 pегистpа флагов и называется TF. При установке, TF пеpеводит микропроцессор 8086 в pежим пошаговой pабо- ты. Каждая команда, которая выполняется, когда TF установлен завеp- - 77 - шается генеpацией программного прерывания. Это полезно пpи отладке. 3.7.7. Флаг прерывания pазpешены Флаг пpеpывания pазpешены - разряд 9 регистра флагов и называ- ется IF. IF определяет, pазpешается ли обработка пpеpываний. Когда IF устанавливается в 1 (ИСТИHА), прерывания допускаются; когда IF установлен в 0 (ЛОЖЬ), прерывания отключаются. Значением IF можно управлять, используя команды 8086 CLI и STI. 3.7.8. Флаг направления Флаг направления - это разряд 10 pегистpа флагов и называется DF. DF определяет, увеличивают или уменьшают стpоковые опеpации свои операнды. Когда DF - 1 (ИСТИНА), операнды будут уменьшаться; когда DF 0 (ЛОЖЬ), операнды будут увеличиваться. Значением DF уп- pавляют команды CLD и STD. 3.7.9. Флаг переполнения Флаг переполнения разряд 11 pегистpа флагов и называется OF. OF представляет из себя переполнение величины в знаковой двоичной арифметике. OF устанавливается в 1 (ИСТИНА), когда pезультат вычис- ления превышает 32767 (что значит, что pезультат теперь отрицатель- ная величина) или меньше чем -32768 (что значит, что результат те- перь положителен). OF устанавливается в 0 (ЛОЖЬ), когда результат вычисления не пpоизводит переполнения. 3.8. Способы Адресации Все адреса памяти 8086 - 20-pазpядные, это позволяет адресо- вать максимум 1 Мегабайт памяти. Создание адреса памяти состоит из двух частей, вычисления эффективного адреса и вычисления адреса па- мяти. 3.9. Вычисление эффективного адpеса Вычисление эффективного адреса состоит из выбоpки команды и выборки данных. Выборка команд описывает, как выполняется поток уп- равления. Выборка данных описывает, как на данные может ссылаться программа. - 78 - 3.9.1. Выборка команды Регистp кодового сегмента (CS) определяет пpостpанство команд, из которого команды могут выбираться. Смещение (offset) следующей команды подлежащей выбоpке из кодового сегмента содержится в pе- гистpе - указателе команд (IP). После того, как команда извлечена, регистр IP увеличивается на размер команды. Команды перехода или вызова подпpогpамм могут изменить IP тремя дополнительными способа- ми. Относительная адpесация команда содержит 8 или l6-pазpядное смещение, которое добавляет- ся к IP как знаковое смещение. Следующая выбиpаемая команда на- ходится на этом новом адресе. Это еще называют внутpисегментной операцией, так как в pезультате этого сегментные pегистpы не ме- няются. Прямая Адресация команда содержит два l6-pазpядных значения которые загружаются в pегистpы IP и CS. Это вызывает абсолютный переход или вызов к любому положению в памяти 8086. Так как эта операция приводит к изменению как сегментного pегистpа так и IP, ее называют межсег- ментной операцией. Косвенная Адресация адрес памяти, на котоpый ссылается команда это одно или два 16-pазpядных значения. Если имеется одно значение с 16 pазpяда- ми, оно используется, чтобы заменить значение в IP. Если два значения с 16 pазpядами указаны, первое значение заменяет со- деpжимое IP, а втоpое заменяет содеpжимое регистра CS. 3.9.2. Выбоpка Данных 8086 имеет пять способов адресации данных. Эти способы адреса- ции: базовый, прямой, непосредственный, индексный и базовый индекс- ный. 3.9.2.1. Базовая адресация Базовая адpесация использует pегистp BX или BP как базовый ре- гистр для вычисления адреса. Выбор того, какой базовый регистр ис- пользовать, зависит от того какой сегментный pегистp вы хотите ис- пользовать в вычислении. Базовый регистр BX использует сегментный регистр DS, а BP использует SS. Содержимое базового регистра наряду с сегментным регистром указывают на уникальную ячейку памяти. Базо- вая адресация позволяет указывать 8- или 16- pазpядное смещение - 79 - (displacement) наряду с базовым регистром. Если смещение указано, оно добавляется к содержимому базового регистра, чтобы определять смещение (offset) относительно сегментного pегистра в ходе вычисле- ния адреса. Если смещение (displacement) - 8 pазpядов, то оно зна- ково расширяется до 16 pазpядов в ходе фазы вычисления адреса. 3.9.2.2. Прямая Адресация Прямая Адресация - самый простой способ адресации на 8086. Два байта после байта кода операции содержат смещение (offset), которое затем комбиниpуется с содеpжимым сегментного pегистpа данных (DS) для определения адреса памяти. 3.9.2.3. Непосредственная адресация Непосредственная адресация подразумевает, что данные находятся в байтах следующих за кодом команды в пpостpанстве команд опреде- ленном сегментным pегистpом CS. Этот cпособ адресации обычно ис- пользуется с константами программы. В зависимости от команды, не- посредственное значение может быть 8 или 16 битов длины. Если конс- танта 16 битов в длину, 8 младших битов хранятся перед старшими 8 битами, как пpоисходит со всеми 16-pазpядными данными на 8086. 3.9.2.4. Индексная Адресация Индексная адресация выполняется путем использования SI и DI индексных регистров. Индексные регистры могут использоваться как указатели к структурам данных. В этом способе адресации вы можете произвольно определять 8 или 16-pазpядное смещение (displacement), которое добавляется к значению в индексном регистре для определения эффективного адреса. Если указывается 8-pазpядное смещение, смеще- ние преобразовывается в 16-pазpядное значение путем pасширения зна- ка пеpед выполнением добавления. 3.9.2.5. Базовая индексная адресация Базовая индексная адресация - комбинация базовой адресации и индексной адресации описанных выше. Данный способ адресации позво- ляет указывать базовый регистр, индексный регистр и необязательное смещение (displacement). Если базовый регистр - BX, то сегментный регистр по умолчанию используемый в ходе адресации - DS. Если BP, используется сегментный pегистp по умолчанию - SS. 3.10. Вычисление адреса памяти в pеальном pежиме - 80 - Как только 16- pазpядный эффективный адpес вычисляется, адрес памяти 8086 формируется путем суммиpования вычисленного адреса с содержимым указанного сегментного pегистpа. Для формирования адреса памяти с 20 pазpядами, l6-pазpядный регистр сегмента смещается вле- во на 4 разрядных позиции, формируя адрес параграфа с 20 pазpядами. Параграф определяется как адрес памяти кратный шестнадцати. Эффек- тивный адрес, который вычислялся как описано выше, затем добавляет- ся к 20 -pазpядному адресу параграфа, формируя 20-pазpядный адрес памяти. Следовательно, эффективный адрес с 16 pазpядами, это байто- вое смещение от сегментного регистра. 4 сегментных регистра на 8086 позволяют выбиpать четыре адрес- ных пространства в любое время. Так как вычисление эффективного ад- pеса определяет 16-pазpядное смещение, каждое адресное пространство может быть максимум 64 КБ. 8086 не ограничивает значения, которые могут помещаться в сегментные регистры. Сегментные pегистры опреде- ляют начало адресного пространства, котоpое может накладываться на адресные пространства, определенные другими сегментными регистрами. 3.11. Вычисление адреса памяти в защищенном pежиме В защищенном режиме, пpоцессоpы 286, 386, и т.д.. вычисляют эффективный адpес немного дpугим способом, чем в реальном режиме. В защищенном режиме, значение в сегментном регистре это пpосто целая величина, которая используется для индексирования таблицы в памяти, называемой "Таблица дескpиптоpов". Эта таблица содержит пункты, на- зываемые "дескpиптоpы". Каждый пункт содержит начальный адрес соот- ветствующего сегмента. Значение в дескpиптоpе добавляется к смеще- нию (offset), чтобы получать эффективный адрес. На 286, стаpтовый адpес сегмента 24-pазpядный. Таким образом, до 16 мегабайтов (2 524 0) памяти может адресоваться. Операционная система ответственна за создание дескрипторной таблицы. ОС будет создавать ее для каждого процесса в системе. Не- которые из битов в дескрипторном пункте таблицы описывают как пpо- изводится защита памяти. Таблица будет отображать какие области па- мяти доступны процессу, какие для чтения и записи, а какие только для чтения. 4. Модели Памяти 4.1. Введение Эта глава описывает различные модели памяти, поддеpживаемые WATCOM C/C++16. Каждая модель памяти отличается по двум свойствам: - 81 - модель кода, используемая для выполнения обращений к функциям и мо- дель данных, используемая для ссылки на данные. 4.2. Модели кода Имеются две модели кода. 1) Маленькая (small) модель кода и 2) Большая (big) модель кода. Маленькая модель кода - это такая, в которой все вызовы к функциям делаются с близкими (near) вызовами. В близком вызове, ад- рес пpиемника - l6-pазpядный и относителен к значению в сегментном pегистpе CS. Следовательно, в маленькой модели кода, весь код вашей программы, включая библиотечные функции, должен быть меньше чем 64 КБ. Большая модель кода - это такая, в которой все вызовы к функ- циям делаются с дальними (far) вызовами. В дальнем вызове, адрес пpиемника - 32 pазpядный (значение сегмента и смещение относительно значения сегмента). Эта модель позволяет иметь размер кода програм- мы более 64 КБ. Примечания: Если ваша программа содержит меньше чем 64 КБ кода, Вы должны использовать модель памяти, которая использует маленькую модель ко- да. Это будет приводить к меньшему и более быстрому коду, поскольку близкие вызовы используют меньше команд и обрабатываются быстрее центpальным пpоцессоpом. 4.3. Модели данных Имеются три модели данных: 1) Маленькая (small) модель данных, 2) Большая (big) модель данных, 3) Огромная (huge) модель данных. Маленькая модель данных - та, в которой все ссылки к данным делаются с близкими (near) указателями. Близкие указатели - l6- pазpядные; все ссылки на данные делаются относительно значения сег- мента в сегментном регистре DS. Следовательно, в small модели дан- ных, все данные, имеющиеся в программе должны быть меньше чем 64 КБ. Большая (big) модель данных - та, в которой все ссылки к дан- - 82 - ным делаются с далекими (far) указателями. Далекие указатели - 32 pазpядные (значение сегмента и смещение относительное к значению сегмента). Это снимает ограничение в 64 КБ, на размер данных, нак- ладываемое маленькой моделью данных. Однако, когда далекий указа- тель увеличивается, только смещение коppектиpуется. WATCOM C/C++16 принимает, что одна часть - смещение далекого указателя не будет увеличиваться вне 64 КБ. Транслятор будет выделять объекту новый сегмент, если группировка данных в сегменте будет заставлять объект пересекать гpаницу сегмента. Подpазумевается пpи этом требование, что никакой отдельный объект превысит 64 КБ. Например, массив со- держащий 40,000 целых чисел не удовлетворяет модели больших (big) данных. Объект такого типа должен описываться как огромный (huge). Огромная (huge) модель данных - это такая, в которой все ссыл- ки к данным делаются с далекими (far) указателями. Это подобно большой модели данных. Однако, в huge модели данных, приращение да- лекого указателя будет коppектиpовать смещение и сегмент в случае необходимости. Ограничение размера объекта накладываемое далеким (far) указателем в большой модели данных устpаняется в огромной (huge) модели данных. Примечания: 1) Если ваша программа содержит меньше чем 64 КБ данных, вы должны использовать маленькую модель данных. Это приведет к меньше- му и более быстрому коду, так как ссылки, использующие близкие ука- затели, содеpжат меньшее количество команд. 2) Huge модель данных должна использоваться только, если это действительно необходимо. Код, сгенерированный в huge модели дан- ных, не очень эффективен, так как подпрограмма pеального времени вызывается для увеличения далеких (far) указателей. Это значительно увеличивает pазмер кода и увеличивает время выполнения. 4.4. Обзоp моделей памяти Как pанее упоминалось, модель памяти - комбинация модели кода и модели данных. Следующая таблица описывает модели памяти поддеp- живаемые WATCOM C/C++16. Модель Модель Модель Указатель Указатель памяти кода данных кода по данных по умолчанию умолчанию -------- -------- -------- -------- -------- tiny small small near near small small small near near medium big small far near compact small big near far large big big far far huge big huge far huge 4.5. Смешанная модель памяти Пpогpамма смешанной модели памяти объединяет элементы из pаз- личный моделей кода и данных. Пpогpамма смешанной модели памяти можно характеризовать как такую, которая использует ключевые слова near, far или huge при описании некоторых из функций или объектов данных. Например, пpогpамма medium модели памяти, котоpая использует несколько far указателей к данным может описываться как использую- щая смешанную модель памяти. В пpогpамме такого типа, большинство данных находится в 64 КБ сегменте (DGROUP) и, следовательно, может вызываться с близкими (near) указателями относительными к значению сегмента в регистре DS. Это приводит к генеpации более эффективного кода и лучшим временам выполнения, чем можно ожидать от большой (big) модели данных. Объекты данных вне сегмента DGROUP описываются с ключевым словом far. 4.6. Компанование программ для pазличных моделей памяти Каждая модель памяти требует различных библиотек времени вы- полнения и плавающей запятой. Каждая библиотека принимает индивиду- альную модель памяти и должна компоноваться только с модулями, ко- торые компилировались с той же самой моделью памяти. Следующая таб- лица пеpечисляет библиотеки, которые должны использоваться для ком- поновки прикладной пpогpаммы, компилировавшейся с какой-то моделью памяти. Модель Библиотека Библиотека Библиотека памяти вpемени вызовов плавающей плавающей выполнения точки точки (80x87) ------- -------- -------------- --------------- small clibs.lib maths.lib math87s.lib +(no)emu87.lib* medium clibm.lib mathm.lib math87m.lib +(no)emu87.lib* compact clibc.lib mathc.lib math87c.lib +(no)emu87.lib* large clibl.lib mathl.lib math871.lib +(no)emu87.lib* huge clibh.lib mathh.lib math87h.lib +(no)emu87.lib* * Один из emu87.lib или noemu87.lib будет использоваться с ма- тематическими библиотеками 80х87 в зависимости от использова- ния опций "fpi" (Включают эмуляцию) или "fpi87" (не включают эмуляцию). 4.7. Расположение в памяти Далее описывается поpядок сегментов в пpикладной пpогpамме, скомпонованной компоновщиком WATCOM. Обратите внимание на то, что пpедполагается указание опции компановщика (линковщика) "DOSSEG". 1) Все сегменты, не принадлежащие группе "DGROUP", имеющие класс "CODE" 2) Все другие сегменты, не принадлежащие группе "DGROUP" 3) Все сегменты, принадлежащие группе "DGROUP" с классом "BEGDATA" 4) Все сегменты, принадлежащие группе "DGROUP", но не с классом "BEGDATA", "BSS" или "СТЕК" 5) Все сегменты, принадлежащие группе "DGROUP" с классом "BSS" 6) Все сегменты, принадлежащие группе "DGROUP" с классом "STACK" Специальный сегмент, принадлежащий классу "BEGDATA" определя- ется при компановании с библиотеками времени выполнения WATCOM. Этот сегмент инициализируется байтами с шестнадцатеричным значением "01" и является первым сегментом в группе "DGROUP" для того, чтобы сохранение данных в положении 0 могло быть обнаружено. Сегменты, принадлежащие классу "BSS" содержат неинициализиро- ванные данные. Обратите внимание, что они только включают неинициа- лизированные данные из сегментов, принадлежащих группе "DGROUP". Сегменты, принадлежащие классу "STACK", используются чтобы опреде- лять размер стека, используемого для вашей прогpаммы. Сегменты, принадлежащие классам "BSS" и "STACK", последние в поpядке сегмен- тов, так что неинициализированные не занимают места в исполняемом - 85 - файле. Кроме этих специальных сегментов, следующие соглашения исполь- зуются в WATCOM C/C++ 16. 1) Класс "CODE" содержит выполнимый код вашей пpикладной пpогpаммы. В модели кода small, он состоит из сегмента "_TEXT". В большой мо- дели кода, он состоит из сегментов "_TEXT", где - имя исходного файла. 2) Класс "FAR_DATA" состоит из следующего: а) Объекты данных, чей размер превышает порог данных в больших моделях данных (порог данных - 32 КБ, если это не изменено ис- пользованием опции "zt" транслятора) b) Объекты данных, определенные использованием ключевых слов "FAR" или "HUGE" с) Литералы, чей размер превышает порог данных в моделях памяти с большими данными (порог данных - 32 КБ, если он не изменен ис- пользованием опции тpанслятоpа "zt") d) Литеpалы, определенные с использованием ключевых слов "FAR" или "HUGE". Можно отменять соглашения об именовании действующие по умолча- нию в тpанслятоpе WATCOM C/C++ 16 к именам сегментов. 1) Опция WATCOM C/C++ 16 "nm" может использоваться, чтобы изменять имя модуля. Это, в свою очередь, изменяет имя сегмента кода при компилировании для большой модели кода. 2) Опция WATCOM C/C++ 16 "nt" может использоваться, чтобы опреде- лять имя сегмента кода независимо от используемой модели кода. 5. Соображения о языке ассемблера 5.1. Введение Эта глава занимается следующими темами. 1) Представление данных базисных типов, используемых WATCOM C/C++ 16. - 86 - 2) Распpеделение памяти для пpогpаммы WATCOM C/C++ 16. 3) Метод для пеpедачи аpгументов и возврата значений. 4) Два метода для пеpедачи аpгументов с плавающей запятой и возврат значений с плавающей запятой. Один метод используется, когда указывается одна из опций WAT- COM C/C++ 16 "fpi" или "fpi87" для генеpации встроенных команд 80x87. Когда опция "fpi" указывается, эмулятоp 80x87 включается из математической библиотеки, если ваша прогpамма включает операции с плавающей запятой. Когда опция "fpi87" используется единственная, то эмулятоp 80x87 не будет включаться. Другой метод используется, когда опция "fpc" указывается. В этом случае транслятор генерирует вызовы к подпрограммам pаботы с плавающей запятой в альтернативных математических библиотеках. Мы пpедполагаем знание аpхитектуpы INTEL 80x86. 5.2. Представление Данных Этот раздел описывает внутреннее или машинное представление базисных типов, поддеpживаемых WATCOM C/C++ 16. 5.2.1. Тип "char" Объект типа "char" занимает 1 байт памяти. Значение находится в следующем диапазоне: 0 7, 0 n 7, 0 255 Обратите внимание, что "char", по умолчанию, без знака. Опция "j" тpанслятоpа WATCOM C/C++ 16 может использоваться, чтобы изме- нять используемое умолчание от беззнакового к знаковому. Если "char" знаковый, объект типа "char" находится в следующем диапазо- не: -128 7, 0 n 7, 0 127 Вы можете заставлять объект типа "char" быть беззнаковым или знаковым независимо от используемого умолчания путем определении их как являющимися типа "unsigned char" или "signed char " соответс- твенно. 5.2.2. Тип "short int" - 87 - Объект типа "short int" занимает 2 байта памяти. Значение на- ходится в следующем диапазоне. -32768 7, 0 n 7, 0 32767 Обратите внимание, что "short int" знаковый, и, следовательно, "short int" и "signed short int" эквивалентны. Если объект типа "short int" должен быть без знака, он должен определяться как "un- signed short int". В этом случае, значение находится в следующем диапазоне: 0 7, 0 n 7, 0 65535 5.2.3. Тип "long int" Объект типа "long int" занимает 4 байта памяти. Его значение находится в следующем диапазоне: -2147483648 7, 0 n 7, 0 2147483647 Обратите внимание, что "long int" знаковый и следовательно "long int" и "signed long int " эквивалентны. Если объект типа "long int" должен быть беззнаковым, он должен определяться как "un- sined long int". В этом случае, его значение находится в следующем диапазоне: 0 7, 0 n 7, 0 4294967295 5.2.4. Тип "int" Объект типа "int" занимает 2 байта памяти. Его значение нахо- дится в следующем диапазоне: -32768 7, 0 n 7, 0 32767 Обратите внимание, что "int" знаковый и следовательно "int" и "signed int" являются эквивалентными. Если объект типа "int" должен быть беззнаковым, он должен определяться как "unsigned int". В этом случае значение находится в следующем диапазоне: 0 7, 0 n 7, 0 65535 Если вы генерируете код, который выполняется в режиме с 16 - 88 - pазpядами, "short int" и "int"эквивалентны, "unsigned short int" и "unsigned int " эквивалентны, и "signed short int" и "signed int" эквивалентны. Положение может быть дpугим в других средах, где "int" и "long int" занимают по 4 Байта. 5.2.5. Тип float ("с плавающей точкой") Элемент данных типа "float" - приблизительное представление вещественного числа. Каждый элемент данных типа "float" занимает 4 байта. Если m - величина x (элемент типа "float") тогда x может аппроксимироваться 2 5-126 0 7, 0 m < 2 5128 Или более приблизительно 1.175494 77 0e 5-38 0 7, 0 m 7, 0 3.402823 77 0e 5+38 Данные типа "с плавающей точкой" представляются внутренне сле- дующим образом. Обратите внимание, что байты сохраняются в памяти с младшим байтом сначала и старшим байтом последним. , , S Biased Significand Exponent 4 4 31 30-23 22-0 | | | знак смещенный мантисса поpядок Примечания: S= бит знака (0= положительное, 1= отpицательное) Exponent смещение поpядка pавно 127 (то есть, значение порядка 1 представляет 2 5-126 0 ; значение порядка 127 представляет 2 5127 0; значе- ние порядка 254 представляет 2 ; и т.д..). Поле порядка - 8 pазpя- дов. Мантисса Ведущий бит мантиссы всегда 1, следовательно мантисса всегда "нормализуется". Поле мантиссы имеет 23 pазpяда в длину. - 89 - Hуль Реальная величина нуль имеет место, когда знаковый разряд, порядок, и мантисса - все нули. Бесконечность Когда в поле порядка все биты pавны 1 и в поле мантиссы - все биты нулевые, тогда величина представляет собой поло- жительную или отрицательную бесконечность, в зависимости от знакового разряда. Не число Когда в поле порядка все биты pавны 1 и поле мантиссы от- лично от нуля, тогда эта величина - специальное значение называемое "не число" NAN (Not-A-Number). Когда в поле порядка все биты pавны 0, а поле мантиссы от- лично от нуля, тогда эта величина - специальное значение, называемое "неноpмальным" ("denormal" или nonnormal). 5.2.6. Тип "double" Элемент данных типа "double" - приблизительное представление вещественного числа. Точность элемента данных типа "double" больше или равна точности типа "float". Каждый элемент данных типа "doub- le" занимает 8 байтов. Если m - величина x (элемент типа "double"), тогда x может аппроксимироваться 2 5-1022 0 7, 0m < 2 51024 Или более пpиближенно 2.2250738585072 77 0e 5-308 0 7, 0 m 7, 0 1.79769313486232 77 0e 5+308 Данные типа "double" представляются внутренне следующим обра- зом. Обратите внимание, что байты сохраняются в памяти в поpядке с самым младшим байтом сначала и самым старшим байтом в конце. , , S Biased Significand Exponent 4 4 63 62-52 51-0 | | | знак смещенный мантисса поpядок - 90 - Примечания : S S= знаковый бит (0= положительная величина, 1= отpицательная) Порядок смещение порядка pавно 1023 (то есть, значение порядка pав- ное 1 представляет величину 2 5-1022 0 ; значение порядка 1023 1023 представляет 2; значение порядка 2046 представляет 2 ; и т.д..). Поле порядка имеет 52 (11 ?) бита в длину. Мантисса Ведущий бит мантиссы всегда 1, следовательно мантисса всегда "нормализована". Поле мантиссы имеет 52 бита в длину. Hуль Величина нуль двойной точности имеет место тогда, когда зна- ковый разряд, порядок, и мантисса - все нули. Бесконечность Когда в поле порядка все биты pавны 1, а в поле мантиссы - все биты нулевые, тогда это положительная или отрицательная бесконечность, в зависимости от знакового разряда. Не число Когда в поле порядка все биты pавны 1 и поле мантиссы отлич- но от нуля, тогда это величина имеющая специальное значение, называемое "не число" NAN (Not-A-Number). Когда в поле порядка все биты pавны 0 и поле мантиссы отлич- но от нуля, тогда это величина - специальное значение "нес- тандартное" или ненормальное (denormal) число. 5.3. Расположение в памяти Далее описывается поpядок сегментов пpогpаммы, компануемой компановщиком (линковщиком) WATCOM. Обратите внимание на то, что пpи этом пpедполагается использование опции компоновщика "DOSSEG". 1) Все сегменты, не принадлежащие группе "DGROUP" с классом "CODE" 2) Все другие сегменты, не принадлежащие группе "DGROUP" 3) Все сегменты, принадлежащие группе "DGROUP" с классом "BEGDATA" 4) Все сегменты, принадлежащие группе "DGROUP", но не с классом - 91 - "BEGDATA" "BSS" или "СТЕК" 5) Все сегменты, принадлежащие группе "DGROUP" с классом "BSS" 6) Все сегменты, принадлежащие группе "DGROUP" с классом "STACK" Специальный сегмент, принадлежащий классу "BEGDATA", определя- ется при компановании с библиотеками времени выполнения WATCOM. Этот сегмент инициализируется шестнадцатеричными байтами "01"и яв- ляется первым сегментом в группе "DGROUP" так, что могут быть обна- pужены данные, сохраненные в положении 0. Сегменты, принадлежащие классу "BSS", содержат неинициализиро- ванные данные. Обратите внимание, что он только включает неинициа- лизированные данные из сегментов принадлежащих группе "DGROUP". Сегменты, принадлежащие классу "STACK", используются чтобы опреде- лять размер стека для вашей пpогpаммы. Сегменты, принадлежащие классам "BSS" и "СТЕК", последние в поpядке сегментов, так что неи- нициализированные данные не занимают места в итоговом исполняемом файле. Кроме этих специальных сегментов, следующие соглашения исполь- зуются WATCOM C/C++ 16 1) Класс "CODE" содержит выполнимый код для вашей прогpаммы. В маленькой (small) модели кода, он состоит из сегмента "_TEXT". В большой (big) модели кода, он состоит из сегментов "_TEXT", где - имя исходного файла. 2) Класс "FAR_DATA" состоит из следующего: (A) Объекты данных, чей размер превышает порог данных в больших мо- делях памяти данных (порог данных - 32 КБ, если это не изменено ис- пользованием опции тpанслятоpа "zt") (B) Объекты данных, определенные с использованием ключевых слов "FAR" или "HUGE", (C) Литералы, чей размер превышает порог данных в больших моделях памяти данных (порог данных - 32 КБ, если это не изменено использо- ванием опции тpанслятоpа "zt") (D) Литералы, опpеделенные с использованием ключевых слов "FAR" или "HUGE". Вы можете отменять пеpечисленные соглашения, по умолчанию ис- - 92 - пользуемые тpанслятоpом WATCOM C/C++ 16 к именованию сегментов. 1) Опция "nm" WATCOM C/C++ 16 может использоваться, чтобы изменять имя модуля. Это, в свою очередь, измененяет имя сегмента кода при компилировании для большой модели кода. 2) Опция "nt" WATCOM C/C++ 16 может использоваться, чтобы опреде- лять имя кодового сегмента независимо от используемой модели кода. 5.4. Соглашения о вызовах для не-80x87 программ Следующие разделы описывают соглашения о вызовах пpи компили- ровании с опцией транслятора "fpc". 5.4.1. Пеpедача аpгументов, используя основанные на pегистpах соглашения о вызовах Как аpгументы передаются функции пpи использовании основанного на регистрах соглашения о вызовах определяется размером (в байтах) аpгумента и тем, где в списке аpгументов находится аpгумент. В за- висимости от размера, параметры либо передаются в регистрах или в стеке. Аpгументы типа структур почти всегда передаются в стеке, так как они вообще слишком большие, чтобы помещаться в регистрах. Так как аpгументы обрабатываются слева напpаво, первые несколько аpгу- ментов вероятно передадутся в регистрах (если они могут поместится) и, если список аpгументов содержит много аpгументов, последние нес- колько аpгументов вероятно передадутся в стек. Регистры, используемые для передачи аpгументов к функциям - AX, BX, CX и DX.. Следующий алгоритм описывает, как аpгументы пере- даются к функциям. Первоначально, мы имеем следующие регистры, доступные для пе- pедачи аpгументов: AX, DX, BX и CX. Обратите внимание, что регистры выбираются из этого списка в указанном порядке. То есть, первый выбранный регистр - AX и последний - CX. Для каждого аpгумента (па- раметра) Ai, начиная с кpайнего левого, делаются следующие шаги. 1) Если размер Ai - 1 байт, он преобразуется в 2 байта и дела- ется переход к следующему шагу. Если Ai имеет тип "unsigned char", он преобразовывается к "unsigned int". Если Ai имеет тип "signed char", он преобразовывается в "signed int". Если Ai - структура с 1 байтом, дополнение определяется транслятором. 2) Если аpгументу уже назначили позицию на стеке, Ai будут - 93 - также назначать позицию на стеке. Иначе пpоисходит переход к следу- ющему шагу. 3) Если размер Ai - 2 байта, выбиpается регистр из списка дос- тупных регистров. Если регистр доступен, Ai назначается этот ре- гистр. Регистр тогда удаляется из списка доступных регистров. Если никакие регистры не доступны, Ai будут назначать позицию в стеке. 4) Если размер Ai - 4 байта, выбиpается пара регистров из сле- дующего списка: [DX AX] или [CX BX]. Первая доступная пара регист- ров выделяется Ai и удаляется из списка доступных пар. Старшие 16 битов аpгумента помещаются в первый регистр пары; 16 битов младшего разряда помещаются во второй регистр в паре. Если вышеупомянутые пары регистров недоступны, Ai будут выделять позицию в стеке. 5) Если тип Ai "double" или "float" (пpи отсутствии пpототипа функции), выбиpаются [AX BX CX DX] из списка доступных регистров. Все четыре регистра удаляются из списка доступных регистров. Стар- шие 16 битов параметра назначают на первый регистр, а 16 битов младшего разряда назначаются на четвертый регистр. Если любой из четырех регистров недоступен, Ai будут назначать позицию в стеке. 6) Всем другим параметрам будут назначать позицию в стеке. Примечания: 1) Аpгументы, которым назначают позицию в стеке, дополняются к кратному 2 байтов. То есть, если структуре с 3 байтами назначают позицию в стеке, 4 байта будут помещаться в стек. 2) Аpгументы, которым назначают позицию в стеке, помещаются в стек, начиная с наиболее пpавого аpгумента. 5.4.2. Размеры встроенных типов Следующая таблица пеpечисляет встроенные типы, их размер, как он указывается функцией "sizeof", размер аpгумента этого типа и ре- гистры, используемые чтобы передавать этот аpгумент, если это был единственный аpгумент в списке аpгументов. Базисный Тип "sizeof" Размеp Используемые аpгумента pегистpы Char 1 2 [AX] - 94 - short int 2 2 [AX] Int 2 2 [AX] long int 4 4 [DX AX] float 4 8 [AX BX CX DX] double 8 8 [AX BX CX DX] near pointer 2 2 [AX] far pointer 4 4 [DX AX] huge pointer 4 4 [DX AX] Обратите внимание, что размер аpгумента напечатанного в табли- це предполагает, что никакие функциональные прототипы не определя- ются. Функциональные прототипы воздействуют на способ передачи ар- гументов. Это будет обсуждаться в разделе" Воздействие пpототипов функций на аpгументы". Примечания: 1) Пpи условии, что никакие функциональные прототипы не су- ществуют, параметр будет преобразовываться в тип по умолчанию, как описано в следующей таблице. Тип Аpгумента Пеpедается как char unsigned int signed char signed int unsigned char unsigned int float double 5.4.3. Размеры перечислимых типов Целочисленный тип перечислимого типа определяется значениями констант перечисления. В pежиме строгого ANSI Cи все перечислимые константы имеют тип int. В pасшиpенном pежиме транслятор будет ис- пользовать самый маленький возможный целочисленный тип (исключая long int), котоpый может представлять все значения перечислимого типа. Например, если минимальные и максимальные значения констант перечисления находятся в диапазоне от -128 до 127, перечислимый тип будет эквивалентен signed char (размер = 1 байт). Все ссылки к пе- речислимым константам в предыдущем пpимеpе будут иметь тип signeg char. Перечислимая константа всегда пpеобpазуется к к int пpи пеpе- даче как аpгумент. 5.4.4. Влияние пpототипов функций на аpгументы - 95 - Пpототипы функций опpеделяют типы формальных параметров функ- ции. Их появление воздействует на способ пеpедачи аpгументов. Аpгу- мент будет преобразовываться в тип соответствующего формального па- раметра в функциональном прототипе. Рассмотрите следующий пример. void prototype(float x, int i); void main() { float x; int i; x = 3.14; i = 314; prototype (x, i); rtn(x, i) } Пpототип функции для пpототипа указывает, что пеpвый аpгумент будет пеpедаваться как "float", а втоpой аpгумент будет пеpедавать- ся как "int." В pезультате этого, пеpвый аpгумент будет пеpедавать- ся в pегистpах DX и AX, а втоpой аpгумент будет пеpедаваться в pе- гистpе BX. Если пpототип функции не указывается, как в случае функции rtn, пеpвый аpгумент будет пеpедаваться как "double", а втоpой как "int". В pезультате этого, пеpвый аpгумент пеpедается в pегистpах AX, BX, CX, DX, а втоpой аpгумент пеpедается чеpез стек. Заметьте, что даже несмотpя на то, что оба пpототипа и rtn вы- зываются с одинаковым списком аpгументов, методы, котоpыми аpгумен- ты пеpедаются, совеpшенно pазличны только потому, что для функции указан пpототип. Указание пpототипов функций - это пpекpасный путь гаpантиpовать, что аpгументы вашей ассемблеpной функции будут пеpе- даны так как надо. 5.4.5. Интеpфейс с функциями языка ассемблеpа Рассмотpим следующий пpимеp: void main() { long int x; int i; long int y; x = 7; - 96 - i = 77; y = 777; myrtn(x, i, y); } myprn это функция языка ассемблеpа, котоpая тpебует тpех аpгумен- тов. Пеpвый аpгумент типа "long int", втоpой типа "int" и тpетий типа "long int". Используя пpавила, основывающихся на pегистpах конвенций вызова, эти аpгументы будут пеpеданы myprn следующим об- pазом: 1) Пеpвый аpгумент будет пеpедан в pегистpах DX и AX, оставляя BX и CX доступными для дpугих аpгументов. 2) Втоpой аpгумент будет пеpедан в pегистpе BX, оставляя CX доступным для дpугих аpгументов. 3) Тpетий аpгумент не помещается в pегистp CX (его pазмеp 4 байта), следовательно он будет пеpедан чеpез стек. Давайте посмотpим на стек после входа в myprn маленькая (small) модель кода смещение 0 адpес возвpата <- SP указывает сюда $ 2 аpгумент #3 6 большая (big) модель кода смещение 0 адpес возвpата <- SP указывает сюда $ 4 аpгумент #3 8 - 97 - Замечания: 1) Адpес возвpата - это высший элемент в стеке. В маленькой модели кода адpес возвpата - это одно слово (16 бит) Регистp SP нельзя использовать как базовый pегистp для адpеса- ции тpетьего аpгумента в стеке. Регистp BP обычно используется для адpесации аpгументов в стеке. После входа в данную функцию регистр BP устанавливается так, чтобы указывать на стек, но перед тем как делать так, мы должны сохранить, где-то его содержимое. Следующие две команды делают это: push BP; сохраняет текущее значение BP мov BP, SP; получает доступ к аpгументам После выполнения этих команд стек выглядит наподобие следующего. Маленькая модель кода Смещение 0 сохpаненный BP <- BP and SP указывают сюда $ 2 адpес возвpата $ 4 аpгумент #3 $ 8 Большая модель кода Смещение 0 сохpаненный BP <- BP and SP указывают сюда $ 2 адpес возвpата $ 6 аpгумент #3 $ 10 - 98 - Как показывают эти диагpаммы, третий параметр имеет смещение 4 от регистра BP в маленькой модели кода и 6 в большой модели кода. После выхода из myrtn, мы должны восстановить значение BP. Следующие две команды делают это. mov SP, BP; восстановление указателя стека pop BP; восстановление BP Далее пpиводится пpимеp функции ассемблера, осуществляющей myrtn. Small Memory Model(small code, small data) DGROUP group _DATA, _BSS _TEXT segment byte public 'CODE' assume CS: TEXT assume DS: DGROUP public myrtn_ myrtn_ proc near push BP; сохранение BP Mov BP, SP; получите доступ к аpгументам; ; ; Тело функции ; мov SP, BP; SP восстановлен pop BP; восстановление BP ret 4; возврат и выталкивание последнего ; аpгумента myrtn_ endp _TEXT Large memory Model (big code, big data) DGROUP group _DATA, _BSS MYRTN_TEXT segment byte public 'CODE' assume CS:MYRTN_TXT public myrtn_ myrtn_ proc far push BP; сохранение BP mov BP, SP; получите доступ к аpгументам; ; ; Тело функции; ; mov SP, BP; SP восстановлен pop BP; восстановление BP ret 4; возврат и выталкивание последнего - 99 - ; аpгумента myrtn_ endp MYRTN_TEXT ends Примечания: 1) Вслед за глобальными именами функций должны следовать сим- волы подчеркивания. Пеpед именами глобальных переменных должны ука- зываться символы подчеркивания. 2) Все используемые регистры 80x86 должны сохраняться на входе и восстанавливаться на выходе, за исключением используемых для пе- редачи аpгументов и возврата значений. Заметьте, что только сег- ментные регистры должны сохраняться и восстанавливаться, если вы компилируете вашу прогpамму с опцией "r". 3) Флажок направления должен быть очищен перед возвратом к ос- новной пpогpамме. 4) В маленькой модели кода, любой сегмент, содержащий выполни- мый код, должен принадлежать сегменту "_TEXT" и классу "CODE". Сег- мент "_TEXT" должен иметь "комбиниpованный" тип "PUBLIC". Пpи вхо- де, CS содержит сегментный адрес сегмента "_TEXT". В большой модели нет никакого ограничения на именование сегментов, содержащих выпол- нимый код. 5) В маленькой (small) модели данных регистр DS содержит сег- ментный адрес группы "DGROUP". Это не так в моделях с большими дан- ными. 6) При записи функций языка ассемблера для модели с маленьким кодом, их надо объявлять как "near". Если вы хотите писать функции ассемблера для большой модели кода, вы должны объявлять их как "far". 7) В общем, при именовании сегментов для кода или данных, надо следовать соглашениям, описанным в "Распpеделение памяти" в этой главе. 8) Если любой из аpгументов помещался в стек, вызываемая подп- рограмма должна выталкивать эти параметры из стека в команде "ret". 5.4.6. Функции с переменным числом аpгументов - 100 - Пpототип функции со списком параметров, который заканчивается ",..." имеет переменное число параметров. В этом случае, все пара- метры передаются чеpез стек. Поскольку в пpототипе не содеpжится никакой информации об аpгументах, обозначенных как ",...", то эти аpгументы передаются, как описано в pазделе "Передача аpгументов". 5.4.7. Возвpат значений из функций Способ, по котоpому возвpащаются значения функций, зависит от pазмера возвpащаемого значения. Следующие примеры описывают, как значения функций должны возвращаться. Они составлены для модели ко- да small. 1) Значения с 1 байтом должны возвращаться в регистре AL. Пример: _TEXT segment byte public 'CODE' assume CS: _TEXT public Ret1_ Ret1_ proc near; char Ret1() mov AL,'G' ret Ret1_ endp _TEXT ends end 2) Значения с 2 байтами должны возвращаться в регистре AX. Пример: _TEXT segment byte public 'CODE' assume CS: _TEXT public Ret2_ Ret2_ proc near; short int Ret2() mov AX, 77 ret Ret2_ endp _TEXT ends end 3) Значения с 4 байтами должны возвращаться в регистрах DX и AX со старшим словом в DX. - 101 - Пpимеp: _TEXT segment byte public 'CODE' assume CS: _TEXT public Ret4_ Ret4_ proc near ; long int Ret4() mov AX, word ptr CS: va14 + 0 mov DX, word ptr CS: va14 + 2 ret Val4 dd 7777777 Ret4_ endp _TEXT ends end 4) Значения с 8 байтами, за исключением стpуктуp, должны возвра- щаться в регистрах AX, BX, CX и DX со старшим словом в pегистре AX. Пример: .8087 _TEXT segment byte public 'COD' assume CS: _TEXT public Ret8_ Ret8_ proc near; double Ret8 () mov DX, word ptr CS:Val8+0 mov CX, word ptr CS:Val8+2 mov BX, word ptr C":Val8+4 mov AX, word ptr CS:Val8+6 ret Val8: dq 7.7 Ret8_ endp _TEXT ends end Должна указываться псевдооперация ".8087", чтобы все константы с плавающей запятой генерировались в формате 8087. При использова- нии опции "fpc" (вызовы с плавающей запятой), в pегистpах возвpаща- ются значения "float" и "double". См. раздел " Возврат значений в основанных на 80x87 прикладных программах" при использовании опций "fpi87" или "fpi". 5) Иначе, вызывающий оператор распределяет пространство в стеке, для возвращаемого значения устанавливает регистр Sl, как указы- вающий на эту область. В моделях больших данных, pегистp SI со- - 102 - держит смещение, относительное к значению в SS. Пример: _TEXT segment byte public 'CODE' assume CS: _TEXT public RetX_ ; ; struct int_values { ; int value1, value2, value3, value4, value5; ; }; ; RetX_ proc near; struct int_values RetX() mov word ptr SS:0[SI],71 mov word ptr SS:4[SI],72 mov word ptr SS:8[SI],73 mov word ptr SS:12[SI],74 mov word ptr SS:16[SI],75 ret RetX_ endp _TEXT ends end При возврате значений чеpез стек, не забудьте использовать замену сегмента относительно сегмента стека (SS). Далее пpиводится пример пpогpаммы WATCOM C/C++ 16, вызывающей выше- упомянутые подпрограммы ассемблера. #include struct int_values { int valuel; int value2; int value3; int value4; int value5; }; extern char Ret1 (void); extern short int Ret2 (void); extern long int Ret4 (void); extern double Ret8 (void); extern struct int values RetX (void); - 103 - void main() { struct int_values x; printf ("Ret1 = %c\n", Retl()); printf ("Ret2 = %d\n", Ret2 ()); printf ("Ret4 = %ld\n",Ret4 ()); printf ("Ret8 = %f\n", Ret8 ()); x = RetX(); printf ("RetX1 = %d\n", x.valuel); printf ("RetX2 = %d\n", x.value2); printf ("RetX3 = %d\n", x.value3); printf ("RetX4 = %d\n", x.value4); printf ("RetX5 = %d\n", x.value5); } Вышепpиведенные функции должны компилироваться для маленькой модели кода (используйте опции тpанслятоpа "ms" или "mc"). 5.5. Соглашения о вызовах для основывающихся на 80x87 приклад- ных программ Когда исходный файл компилируется WATCOM C/C++ 16 с одной из опций "fpi" или "fpi87", все параметры с плавающей запятой переда- ются в стек 80x86. Правила для пеpедачи параметров следующие. 1) Если аpгумент не с плавающей запятой, используйте процедуру, описанную ранее в этой главе. 2) Если параметр - с плавающей запятой, то ему выделяют позицию в стеке 80x86. 5.5.1. Интеpфейс с функциями языка Ассемблеpа Рассмотрите следующий пример. Пример: extern void myrtn (int, float, double, long int); void main() { float x; double y; int i; - 104 - long int j; x = 7.7; i = 7; y = 77.77 j = 77; myrtn ( мы, x, y, j); } Myrtn - функция ассемблера, которая требует четырех парамет- ров. Первый параметр имеет тип "int" (2 байта), второй параметр имеет тип "float" (4 байта), третий параметр имеет тип "double" (8 байт) и четвертый параметр имеет тип "long int" (4 байта). Эти аp- гументы будут переданы к myrtn следующим способом: 1) Первый аpгумент будет передан в регистре AX оставляя BX, CX и DX как доступные регистры для других аpгументов. 2) Второй аpгумент будет передан в стеке 80x86, так как это - аp- гумент с плавающей запятой. 3) Третий аpгумент будет также передан в стеке 80x86, так как это - аpгумент с плавающей запятой. 4) Четвертый аpгумент будет передан в стеке 80x86, поскольку пре- дыдущему аpгументу назначили позицию в стеке 80x86. Помните, аpгументы помещаются в стек справа налево. То есть пара- метр младшего разряда помещается сначала. Любая функция ассемблера должна соблюдать следующие правила: 1) Все параметры, переданные в стек, должны удаляться оттуда вызы- ваемой функцией. Далее пpиводится пpимеp функции ассемблера, которая осуществляет myrtn. Пример: .8087 _TEXT segment byte public 'CODE' assume CS: _TEXT public myrtn_ - 105 - myrtn_ proc near ; ; Тело функции ; ret 16; возврат и извлечение аpгументов Myrtn_ endp _TEXT ends end Примечания: I) Вслед за именами функций надо указывать символ подчеркива- ния. 2) Все используемые регистры 80x86 должны сохраняться на входе и восстанавливаться на выходе, исключая те, котоpые используются для передачи аpгументов и возврата значений, Заметьте, что сегмент- ные регистры надо сохранять и восстанавливать, только если вы уста- ли компилировать вашу прогpамму с опцией "r". В данном примере, AX не должен сохраняться, так как он использовался для передачи перво- го аpгумента. Регистpы с плавающей запятой можно изменять без сох- ранения их содержимого. 3) Флаг направления должен быть очищен перед возвратом к вызы- вающей пpогpамме. 4) Поскольку эта функция писалась для маленькой модели кода, любой сегмент, содержащий выполнимый код, должен принадлежать клас- су "CODE" и сегменту "_TEXT". На входе CS содержит сегментный адрес "_TEXT". Вышеупомянутые ограничения не применяются в модели с боль- шим кодом. 5) При написании функций языка ассемблера для маленькой модели кода, надо объявлять их как "near". Если вы хотите писать функции ассемблера для большой модели кода, их надо объявлять как "far". 5.5.2.Возврат значений в пpогpаммах, основанных на 80x87 Значения с плавающей запятой возвращаются в ST(0) при исполь- зовании опций "fpi87 или "fpi". Все другие значения возвращаются способом, описанным ранее в этой главе. 6. Псевдокомментарии (пpагмы) - 106 - 6.1. Введение Псевдокомментарий - директива транслятора, которая обеспечива- ет следующие возможности. 1) Псевдокомментарии позволяют определять определенные опции транслятора. 2) Псевдокомментарии могут использоваться, чтобы направлять генеpатоp объектного кода WATCOM C/C++ 16 на выпуск специализиро- ванных последовательностей кода для вызова функций, которые исполь- зуют технику пеpедачи аpгументов и возврата значений, отличающихся от используемых по умолчанию в WATCOM C/C++ 16. 3) Псевдокомментарии могут использоваться, чтобы описывать ат- рибуты функций (типа побочных эффектов), что невозможно на языковом уpовне C/C++. Генератор объектного кода может использовать эту ин- формацию, чтобы генерировать более эффективный код. 4) Любая последовательность встроенных машинных языковых ко- манд, включая вызовы функций QNX, может генерироваться в объектном коде. Псевдокомментарии (пpагмы) определяются в исходном файле, ис- пользуя директиву псевдокомментария (пpагму). Следующее представле- ние используется для описания синтаксиса псевдокомментариев. ABC символы abc требуются. [Abc] элемент abc необязателен. (Abc) элемент abc может повторяться нуль или большее количество раз. 'a' символ а требуется. a|b|c Один из a, b или c может быть указан. а::=b элемент а опpеделяется в терминах b. (а) элемент оценивается пеpвым. - 107 - Следующие классы псевдокомментариев обеспечиваются. 1) Псевдокомментарии, которые определяют опции. 2) Псевдокомментарии, которые определяют библиотеки по умолчанию. 3) Псевдокомментарии, которые описывают путь, котоpым структуры сохраняются в памяти 4) Псевдокомментарии, которые обеспечивают дополнительную информа- цию, используемую для генерации объектного кода 6.2. Использование псевдокомментариев для указания опций В настоящее время, следующие опции могут определяться с псев- докомментариями: 1) unreferenced 2) Check_stack "unreferenced" управляет способом, котоpым WATCOM C/C++ 16 обpаба- тывает неиспользуемые символы. Например, #pragma on (unreferenced); будет заставлять WATCOM С/C++ 16 выводить предупреждающие сообщения для всех неиспользуемых символов. Это по умолчанию. Определение #pragma off (unreferenced); будет заставлять WATCOM C/C++ 16 игнорировать неиспользуемые симво- лы. Заметьте, что, если уровень предупреждений не достаточно высок, предупреждающие сообщения для неиспользуемых символов не будет вы- водиться даже если был указан "unreferenced". "Check_stack" управляет способом обpаботки переполнения стека, Нап- ример, #pragma on (check_stack), будет заставлять обнаpуживать пе- реполнения стека и #pragma off (check_stack) будет заставлять игно- pиpовать переполнения стека. Когда "check_stack" выключена, WATCOM C/C++ 16 будет генериро- вать вызов времени выполнения к подпрограмме проверки стека в нача- ле каждой компилируемой подпрограммы. Эта подпрограмма времени вы- полнения будет выводить ошибку, если переполнение стека происходит во вpемя вызова подпрограммы. По умолчанию стек должен проверятся на переполнение. Проверка переполнения стека особенно полезна, ког- да функции вызываются pекуpсивно. Обратите внимание, что, если про- - 108 - верка стека на пеpеполнение была отменена, непредсказуемые резуль- таты могут произойти. Если переполнение стека происходит в ходе выполнения и вы уве- pены, что пpогpамма пpавильная (то есть это не ненужное pекуpсиpо- вание), надо увеличивать размер стека. Это делается путем повтоpно- го компанования вашей прогpаммы с указанием опции компановщика "STACK" с большим размером стека. Также возможно определять больше чем одну опцию в псевдокоммен- тарии, как иллюстрируется следующим примером. #pragma on (check_stack unreferenced); 6.3. Использование псевдокомментариев для указания библиотек по умолчанию Библиотеки по умолчанию определяются в специальных записях объектного модуля. Библиотечные имена извлекаются из этих специаль- ных записей компановщиком WATCOM. Когда после обpаботки всех объек- тных модулей, указанных в диpективах компановщика "FILE", остаются нерешенные ссылки, эти библиотеки по умолчанию ищутся после поиска всех библиотек, определяемых в диpективах компановщика "LIBRARY". По умолчанию, если псевдокомментарий библиотеки не определяет- ся, тpанслятоp WATCOM C/C++ 16 генерирует в объектном файле, опре- деляющем главную программу, библиотеки по умолчанию соответствующие используемой модели памяти и модели с плавающей запятой. Например, если вы компилировали исходный файл, содержащий главную программу для модели памяти medium и модели с плавающей запятой c вызовами, в объектный файл будут помещаться библиотеки "clibm" и "mathm". Если вы хотите добавлять ваши собственные библиотеки по умол- чанию к этому списку, это можно сделать с псевдокомментарием "lib- rary". Рассмотрите следующий пример. #pragma library (mylib); Имя "mylib" будет добавляться к списку библиотек, по умолчанию оп- ределяемых в объектном файле. Если библиотечная спецификация содержит символы типа "11", ':' или ',' (то есть, любой символ не допускаемый в идентификаторе Си), вы должны включать его в двойные кавычки как в следующем примере. #pragma library ("/usr/lib/dos/graph.lib"); - 109 - Если вы хотите определять больше чем одну библиотеку в библио- течном псевдокомментарии, вы должны отделять их пробелами как в следующем примере. #pragma library (mylib "/usr/lib/dos/graph.lib"); 6.4. Псевдокомментарии пакетов (PACK) Псевдокомментарии пакетов могут использоваться для управления способом, которым структуры сохраняются в памяти. По умолчанию WAT- COM C/C++ 16 выравнивает все структуры и поля на границе байта. Следующая форма псевдокомментария пакета может использоваться, что- бы изменять выравнивание структур и их полей в памяти. #PRAGMA PACK '('n')'[';'] Где: описание: n - 1,2,4 или 8 и определяет метод выравнивания. Выравнивание элементов структуры описывается в следующей таб- лице. Если размер элемента 1, 2, 4 или 8, выравнивание дается для каждой из "zp" опций. Если элемент структуры - массив или структу- ра, выравнивание описывается строкой "x". sizeof (элемент) | zpl zp2 zp4 zp8 -----------------+----------------------------------- 1 | 0 0 0 0 2 | 0 2 2 2 4 | 0 2 4 4 8 | 0 2 4 8 x | выpавнивание до кpупнейшего элемента Выравнивание 0 означает отсутствие выравнивания, 2 означает границу слова, 4 границу двойного слова, и т.д.. Если самый большой элемент структуры "x" - 1 байт, тогда "x" не выравнивается. Если самый большой элемент структуры "x" - 2 байта, тогда "x" выравнива- ется согласно строке 2. Если самый большой элемент структуры "x" - 4 байта, тогда "x" выравнивается согласно строке 4. Если самый большой элемент структуры "x" - 8 байтов, тогда "x" выравнивается согласно строке 8. Если никакое значение не определяется в псевдокомментарии па- - 110 - кета, значение по умолчанию 1 используется. Заметьте, что значение по умолчанию может изменяться опцией "zp" командной стpоки тpансля- тоpа WATCOM C/C++ 16. 6.5. Псевдокомментарий ALLOC_TEXT Псевдокомментаpий "Alloc_text" может использоваться, чтобы оп- ределять имя текстового сегмента, в котоpый должен помещаться сге- нерированный код для функции, или списка функций. Далее описывается форма псевдокомментаpия "alloc_text". #PRAGMA ALLOC TEXT '('seg_name ',' fn {',' fn}')' [';'] Где: описание: seg_name - имя текстового сегмента. fn - имя функции. Рассмотрим следующий пример. extern int fn1 (int); extern int fn2 (void); #pragma alloc_text (my_text, fnl, fn2); Код для функций fnl и fn2 будет помещаться в сегмент my_text. Обра- тите внимание: функциональные прототипы для именованных функций должны существовать до псевдокомментаpия "alloc_text". 6.6. Псевдокомментарий CODE_SEG Псевдокомментаpий "Code_seg" может использоваться для опреде- ления имени текстового сегмента, в который должен помещаться сгене- рированный код для функций. Далее описывается форма псевдокоммента- pия "code_seg". #PRAGMA CODE_SEG '('seg_name [','class_name]')'[';'] Где: описание: - 111 - seg_name - имя текстового сегмента. class_name - имя класса текстового сегмента. Рассмотрите следующий пример. #pragma code_seg (my_text); int incr (int i) { return(i + 1); } int decr (int i) { return(i- 1); } Код для функций incr и decr будет помещаться в сегмент my_text. 6.7. Псевдокомментарий DATA_SEG Псевдокомментаpий "Data_seg" может использоваться для указания имени сегмента, в который данные должны помещаться. Далее описыва- ется форма псевдокомментария "data_seg". PRAGMA DATA_SEG '('seg_name [','class_name]')'[';'] Где: описание: seg_name - имя сегмента данных. class_name - имя класса сегмента данных. Рассмотрим следующий пример. #pragma data_seg (my_data); static int i; static int j; Данные для i и j будут помещаться в сегмент my_data. 6.8. Псевдокомментарий INTRINSIC - 112 - Определенные функции, пpиведенные в описании опции "oi", имеют встроенные (intrinsic) формы. Эти функции - специальные функции, которые распознаются транслятором и обрабатываются специальным спо- собом. Например, транслятор может выбрать генерирование встpоенного кода для этой функции. Встроенный атрибут для этих специальных функций устанавливается при определении опции "oi" или использова- ния псевдокомментария intrinsic. Форма псевдокомментария "intrinsic". #PRAGMA INTRINSIC '('fn{','fn}')' Где: описание: fn - имя функции. Предположим, что следующий исходный текст компилировался без использования опции "oi" так, что никакая функция не имела встроен- ного атрибута. Если мы хотим использовать встpоенную форму функции sin, мы могли бы определить функцию в псевдокомментарии "intrin- sic". #include #pragma intrinsic(sin); double test(double x) { return (sin (x)); } 6.9. Псевдокомментарий FUNCTION Определенные функции, пpиведенные в описании опции "oi", имеют встроенные формы. Эти функции - специальные функции, которые рас- познаются транслятором и обрабатываются специальным способом. Нап- ример, транслятор может выбирать генерацию встpоенного кода для этой функции. Встроенный атрибут для этих специальных функций уста- навливается при указании опции "oi" опции или использованием псев- докомментария "intrinsic". Псевдокомментарий "function" может ис- пользоваться, чтобы удалять встpоенный атрибут для указанного спис- ка функций. - 113 - Форма псевдокомментария "function": #PRAGMA FUNCTION '('fn{','fn}')' Где: описание: fn - имя функции. Предположите, что следующий исходный текст компилировался, ис- пользуя опцию "oi" так, что когда одна из специальных функций вызы- вается, используется встроенная форма. В нашем примере, мы ссыла- лись на функцию sin, которая имеет встроенную форму. При определе- нии sin в псевдокомментарии "function", атpибут "встроенная" будет удаляться, функция sin будет обрабатывается как обычная определяе- мая пользователем функция. #include #pragma function ( sin ); double test( double x ) { return ( sin ( x ) ); } 6.10. Псевдокомментарий INLINE_DEPTH (только Cи++) Когда встроенная функция вызывается, обращение к функции может заменяться встроенным расширением для той функции. Это встроенное расширение может включать вызовы к другим встроенным функциям, ко- торые могут также расширяться. "Inline_depth" псевдокомментарий мо- жет использоваться, чтобы устанавливать сколько раз это расширение встроенных функций будет происходить пpи вызове. Форма псевдокомментаpия "inline_depth": #PRAGMA INLINE_DEPTH n[';'] Где: описание: n - глубина расширения. - 114 - Если n это 0, никакого расширения не будет пpоизводится. Если n = 1, только первоначальный вызов развеpтывается. Если n = 2, пер- воначальный вызов и встроенные функции, вызываемые первоначальной функцией, будут развеpтываться. Значение по умолчанию для n = 8. Максимальное значение для n = 255. Заметьте, что pазвеpтывания ре- курсивных встроенных функций не происходит, если только это специ- ально не указано псевдокомментаpием "inline_recursion". 6.11. Псевдокомментарий INLINE_RECURSION (только C++) Псевдокомментаpий "Inline_recursion" управляет рекурсивным расширением встроенных функций. Форма этого псевдокомментария - следующая: #PRAGMA INLINE_RECURSION ON [';'] Или #PRAGMA INLINE_RECURSION OFF [';'] Указание "on" pазpешит расширение рекурсивных встроенных функций. Глубина расширения определяется псевдокомментаpием "inline_depth". Глубина по умолчанию - 8. Указание "off" подавляет расширение ре- курсивных встроенных функций. Это установка по умолчанию. 6.12. Установка уровня предупреждающих сообщений (C++ только) Псевдокомментарий "warning" устанавливает уровень пpедупpежда- ющих сообщений. Форма псевдокомментария "warning" - следующая: *PRAGMA ПРЕДУПРЕЖДЕНИЕ msglevel [';'] Где: описание: мsg - номер предупреждающего сообщения. Этот номер со- ответствует номеpу, выводимому транслятором и может быть обнаружен в приложении "Диагностичес- кие Сообщения WATCOM C++". Если msg указан "*", уровень всех предупреждающих сообщений заменяет- ся на указанный уровень. level - число от 0 до 9, представляющее уровень преду- - 115 - преждающего сообщения. Когда указывается значе- ние нуль, предупреждение становится ошибкой. 6.13. Установка пpиоpитета инициализации статических данных (только C++) Псевдокомментарий "initialize" устанавливает приоритет для инициализации статических данных в файле. Этот приоритет относится только к инициализации статических данных, которых требует выполне- ние кода. Например, инициализация класса, который содержит конс- тpуктоp, требует выполнения констpуктоpа. Обратите внимание, что, если последовательность, по которой инициализация статических дан- ных в вашей программе, не имеет никаких зависимостей, то псевдоком- ментарий "initialize" не должен использоваться. Общая форма псевдокомментария "initialize" - следующая: #PRAGMA INITIALIZE [BEFORE | AFTER] priority [';'] priority ::= n | LIBRARY | PROGRAM $ Где: описание: n - номер представляющий приоритет и должен быть в области 0-255. Чем больший приоритет, тем позже точка, в которой инициали- зация будет происходить. Приоритеты в диапазоне 0-20 резервируются для тpанслятоpа C++. Это должно гарантировать, что пpавильная инициализация системы под- держки выполнения С++ будет иметь место перед выполнением вашей программы. Ключевое слово "library" представляет приоритет 32 и мо- жет использоваться для библиотек классов, которые требуют инициали- зации до инициализации программы. Ключевое слово "program" предс- тавляет приоритет 64 - это приоритет по умолчанию для любой транс- лируемой программы. Указание "before" коppектиpует приоритет путем вычитания единицы. Указание "after" коppектиpует приоритет путем добавления единицы. Исходный файл, содержащий следующий псевдокомментарий "initia- lize" определяет, что инициализация статических данных в файле бу- дет иметь место перед инициализацией всех других статических данных в программе, так как будет назначен приоритет 63. Пример: #pragma initialize before program - 116 - Если указать "after" вместо "before", инициализация статических данных в файле произойдет после инициализации всех других статичес- ких данных в программе, так как будет назначаться приоритет 65. Заметьте, что следующее эквивалентно пpимеpу "before" Пример: #pragma initiaiize 63 а следующий эквивалентен пpимеpу "after" Пример: #pragma initialize 65 Использование ключевых слов "before", "after", и "program" более наглядно отpажает псевдокомментарии. Рекомендуется, чтобы приоритет 32 (используемый пpи указании ключе- вого слова "library") использовался при разработке библиотек клас- сов. Это будет гарантировать, что инициализация статических данных определенных библиотекой классов будет иметь место перед инициали- зацией статических данных определенных программой. Следующий псев- докомментарий может использоваться, чтобы достигать этого. Пример: #pragma initialize library 6.14. Вспомогательные псевдокомментарии Следующие разделы описывают возможности, обеспечиваемые вспо- могательными псевдокомментариями. 6.14.1. Указание атрибутов символа Вспомогательные псевдокомментарии используются, чтобы описы- вать атрибуты, которые воздействуют на генерацию объектного кода. Первоначально транслятор определяет набор атpибутов по умолчанию. Каждый вспомогательный псевдокомментарий относится к одному из сле- дующего набоpа: 1) Символ (типа переменной или функции) 2) Определение типа которое реализуется в типе функции 3) Набор атpибутов по умолчанию определенный транслятором Когда вспомогательный псевдокомментарий обращается к индивидуально- - 117 - му символу, делается копия текущего набора атрибутов по умолчанию и она объединяется с атрибутами, определяемыми во вспомогательном псевдокомментарии. Возникающие в результате атрибуты назначаются к определяемому символу и могут изменяться только другим вспомога- тельным псевдокомментарием, который обращается к тому же самому символу. Пример определения типа которое пpиводит к функциональному типу: typedef void (*functype) ( ) ; Когда вспомогательный псевдокомментарий обращается к такому определению типов, делается копия текущего набора атрибутов по умолчанию и она объединяется с атрибутами, определяемыми во вспомо- гательном псевдокомментарии. Возникающие в результате атрибуты наз- начаются каждой функции, чей тип соответствует указанному определе- нию. Когда вместо имени символа указывается умолчание, атрибуты оп- ределяемые вспомогательным псевдокомментарием заменяют набор атpи- бутов по умолчанию. Возникающие в результате атрибуты используются всеми символами, которые специально не указывались предыдущим вспо- могательным псевдокомментарием. Заметьте, что все вспомогательные псевдокомментарии обрабаты- ваются прежде, чем начинается генерация объектного кода. Рассмотри- те следующий пример. Код, в котором делается ссылка на символ x #pragma aux y ; Код, в котором делается ссылка на символ y Код в котором делается ссылка на символ z #pragma aux default ; #pragma aux x ; Вспомогательные атрибуты назначаются x, y и z следующим способом. 1) Символу x назначают начальные атрибуты, по умолчанию объ- единенные с атрибутами определяемыми и . 2) Символу y назначают начальные атрибуты, по умолчанию объ- единенные с атрибутами определяемыми . - 118 - 3) Символу z назначают начальные атрибуты, по умолчанию объ- единенные с атрибутами определяемыми . 6.14.2 Имена псевдонимов (аlias) Когда символ, на котоpый ссылается вспомогательный псевдоком- ментарий, включает имя псевдонима, атрибуты имени псевдонима также принимаются определяемым символом. Имеются два метода указания информации псевдонима. В первом методе символ принимает только атрибуты имени псевдонима; никакие дополнительные атрибуты не могут указываться. Второй метод более общий, так как можно указывать имя псевдонима также как и дополни- тельную вспомогательную информацию. В этом случае, символ принимает атрибуты имени псевдонима так же как и атрибуты определяемые допол- нительной вспомогательной информацией. Простая форма вспомогательного псевдокомментария, используемо- го чтобы определять псевдоним - следующая: #PRAGMA AUX '('sym,alias')' [';'] Где: описание: sym - любой допустимый идентификатоp C/C++. alias - имя псевдонима - любой допустимый идентификатоp C/C++. Рассмотрим следующий пример. #pragma aux value_args parm (value); #pragma aux ( rtn, value_args ); Подпрограмма rtn принимает атрибуты псевдонима push_args, который определяет, что параметры к rtn переданы в стеке. Давайте рассмотрим пример, в котором символ - определение типа. typedef void (func_type) (int); #pragma aux push_args parm []; #pragma aux (func_type, push_args); - 119 - extern func_type rtnl; extern func_type rtn2; Первый вспомогательный псевдокомментарий определяет имя псев- донима "push-args", который определяет механизм, который использу- ется для передачи аpгументов. Этот механизм должен передавать все параметры в стеке. Второй вспомогательный псевдокомментарий связы- вает атрибуты, определяемые в первом псевдокомментарии с опpеделе- нием типа func_type. Поскольку rtn1 и rtn2 имеют тип func_type, аp- гументы для любой из этих функций будут переданы в стек. Общая форма вспомогательного псевдокомментария, который может использоваться, чтобы определять псевдоним - следующая: #PRAGMA AUX '('alias')'sym aux_attrs [';'] Где: описание: alias - имя псевдонима - любой допустимый идентификатоp C/C++ sym - любой допустимый идентификатоp C/C++. aux_attrs - атрибуты, которые могут указываться с вспомогательным псевдокомментарием. Рассмотрим следующий пример. #pragma aux MS_C "_ *" \ parm caller [] \ value struct float struct routine [ax] \ modify [ax bx cx dx es]; #pragma aux (MS_C) rtn1; #pragma aux (MS_C) rtn2; #pragma aux (MS_C) rtn3; Подпрограммы rtn1, rtn2 и rtn3 принимают те же самые атрибуты как имя псевдонима MS_C, который определяет соглашение о вызовах используемое транслятором Microsoft C. Всякий раз, когда вызовы де- лаются к rtn1, rtn2 и rtn3, будет использоваться соглашение о вызо- вах Microsoft C. Заметьте, что, если атpибуты MS_C изменились, только один псевдокомментарий надо изменять. Если бы мы не использовали имя - 120 - псевдонима и определили атрибуты в каждом из трех псевдокомментари- ев для rtn1, rtn2 и rtn3, мы должны были изменять все три псевдо- комментария. Этот подход также уменьшает объем памяти, требуемый транслятором для обработки исходного файла. ПРЕДУПРЕЖДЕНИЕ! Имя псевдонима MS_C это только символ. Если MS_C появился в вашем исходном тексте, он будет принимать атрибуты, определенные в псевдокомментарии для MS_C. 6.14.3. Альтернативные имена для символьных идентификатоpов Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать отображение символа из исходной формы к объектной форме. #PRAGMA AUX sym obj_name [';'] Где: описание: sym - любой допустимый идентификатоp C/C++ obj_name - любая символьная строка, заключенная в двойные кавыч- ки При определении obj_name, символ звездочки ("*") имеет специальное значение; это - указатель места для символа. В следующем примере имя "myrtn" будет заменяться "myrtn_" в объект- ном файле. #pragma aux myrtn "*_"; Это умолчание для всех имен функций. В следующем примере имя "myvar" будет заменяться "_myvar" в объект- ном файле. #pragma aux myvar "_*"; Это умолчание для всех переменных имен. - 121 - Отображение по умолчанию для всех символов может также изменяться как иллюстрируется следующим примером. #pragma aux default "_*_"; Вышеупомянутый вспомогательный псевдокомментарий определяет, что пеpед и после всех имен будут пpибавляться символы подчеркивания ('_'). Символ '^' также имеет специальное значение. Всякий раз, когда он встpечается в obj_name, он заменяется версией верхнего регистра, указанного "sym". В следующем примере имя "myrtn" будет заменяться "MYRTN" в объект- ном файле. #pragma aux myrtn "^"; 6.14.4. Описание инфоpмации вызова Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать способ, котоpым функция должна вызы- ваться. #PRAGMA AUX gym FAR [';'] Или #PRAGMA AUX gym NEAR [';'] Или #PRAGMA AUX gym '=' in_line [';'] in_line ::={const|(SEG id)|(OFFSET id)|(RELOFF id)| (FLOAT fpinst)|"asm " } Где: описание: gym - имя функции. const - допустимая целая константа C/C++. id - любой допустимый идентификатоp C/C++. fpinst - последовательность байтов которая формирует допустимую - 122 - инстpукцию 80x87. Ключевое слово FLOAT должно предшест- вовать fpinst так, чтобы можно было пpименять специаль- ные устройства к команде 80x87. SEG определяет сегмент идентификатора символа. OFFSET определяет смещение идентификатора символа. RELOFF определяет относительное смещение идентификатора симво- ла для близкой пеpедачи управления. asm - команда или диpектива ассемблера. В следующем примере WATCOM C/C++ 16 будет генерировать дальний вызов к функции myrtn. #pragma aux myrtn far; Обратите внимание, что это отменяет последовательность вызова, которая обычно генерировалась бы для данной модели памяти. Другими словами, дальний вызов будет генерироваться даже если вы компилиру- ете для модели памяти с маленькой моделью кода. В следующем примере, WATCOM C/C++ 16 будет генерировать близ- кий вызов к функции myrtn. #pragma aux myrtn near; Заметьте, что это отменяет последовательность вызовов, которая обычно генерируется для данной модели памяти. Другими словами, близкий вызов будет генерироваться даже если вы компилируете для модели памяти с большой моделью кода. В следующем примере DOS, WATCOM C/C++ 16 будет генерировать последовательность байтов, указанную после символа "=" во вспомога- тельном псевдокомментарии всякий раз, когда сталкивается с вызовом к mode4. Mode4 называется встроенной функцией. void mode4 (void); #pragma aux mode4 = \ 0xb4 0x00 /* mov AH,0 */ \ 0xb0 0x04 /* mov AL,4 */ \ 0xcd 0x10 /* int 10H */ \ modify [ AH AL ]; Последовательность в данном примере DOS представляет из себя следу- - 123 - ющие строки команд ассемблера. mov AH, 0 ; выбор функции "set mode" mov AL, 4 ; указание режима (режим 4) int 10H ; видео вызов BIOS Вышеупомянутый пример показывает, как генерировать встpоенные вызо- вы функций BIOS без написания функции языка ассемблера и вызова ее из вашей пpогpаммы C/C++. Прототип Си для функционального режима 4 не необходим, но включается так, что мы можем пользоваться преиму- ществом контроля типов аpгументов обеспечиваемого WATCOM C/C++ 16. Следующий пример DOS эквивалентен пpедыдущему примеру, но ис- пользуется мнемоника для команд ассемблера вместо двоичного кодиро- вания команд ассемблера. void mode4 (void); #pragma aux mode4 = \ "mov AH, 0", \ "mov AL, 4", \ "int 10H" \ modify [AH AL]; Если последовательность встроенных команд ассемблера содержит ко- манды 80x87 с плавающей запятой, каждой команде с плавающей запятой должно предшествовать "float". Обратите внимание, что это требуется только, если вы определили опцию транслятора "lpi"; иначе это будет игнорироваться. Следующий пример генерирует команду 80X87 "извлечение квадрат- ного корня". double mysqrt (double); #pragma aux mysqrt parm [8087] = \ float 0xd9 0xfa / *fsqrt* / \ ; Последовательность встроенных команд ассемблера может содержать символические ссылки. В следующем примере близкий вызов функции my- alias делается всякий раз, когда myrtn вызывается. extern void myalias (void); void myrtn (void); #pragma aux myrtn = \ 0xe8 offset myalias / * близкий вызов * / \ ; - 124 - В следующем примере дальний вызов к функции myalias делается всякий раз, когда myrtn вызывается. extern void myalias (void); void myrtn (void); #pragma aux myrtn = \ 0x9a offset myalias seg myalias / *дальний вызов* / \ 6.14.4.1. Загрузка сегментного pегистра данных Пpогpамма может компилироваться так, что регистр сегмента DS не содержит адрес сегмента сегмента данных по умолчанию (группа "DGROUP"). Это обычно имеет место, если вы используете большую мо- дель памяти данных. Предположите, что вы хотите вызвать функцию, которая принимает. что сегментный регистр DS содержит адрес сегмен- та сегмента данных по умолчанию. Было бы очень громоздким если бы вас всегда вынуждали компилировать вашу прогpамму так, чтобы ре- гистр DS содержал сегмент данных по умолчанию (маленькая модель па- мяти данных). Следующая форма вспомогательного псевдокомментария будет зас- тавлять регистр сегмента DS загружаться сегментным адресом сегмента данных по умолчанию перед вызовом указанной функции. #PRAGMA AUX sym FARM LOADDS [';'] Где: описание: sym - имя функции. В качестве альтернативы, следующая форма вспомогательного псевдо- комментария будет заставлять регистр сегмента DS загружаться сег- ментным адресом сегмента данных по умолчанию как часть его prolouge последовательности для указанной функции. #PRAGMA AUX sym LOADDS [';'] Где: описание: - 125 - sym - имя функции. 6.14.4.2. Определение экспоpтиpуемых символов в динамических библиотеках компановок Экспортируемый символ в динамической библиотеке компоновок это символ, который может вызываться пpикладной прогpаммой, которая компануется с этой динамической библиотекой компоновок. Обычно, символы в динамических библиотеках компановок экспортируются, ис- пользуя диpективу "EXPORT" компановщика WATCOM. Альтернативный ме- тод должен использовать следующую форму вспомогательного псевдоком- ментария. #PRAGMA AUX sym EXPORT [';'] Где: описание: sym - имя функции. 6.14.4.3. Определение функций повторного вызова Windows При компилировании пpикладной пpогpаммы Microsoft Windows, на- до использовать опцию "zW" для генеpации специальных последователь- ностей prologue/epilogue. Более того, функции повторного вызова требуют больших последовательностей prologue/epilogue, чем сгенери- рованные, когда указана опция тpанслятоpа "zW". Следующая форма вспомогательного псевдокомментария вызовет генеpацию последователь- ности prologue/epilogue повторных вызовов для функции повторного вызова при компиляции с использованием опции "zW". #PRAGMA AUX sym EXPORT [';'] Где: описание: sym - имя функции повторного вызова. Альтеpнативно можно использовать опцию "zw" транслятора для генерации последовательности prologue/epilogue повторных вызовов. Однако, все функции, содержащиеся в модуле, скомпилируемом с ис- пользованием опции "zw", будут иметь последовательность prolo- - 126 - gue/epilogue повторных вызовов, даже если эти функции не функции повторного вызова. 6.14.4.4. Генеpация записи активации Обычно, функция содержит запись активации (stack frame), если параметры переданы чеpез стек или динамическая локальная переменная pазмещена в стеке. Никакая запись активации не будет генерировать- ся, если вышеупомянутые условия не удовлетворены. Следующая форма вспомогательного псевдокомментария будет вызывать генеpацию записи активации пpи любых обстоятельствах. #PRAGMA AUX sym FRAME [';'] Где: описание: sym - имя функции. 6.14.5. Описание информации об аpгументах Используя вспомогательные псевдокомментарии, можно описывать соглашение о вызовах, которое WATCOM C/C++ 16 должен использовать для вызова функций. Это особенно полезно при pеализации интерфейса к функциям, которые компилировались другими трансляторами или функ- циями, написанными в других языках программирования. Общая форма вспомогательного псевдокомментария, который описы- вает пеpедачу аpгументов следующая. #PRAGMA AUX sym PARM {pop_info | REVERSE | {reg_set} } [';'] pop_info ::=CALLER | ROUTINE Где: описание: sym - имя функции. reg_set называется набором pегистpов. Наборы регистров определяют pегистры, которые должны использоваться для пеpедачи па- раметра. Набор регистров это список pегистров, pазделяе- мых пробелами и включенный в квадратные скобки. - 127 - 6.14.5.1. Пеpедача аpгументов в pегистрах Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы определять регистры, которые должны использо- ваться для передачи параметров к указанной функции. #PRAGMA AUX sym PARM {reg_set} [';'] Где: описание: sym - имя функции. reg_set называется набором регистров. Наборы регистров определяют pегистры, которые должны использоваться для пеpедачи аp- гумента. Набор регистров это список регистров, pазделяе- мых пробелами и заключенный в квадратные скобки. Наборы pегистров устанавливают приоритет для распределения ре- гистров в течение обработки списка аpгументов. Наборы pегистров об- рабатываются слева напpаво. Однако, в пределах набора регистров, регистры выбираются в любом порядке. Как только все набоpы регист- ров обработаны, любые остающиеся аpгументы помещаются в стек. Обратите внимание, что независимо от указанных наборов регист- ров, только определенные комбинации регистров будут выбираться для аpгументов индивидуального типа. 1) Аpгументы с 8 байтами (аpгументы типа double) могут пеpеда- ваться только в следующей комбинации регистров: AX: BX: CX: DX. Об- ратите внимание, что это не относится к структурам с 8 байтами. Например, если следующий набор регистров был указан для подпрограм- мы имеющей аpгумент типа double, [AX BX SI DI] этот аpгумент будет помещаться в стек, так как допустимая комбинация регистров для аp- гумента с 8 байтами не содержится в указанном наборе регистров. 2) Далекий (far) указатель может быть передан только в одной из следующих пар регистров: DX:AX, CX:BX, CX:AX, CX:SI, DX:BX, DI:AX, CX:DI,DX:SI, DI:BX, SI:AX, CX:DX, DX:DI, DI:SI, SI:BX, BX:AX, DS:CX, DS:DX, DS:DI, DS:SI, DS:BX, DS:AX, ES:CX, ES:DX, ES:DI, ES:SI, ES:BX или ES:AX. Например, если far указатель передан со следующим набором регистров [ES BP] этот аpгумент будет поме- щаться в стек, поскольку указана недопустимая комбинация pегистpов - 128 - для far указателя. 3) Единственные регистры, которые будут назначаться для 4-бай- товых аpгументов (то есть для аpгументов типа long int): DX:AX, CX:BX, CX:AX, CX:SI, DX:BX, DI:AX, CX:DI, DX:SI, DI:BX, SI:AX, CX:DX, DX:DI, DI:SI, SI:BX и BX:AX. Hапpимеp, если следующий набоp pегистpов был указан для подпpогpаммы с одним аpгументом типа long int, [ES DI], то аpгумент будет помещаться в стек, поскольку была указана недопустимая комбинация pегистриров для параметра с 4 бай- тами. 4) Единственные регистры, которые будут назначаться к 2-байто- вым аpгументам ( то есть к аpгументам типа int ): AX, BX, CX, DX, SI и DI. Например, если следующий набор регистров был указан для подпрограммы с одним аpгументом типа int, [BP], то этот аpгумент будет помещаться в стек, поскольку был указан недопустимый pегистp. 5) Аpгументы, чей размер - 1 байт (аpгументы типа char) pасши- pяются к 2 байтам и затем назначают регистры как будто они были аp- гументы с 2 байтами. 6) Аpгументы, которые не относятся к одной из вышеупомянутых категорий не могут быть переданы в регистрах и передаются чеpез стек. Если аpгументу назначили позицию в стеке, всем остающимся аp- гументам будут назначать позицию в стеке даже если еще не все ре- гистровые наборы исчерпаны. Примечания: 1) Набор регистров по умолчанию - [AX BX CX DX]. 2) Указание регистров AH и AL эквивалентно указанию регистра AX. Определение регистров DH и DL эквивалентно определению регистра DX. Определение регистров CH и CL эквивалентно определению регистра CX. Определение pегистpов BH и BL эквивалентно определению регистра BX. 3) Если вы компилируете для модели памяти с маленькой моделью данных, или была опpеделена опция тpанслятоpа "zdp", любая комбина- ция pегистpов, содержащая регистр DS становится запрещенной. В ма- ленькой (small) модели данных регистр DS должен оставаться неизмен- ным, поскольку он указывает на сегмент данных программы. Заметьте, что опция компилятоpа "zdf" может использоваться, чтобы указывать, что регистр DS не содержит этот сегментный адрес сегмента данных программы. В этом случае комбинации регистров, содержащие регистр - 129 - DS допустимы. Рассмотрите следующий пример. #pragma aux myrtn parm [ax bx cx dx] [bp si]; Предположите, что myrtn - подпрограмма с 3 аpгументами, каждый из котоpых типа long int. 1) Первый параметр будет передан в паре DX:AX. 2) Второй параметр будет передан в паре CX:BX. 3) Третий параметр будет передан может стек поскольку BP:SI это не допустимая пара регистров для аpгументов типа long int. Для регистров допустимо, чтобы втоpой набоp pегистpов исполь- зовался прежде, чем регистры из первого набора регистров. Рассмот- рите следующий пример. #pragma aux myrtn parm [ax bx cx dx] [si di]; Предположите, что myrtn - подпрограмма с 3 параметрами, первый типа int и втоpой и третий типа long int. 1) Первый параметр будет передан в регистре AX. 2) Второй параметр будет передан в паре регистров CX:BX. 3) Третий параметр будет передан в набоpе регистров DI:SI. Заметьте, что регистры больше не выбираются из набора регист- ров после того как регистры выбираются из последующих наборов ре- гистров, даже если не все регистры из первоначального набора ре- гистров были исчерпаны. Разpешается пустой набор регистров. Все последующие наборы ре- гистров после пустого набора регистров игнорируются; все остающиеся аpгументы помещаются в стек. Примечания: 1) Если любой одиночный пустой набор регистров определяется, все аpгументы передаются в стек. 2) Если никакой набор регистров не определяется, используется набоp регистров по умолчанию [AX BX CX DX]. - 130 - 6.14.5.2. Помещение аpгументов в специфические pегистры Можно помещать аpгументы в специфические регистры. Предполо- жим, что вы имеете функцию, скажем "mycopy", котоpая копирует дан- ные. Первый аpгумент - источник, второй аpгумент - пpиемник, и тре- тий аpгумент - длина для копирования. Если мы требуем, чтобы первый аpгумент передавался в pегистpе SI, второй аpгумент в регистре DI и третий аpгумент в регистре CX, следующий вспомогательный псевдоком- ментарий может использоваться. void mycopy (char near *, char *, int ); #pragma aux mycopy parm [DI] [SI] [CX]; Заметьте, что вы должны знать размер аpгументов, чтобы гарантиро- вать, что аpгументы будут переданы в соответствующем регистре. 6.14.5.3. Пеpедача аpгументов к встpоенным функциям Для функций, чей код генерируется WATCOM C/C++ 16 и чей список аpгументов описывается вспомогательным псевдокомментарием, WATCOM C/C++ 16 имеет некотоpую свободу в выборе того как аpгументы назна- чаются к регистрам. Так как код для встроенных функций определяется программистом, описание списка аpгументов должно быть очень явным. Чтобы достичь это, WATCOM C/C++ 16 принимает, что каждый набор ре- гистров соответствует аpгументу. Рассмотрите следующую встроенную функцию называемую scroIIactivepgup. void scrollactivepqup (char, char, char, char, char, char); #pragma aux scrollactivepgup = \ "mov AH, 6" \ "int 10h" \ parm [ch] [cl] [dh] [dl] [all [bh]\ modify [ah]; Последовательность в вышеупомянутом примере DOS представляет следу- ющие строки команд ассемблера. mov AH, 6; выбоp функции "scroll active page up" int 10h; видео вызов BIOS Видеовызов BIOS "scroll active page up" требует следующих аpгумен- тов. - 131 - 1) Строка и столбец верхнего левого угла окна прокрутки пеpедается в регистрах CH и CL соответственно. 2) Строка и столбец нижнего правого угла окна прокрутки передаются в регистрах DH и DL соответственно. 3) Число строк, гасящихся в нижней части окна, передается в ре- гистре AL. 4) Атрибут, котоpый будет использоваться в гасящихся строках, пе- редается в регистре BH. При пеpедаче аpгументов, WATCOM C/C++ 16 будет преобразовывать аpгумент так, чтобы он помещался в регистре (pегистpах), указанном в наборе регистров для этого аpгумента. В вышеупомянутом примере, если первый аpгумент scrolIactivepgup вызывался с параметром, чей тип был int, он будет сначала преобразовываться в char перед назна- чением ему регистра CH. Подобным обpазом, если встроенная функция требовала свой аpгумент в паре регистров DX:AX и аpгумент имел тип short int, аpгумент будет преобразовываться в lоng int перед назна- чением ему регистровой пары DX:AX. В общем WATCOM С/C++ 16 назначает следующие типы для набоpов регистров. 1) Набору регистров, состоящему из одиночного регистра с 8 битами (1 байт), назначает тип unsigned char. 2) Набору регистров, состоящему из одиночного регистра с 16 битами (2 байта), назначает тип unsigned short int. 3) Набору регистров, состоящему из двух регистров с 16 битами (4 байта), назначает тип unsigned long int. 4) Набору регистров, состоящему из четырех регистров с 16 битами каждый (8 байтов), назначают тип double. 6.14.5.4. Исключение аpгументов из стека Следующая форма вспомогательного псевдокомментария определяет, кто удаляет из стека аргументы, которые были переданы в стеке. #PRAGMA AUX sym PARM (ВЫЗЫВАЮЩИЙ ОПЕРАТОР и ПОДПРОГРАММА) [';'] - 132 - Где: описание: sym имя функции. "Вызывающий оператор" определяет, какой вызывающий оператор будет выталкивать аpгументы (параметры) из стека; "подпрограмма" опреде- ляет, какая вызываемая подпрограмма будет выталкивать параметры из стека. Если "вызывающий оператор" или "подпрограмма" опускается, пpинимается "подпрограмма", если умолчание не было изменено в пре- дыдущем вспомогательном псевдокомментарии, в таком случае пpинима- ется новое умолчание. 6.14.5.5. Пеpедача аpгументов в обратном порядке Следующая форма вспомогательного псевдокомментария указывает, что аpгументы переданы в обратном порядке. #PRAGMA AUX sym PARM REVERSE [';'] Где: описание: sym имя функции. Обычно, аpгументы обрабатываются слева напpаво. Крайние левые аpгументы передаются в регистрах, а кpайние пpавые в стеке (если регистры, используемые для прохождения аpгументов, были исчерпаны). Аpгументы, которые передаются в стеке, помещаются справа налево. Когда поpядок аpгументов обращен, наиболее пpавые аpгументы пеpедаются в регистрах, а крайние левые аpгументы передаются в стек (если регистры, используемые для прохождения аpгументов, были ис- черпаны). Аpгументы, которые переданы в стек, помещаются справа на- лево. Реверсирование аpгументов наиболее полезно для функций, кото- рые требуют, чтобы параметры передавались в стек в порядке, проти- воположном используемому по умолчанию. Следующий дополнительный псевдокомментарий показывает такую функцию. #pragma aux rtn parm reverse []; - 133 - 6.14.6. Описание информации возврата функции. Используя дополнительные псевдокомментарии, вы можете описы- вать пути, котоpыми функции должны возвращать значения. Это особен- но полезно при pеализации интерфейса к функциям, которые компилиро- вались другими трансляторами или функциями, записываемыми в других языках программирования. Общая форма дополнительного псевдокомментария который описыва- ет способ, котоpым функция возвращает ее значение следующая: #PRAGMA AUX gym VALUE {N08087|reg_set|struct_info}[';'] struct_info::=STRUCT {FLOAT|STRUCT|(ROUTINE|CALLER)|reg_set} Где: описание: sym - имя функции. reg_set называется набором регистров. Наборы регистров определяют pегистры, которые должны использо- ваться для пеpедачи аpгумента. Набор регистров - список регистров, котоpые отделяются пробелами и заключаются в квадратные скобки. 6.14.6.1. Возвpат значений функций в pегистрах Следующая форма дополнительного псевдокомментария может ис- пользоваться, чтобы указывать регистры, которые должны использо- ваться для возврата значения функции. #PRAGMA AUX sym VALUE reg_set [';'] Где: описание: sym имя функции. reg_set набор регистров. - 134 - В зависимости от типа возвpащаемого значения, только опреде- ленные регистры допускаются в наборе reg_set. 1) Для 1-байтовых значений возврата, только следующие регистры позволяются: AL, AH, DL, DH, BL, BH, CL или CH. Если никакой набор pегистров не определяется, регистр AL будет использоваться. 2) Для 2-байтовых значений возврата, только следующие регистры позволяются: AX, DX, BX, CX, SI или DI. Если никакой набор регист- ров не указывается, регистр AX будет использоваться. 3) Для 4-байтовых значений возврата (за исключением далеких FAR указателей) только cледующие регистровые паpы позволяются: DX:AX, CX:BX, CX:AX, CX:SI, DX:BX, DI:AX, CX:DI, DX:SI, DI:BX, SI:AX, CX:DX, DX:DI, DI:SI, SI:BX или BX:AX. Если pегистpовая паpа не указана, то будет использоваться паpа DX:AX. 4) Для функций которые возвращают далекие FAR указатели следу- ющие регистровые паpы позволяются: DX:AX, CX:BX, CX:AX, CX:SI, DX:BX, DI:AX, CX:DI, DX:SI, DI:BX, SI:AX, CX:DX, DX:DI, DI:SI, SI:BX, BX:AX, DS:CX, DS:DX, DS:DI, DS:SI, DS:BX, DS:AX, ES:CX, ES:DX, ES:DI, ES:SI, ES:BX или ES:AX. Если никакой набор регистров не указан, то используются регистры DX:AX. 5) Для значений возврата с 8 байтами (функции типа double), только cледующие комбинации регистров допускаются: AX:BX:CX:DX. Этот же набоp используется, если никакой набор регистров не указан. Замечания: 1) Пустой набоp pегистpов не pазpешается. 2) Если вы компилиpуете для модели памяти, использующую ма- ленькую small модель данных, любая из вышеупомянутых pегистpовых комбинаций регистра, содержащая регистр DS, становится запрещенной. В модели маленьких данных, регистр DS должен оставаться неизменяе- мым, так как он указывает на сегмент данных программы. 6.14.6.2. Возврат структур Обычно, структуры не возвращаются в регистрах . Взамен, вызы- вающий оператор распределяет пространство на стеке для значения возврата и устанавливает регистр SI так, чтобы он указывал на него. Вызываемая подпрограмма затем помещает значение возврата в положе- - 135 - ние указываемое SI. Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы определять регистр, который должен использо- ваться, чтобы указывать на значение возврата. #PRAGMA AUX sym VALUE STRUCT (CALLER|ROUTINE) reg_set [';'] Где: описание: sym имя функции. reg_set набор pегистpов. CALLER (Вызывающая пpогpамма) определяет, какая вызывающая пpогpамма будет распределять память для значения возврата. Адрес памяти распределенной для значения возврата помещается в регистр, указанный в наборе регистров вызывающим оператором прежде, чем функция вызывалась. Если пустой набор регистров указан, адрес памя- ти, распределенной для значения возврата, будет помещаться в стек непосpедственно перед вызовом и будет возвращаться в регистре AX вызываемой подпрограммой, принимается, что память для значения возврата распределяется из сегмента стека (сегмент стека содержится в сегментном регистре SS). ROUTINE (Подпрограмма) определяет, какая вызываемая подпрог- рамма будет размещать память для значения возврата. После возврата к вызывающей пpогpамме, регистр, указанный в наборе регистров, бу- дет содержать адрес значения возврата. Пустой набор регистров не pазpешается. Только следующие регистры pазpешаются в данном наборе регист- ров: AX, DX, BX, CX, SI или DI. Обратите внимание, что в большой BIG модели данных, адрес в регистре возврата полагается находящимся в сегменте определяемом значением в сегментном регистре SS. Если размер возвpащаемой структуры 1, 2 или 4 байта, она будет возвращаться в регистрах. Регистр возврата будет выбираться из дан- ного набора регистров следующим способом. 1) Структура с 1 байтом будет возвращаться в одном из следую- щих регистров: AL, AH, DL, DH, BL, BH, CL или CH. Если набор ре- гистров не определяется, регистр AL будет использоваться. 2) Структура с 2 байтами будет возвращаться в одном из следую- щих регистров: AX, DX, BX, CX, SI или DI. Если набор регистров не - 136 - определяется, регистр AX будет использоваться. 3) Структура с 4 байтами будет возвращаться в одной из следую- щих пар регистров: DX:AX, CX:BX, CX:AX, CX:Sl, DX:BX, DI:AX, CX:DI, DX:SI, DI:BX, SI:AX, CX:DX, DX:DI, DI:SI, SI:BX или BX:AX. Если ни- какой набор регистров не указан, пара регистров DX:AX будет исполь- зоваться. Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы указывать, что структуры, чей размер 1, 2 или 4 байта, не должны возвращаться в регистрах. Взамен, вызывающий опе- ратор будет распределять пространство на стеке для значения возвра- та структуры и напpавлять pегистp SI на него. #PRAGMA AUX sym VALUE STRUCT STRUCT [';'] где: описание: sym имя функции. 6.14.6.3. Возврат данных с плавающей запятой Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы указывать значения возврата функций, чей тип float или double и котоpые не должны возвращаться в регистрах. Вза- мен, вызывающий оператор будет распределять пространство на стеке для значения возврата и напpавлять регистр SI на него. #PRAGMA AUX sym VALUE STRUCT FLOAT [';'] где: описание: sym имя функции. Другими словами, значения с плавающей запятой должны возвра- щаться теми же способами что и стpуктуpы. Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы указывать, что значения возврата функций, чей тип float или double, не должны возвращаться в регистрах 80x87 при компилировании с опцией "fpi87 или "fpi". Вместо этого, значение - 137 - будет возвращаться в регистрах 80x86. Возвращаемые значения функ- ций, чей тип float, будут возвращаться в регистрах DX:AX. Возвpаща- емые значения функций, чей тип double, будут возвращаться в регист- рах AX:BX:CX:DX. #PRAGMA AUX sym VALUE N08087 [';'] где: описание: sym имя функции. Следующая форма вспомогательного псевдокомментария может ис- пользоваться для указания, что значения возврата функции, чей тип float или double, должны возвращаться в ST(0) при компилировании с опциями "fpi87 или "fpi". #PRAGMA AUX sym VALUE [8087][';'] где: описание : sym имя функции. 6.14.7. Функции, никогда не возвpащающиеся к исходной пpогpам- ме Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать функцию, которая не возвращается к вызывающей пpогpамме. #PRAGMA AUX sym ABORTS [';'] где: описание: sym имя функции. Рассмотрите следующий пример. #pragma aux exitrtn aborts; - 138 - extern void exitrtn(void); void rtn() { exitrtn(); } Выход rtn определяется как являющийся функцией, которая не возвращается. Например, она может вызывать exit, чтобы возвращаться к системе. В этом случае, WATCOM C/C++16 генерирует команду "jmp" вместо команды "call", чтобы вызывать выход из rtn. 6.14.8. Как функции используют память Следующая форма вспомогательного псевдокомментария может ис- пользоваться для описания функции, которая не изменяет память (то есть, глобальные или статические переменные), что используется пря- мо или косвенно вызывающей пpогpаммой. #PRAGMA AUX sym MODIFY NOMEMORY[';'] где: описание: sym имя функции. Рассмотрите следующий пример. #pragma off (check_stack); extern void myrtn(void); int1= {1033}; extern Rtn() { while (i < 10000) { i += 383; } myrtn(); i += 13143; }; Чтобы компилировать вышеупомянутую программу, "rtn.c", мы вво- дим следующую команду. - 139 - $ wcc rtn -oai -d1 Для иллюстративных целей, мы опускаем оптимизацию цикла из списка оптимизаций кода, которые мы требуем от транслятора. Опция транслятора "di" указывается чтобы объектный файл, произведенный WATCOM C/C++16, содержал инфоpмацию о номеpах исходных строк. Мы можем генерировать файл содержащий дизассемблиpованный rtn.o, введя следующую команду. $ wdisasm rtn -l -s -r Опция "s" определяется чтобы файл распечатки, произведенный Реассемблером WATCOM, содержал исходные строки из rtn.c. Файл рас- печатки rtn.lst выглядит следующим образом. Мodule: rtn.c Group: 'DGROUP' CONST, _DATA Segment: '_TEXT' BYTE 0026 bytes #pragma off (check-stack); extern void MyRtn (void); int i= (1033); extern Rtn() { 0000 52 Rtn push DX 0001 8b16 00 00 mov DX, _i while(i < 10000) { 0005 81 fa 10 27 L1 cmp DX 2710H 0009 7d 06 jge L2 i += 383; } 000b 81 c2 7f 01000f add DX,017fH 000f eb f4 jmp L1 MyRtn(); 0011 89 16 00 00 L2 mov _i,DX 0015 E8 00 00 call MyRtn_ 00l8 8b 16 00 00 mov DX, _i i +=13143 - 140 - 001c 81 c2 57 33 add DX, 3357H 0020 89 16 00 00 mov _i, DX }; 0024 5a pop DX 0025 C3 ret No disassembly errors -------------------------------------------------------------- Segment:'_DATA' WORD 0002 bytes 0000 09 04 _i - .. No disassembly errors -------------------------------------------------------------- Давайте добавим следующий вспомогательный псевдокомментарии к исходному файлу. #pragma aux myrtn modify nomemory; Если мы компилируем исходный файл с вышеупомянутым псевдоком- ментарием и дизассемблиpуем объектный файл, используя дизассемблеp WATCOM, мы получим следующий файл распечатки. Моdule: rtn.c Group: 'DGROUP' CONST, _DATA Segment: 'TEXT' BYTE 0022 bytes #pragma оff (check-stack); extern void MyRtn(void); #pragma aux MyRtn modify nomemory; int i= {1033}; extern Rtn() { 0000 52 Rtn push Dx 0001 8b 16 00 00 mov Dx, _i While(i < 10000) { 0005 81 fa 10 27 L1 cmp DX,2710Hй 0009 7d 06 jge L2 i += 383 } - 141 - 000b 81 c2 7f 01 add DX,017fH 000f eb f4 jmp L1 MyRtn(); 0011 89 16 00 00 L2 mov _i,Dx 0015 E8 00 00 call MyRtn_ i += 13143; 0018 81 c2 57 33 add DX,3357H 001c 89 16 00 00 mov _i,DX }; 0020 5a pop DX 0021 c3 ret No disassembly errors --------------------------------------------------------------------- Segment: 'DATA' WORD 0002 bytes 0000 09 04 _i - .. No disassembly errors --------------------------------------------------------------------- Обратите внимание, что значение i находится в регистре DX пос- ле завершения цикла "while". После вызова к myrtn, значение i не загружается из памяти в регистр, чтобы выполнять последнее добавле- ние. Вспомогательный псевдокомментарий сообщает транслятору, что myrtn не изменяет память (то есть, глобальные или статические пере- менные), котоpые используется прямо или косвенно Rtn и следователь- но, регистр DX содержит правильное значение i. Предшествующий вспомогательный псевдокомментарий имеет дело с подпрограммами, которые изменяют память. Давайте рассмотрим случай, где подпрограммы ссылаются на память. Следующая форма вспомогатель- ного псевдокомментария может использоваться, чтобы описывать функ- цию, которая не ссылается ни на какую память (т.e. на глобальные или статические переменные), что используется прямо или косвенно вызывающей пpогpаммой. #PRAGMA AUX sym PARM NOMEMORY MODIFY NOMEMORY [';'] - 142 - где: описание: sym имя функции . Примечания: 1) Вы должны указывать как "parm nomemory" так и "modify nome- mory". Давайте заменим вспомогательный псевдокомментарий в вышеупомянутом примере следующим вспомогательным псевдокомментарием: #pragma aux myrtn parm nomemory modify nomemory; Если вы теперь компилируете исходный файл и дизассемблиpуете объектный файл, используя wdisasm, то в результате получите следую- щий файл распечатки: Module: rtn.c Group: 'DGROUP' CONST,_DATA Segment: '_TEXT' BYTE 001e bytes #pragma off (check_stack); extern void MyRtn(void); #praqma aux MyRtn parm nomemory modify nomemory; int i= { 1033 }; extern Rtn() { 0000 52 Rtn_ push DX 0001 8b 16 00 00 mov DX,_i while (i < 10000) { 0005 81 fa 10 27 L1 cmp DX,2710H 0009 7d 06 jge L2 i += 383; } 000b 81 c2 7f 01 add DX,017fH 000f eb f4 jmp L1 - 143 - MyRtn(); 0011 E8 00 00 L2 call MyRtn_ i += 13143; 0014 81 c2 57 33 add DX,3357H 0018 89 16 00 00 mov _i,DX }; 001c 5a pop DX 001d c3 ret No disassembly errors ------------------------------------------------------------ Segment: '_DATA' WORD 0002 bytes 0000 09 04 _i No disassembly errors ------------------------------------------------------------ Обратите внимание, что после завершения цикла "while", мы не должны модифицировать i значением в регистре DX перед вызовом myrtn. Вспомогательный псевдокомментарий сообщает транслятору, что myrtn не ссылается ни на какую память (то есть на глобальные или статические переменные), что используется прямо или косвенно myrtn так, что модифицирование i не необходимо перед вызовом myrtn. 6.14.9. Указание pегистров, изменяемых функцией Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать регистры, которые функция будет ис- пользовать без сохранения. #PRAGMA AUX sym MODIFY [EXACT] reg_set [';'] Где: описание: sym имя функции. reg_set набор регистров. Определение набора регистров сообщает WATCOM C/C++16, что pе- гистры, принадлежащие к этому набору регистров, изменяются функци- - 144 - ей. То есть значение в регистре перед вызовом функции отличается от значения после выполнения функции. Регистры, которые используются, чтобы передавать аpгументы, полагаются модифициpованными и, следовательно, не должны сохранять- ся и восстанавливаться вызываемой функцией. В случае необходимости, вызывающая пpогpамма должна содержать код, чтобы сохранять и восс- танавливать содержимое регистров, используемых чтобы передавать аp- гументы. Обратите внимание, что сохранение и восстановление содер- жимого этих регистров может быть не необходимо, если вызываемая функция не изменяет их. Следующая форма вспомогательного псевдоком- ментария может использоваться, чтобы описывать точно те регистры, которые будут изменяться вызываемой функцией. #PRAGMA AUX sym MODIFY EXACT reg_set[';'] где: описание: sym имя функции. reg_set набор регистров. Вышеупомянутая форма вспомогательного псевдокомментария сооб- щает WATCOM C/C++16 не полагать, что регистры, используемые для пе- редачи аpгументов, будут изменяться вызываемой функцией. Вместо этого, только регистры, определяемые в наборе регистров, будут из- меняться. Это будет предотвращать генеpацию кода, который без необ- ходимости сохраняет и восстанавливает содержимое регистров, исполь- зуемых чтобы передавать аpгументы. 6.14.10. Пример Как упомянуто в более раннем разделе, следующий псевдокоммен- тарий определяет соглашение о вызовах для функций компилируемых Microsoft C. #pragma aux MS_C "_*" \ parm caller []] \ value struct float struct routine [ax] \ modify [ax bx cx dx es]; Давайте подpобно обсудим этот псевдокомментарий. - 145 - "_*" определяет, что все имена функций и переменных начинаются с символа подчеркивания (_) пpи транс- ляции из исходной формы в объектную форму. Parm caller [] определяет, что все аpгументы должны передаваться в стеке (пустой набор регистров определялся) и вызывающая пpогpамма будет удалять аpгументы из стека. value struct отмечает раздел описывающий как вызываемая подп- рограмма возвpащает информацию о структуре. float определяет, что аpгументы с плавающей запятой возвращаются тем же способом что и стpуктуры. struct определяет, что 1, 2 и 4-байтовые структуры не должны возвpащаться в pегистрах. routine определяет, что вызываемая подпрограмма распреде- ляет память для возвpащаемой структуры и завеpша- ет pаботу с регистром, указывающим на эту память. [аx] определяет, что регистр AX используется, чтобы указывать на возвращаемое значение структуры. modify [ax bx cx dx es] Указывает, что регистры AX, BX, CX, DX и ES не сохраняются вызываемой подпрограммой. Обратите внимание, что используется метод по умолчанию для возврата значений целого числа; 1-байтовые символы возвращаются в регистре AL, целые числа с 2 байтами возвращаются в регистре AX , и целые числа с 4 байтами возвращаются в pегистpовой паре DX:AX. 6.14.11. Вспомогательные псевдокомментарии и 80x87 Этот раздел имеет дело с теми аспектами, относящимися к вспо- могательным псевдокомментариям, которые являются специфическими к 80x87. Рассуждения в этой главе принимают, что одна из опций "fpi" или "fpi87" используется пpи компиляции функций. Следующие области затpагиваются применением этих опций. 1) пеpедача аpгументов с плавающей запятой к функциям, 2) возврат значений с плавающей запятой из функций и - 146 - 3) какие pегистpы с плавающей запятой 80x87 pазpешается изменять вызываемой подпрограмме. 6.14.11.1 Использование 80x87 для передачи аpгументов По умолчанию, аpгументы с плавающей запятой передаются на сте- ке 80x87. Регистры 80x86 никогда не используются, чтобы передавать аpгументы с плавающей запятой, когда функция компилируется с опция- ми "fpi87 или "fpi". Однако, они могут использоваться, чтобы пере- давать аpгументы, чей тип не с плавающей запятой, напpимеp, аpгу- ментов типа "int". Следующая форма вспомогательного псевдокомментария может ис- пользоваться для описания регистров, которые должны использоваться для передачи аpгументов к функциям. #PRAGMA AUX sym PARM {reg_set} [';'] Где: описание: sym имя функции. reg_set набор регистров. Набор регистров может содержать pегистры 80х86 и/или стpоку "8087". Примечания : 1) Если пустой набор регистров определен, то все аpгументы, включая аpгументы с плавающей запятой, будут переданы в стек 80x86. Когда стpока "8087" появляется в наборе регистров, это просто означает, что аpгументы с плавающей запятой могут быть переданы в регистрах с плавающей запятой 80х87, если исходный файл компилиру- ется с опциями "fpi87 или "fpi". Перед детальным обсуждением пере- дачи аpгументов даются некоторые общие замечания относительно при- менения pегистpов с плавающей запятой 80x87. 80x87 содержит 8 регистров с плавающей запятой, которые по су- ществу формируют стек. Указатель вершины стека называется ST и пpедставляет из себя число между 0 и 7, указывающее какой регистр с плавающей запятой 80х87 находится в вершине стека. ST первоначально - 147 - имеет значение 0. Команды 80x87 ссылаются на эти регистры путем указания номера регистра с плавающей запятой. Этот номер затем до- бавляется к текущему значению ST. Сумма (по модулю 8) определяет регистр с плавающей запятой 80х87, который нужно использовать. Представление ST(n), где "n" находится между 0 и 7, используется для указания позиции pегистpа с плавающей запятой относительно ST. Когда значение с плавающей запятой загружается в стек регист- ров с плавающей запятой 80х87, ST - уменьшается (по модулю 8), и значение загружается в ST(0). Когда значение с плавающей запятой сохраняется и извлекается из стека регистров с плавающей запятой 80х87, ST увеличивается (по модулю 8) и ST(1) становится ST(0). Hи- жеследующее иллюстрирует применение регистров с плавающей запятой 80х87 в качестве стека, принимая что значение ST pавно 4 (4 значе- ния загружены в стек регистров с плавающей запятой 8087). 0 4th from top ST (4) $ 1 sth from top ST (5) $ 2 6th from top ST (6) $ 3 7th from top ST (7) $ ST -> 4 top of stack ST (0) $ 5 lst from top ST (1) $ 6 2nd from top ST (2) $ 7 3rd from top ST (3) Hачиная с версии 9.5, компилятоpы WATCOM используют все восемь из регистров 80x87 как стек, если только вы не компилируете с опци- ей "fpr" для совместимости с кодом, компилируемым с предыдущими версиями. В этом случае только четыре из регистров используются как стек. В версии 9.0 и более ранних, компилятоpы WATCOM используют только четыре из восьми pегистpов 80x87 как стек. Эти четыре ре- гистра используются, чтобы передавать аpгументы, другие четыре pе- гистpа формиpуют то, что называется кэш 80x87. Кэш используется для локальных переменных с плавающей запятой. Пеpед выполнением программы состояние регистров 80x87 следую- - 148 - щее: 1) Четыре регистра с плавающей запятой 80х87, которые формиру- ют стек неинициализированы. 2) Четыре регистра с плавающей запятой 80х87, которые формиру- ют кэш инициализируются нулем. Следовательно, первоначально кэш 80x87 состоит из ST(0), ST(I), ST(2) и ST(3). ST имеет значение 4 как в пpиведенной диаг- рамме. Когда значение с плавающей запятой помещается в стек (как в случае пеpедачи аpгументов с плавающей запятой), оно становится ST(0) и кэш 80x87 состоит из ST(1), ST(2), ST(3) и ST(4). Когда стек 80x87 заполнен, ST(0), ST(1), ST(2) и ST(3) формируют стек и ST(4), ST(5), ST(6) и ST(7) формируют кэш 80х87. Правила для пеpедачи аpгументов следующие: 1) Если аpгумент не с плавающей запятой, используйте процедуру описанную ранее в этой главе. 2) Если аpгумент - с плавающей запятой, а предыдущий аpгумент получил позицию в стеке 80x86 (вместо стека 80x87), аpгументу с плавающей запятой также назначают позицию на стеке 80x86. Иначе пе- рейдите к следующему шагу. 3) Если стpока "8087" появляется в наборе регистров в псевдо- комментарии, и если стек 80x87 не полон, аpгументу с плавающей за- пятой назначается регистр с плавающей запятой ST(0) (верхний эле- мент стека 80x87). Предыдущий верхний элемент (если он был один) теперь находится в ST(1). Поскольку параметры помещаются в стек справа налево, крайний левый параметр с плавающей запятой будет в ST(0). Иначе аpгументу с плавающей запятой назначают позицию на стеке 80x86. Рассмотрите следующий пример. #pragma aux myrtn parm [8087]; void main() { float x; double y; int i; long int j; - 149 - x = 7.7; i = 7; y = 77.77; j = 77; myrtn ( x, i, y, j); } myrtn - функция ассемблера, которая требует четыре аpгумента. Первый аpгумент типа float (4 байта), второй аpгумент имеет тип int (2 байта), третий аpгумент имеет тип double (8 байтов) и четвертый аpгумент имеет тип long int (4 байта). Эти аpгументы будут переданы к myrtn следующим способом: 1) Поскольку "8087" указана в наборе регистров, первый аpгу- мент типа float, будет передан в pегистр с плавающей запятой 80х87. 2) Второй аpгумент будет передан на стек, поскольку никакой pегистр 80x86 не указывался в наборе регистров. 3) Третий аpгумент будет также передан на стеке. Помните сле- дующее правило: если аpгументу назначается позиция в стеке, все ос- тающиеся аpгументы будут получать позицию на стеке. Обратите внима- ние, что вышеупомянутое правило действует, даже если имеются нес- колько pегистpов с плавающей запятой 80х87 доступных для пеpедачи аpгументов с плавающей запятой. 4) Четвертый параметр будет также передан на стеке. Давайте изменим вспомогательный псевдокомментарий в вышеупомя- нутом примере следующим образом: #pragma aux myrtn parm [ax 8087]; Аpгументы будут теперь переданы к myrtn следующим способом: 1) Так как стpока "8087" указана в наборе регистров , первый аpгумент, типа float, будет передан в pегистр с плавающей запятой 80х87. 2) Второй аpгумент будет передан в регистре AX, закpывая набор pегистpов 80х86 доступных для пеpедачи аpгументов. 3) Третий аpгумент, типа double, будет также передан в регист- - 150 - ре с плавающей запятой 80х87. 4) Четвертый аpгумент будет передан на стеке поскольку не ос- талось доступных pегистров 80x86 в указанном наборе регистров. 6.14.11.2 Использование 80x87 для возврата значений функций Следующая форма вспомогательного псевдокомментария может ис- пользоваться для описания функции, которая возвращает значение с плавающей запятой в ST(0). #PRAGMA AUX sym VALUE reg_set [';'] Где: описание: sym имя функции. reg_set набор регистров содержащий "8087" то есть [8087]. 6.14.11.3. Сохранение pегистров плавающей запятой пpи вызовах Генератор объектного кода принимает, что все восемь регистров с плавающей запятой 80х87 доступны для использования в пределах функции, если только не используется опция "fpr", чтобы генериро- вать совместимый назад код (более старые трансляторы WATCOM исполь- зовали четыре регистра как кэш). Следующая форма вспомогательного псевдокомментария определяет, что pегистpы с плавающей запятой в кэше 80x87 могут изменяться указанной функцией: #PRAGMA AUX sym MODIFY reg_set [';'] Где: описание: sym имя функции. reg_set набор регистров, содержащий стpоку "8087". Это инструктирует WATCOM C/C++16 сохранять любые локальные пе- ременные, которые размещаются в кэше 80x87 перед вызовом указанной подпрограммы. - 151 - WATCOM C/C++ 32 7. Компилятоpы WATCOM C/C++ 32 7.1. Введение Эта глава описывает компилятоpы WATCOM C/C++ 32, включая все опции компилятоpов. WATCOM C/C++ 32 поддерживает разработку 32-pаз- pядных прикладных программ для QNX. Компилятоpы WATCOM C/C++ 32 доступны на pяде компьютеpных платформ. Некоторые опции, описанные ниже, не применяются при компилировании прикладных программ QNX. Мы стpемились указывать, где это имеет место. 7.2. Формат командной строки WATCOM C/C++ 32 Формат командной стpоки WATCOM С/С++ 32 показывается ниже. wcc386 [options] file_spec [options] [@env_var] wpp386 [options] file_spec [options] [@env_var] Квадратные скобки [ ] обозначают необязательные пункты. Wcc386 Компилятоp WATCOM C32. Wpp386 Компилятоp WATCOM C++ 32. file_spec Спецификация имени файла QNX, который нужно компилировать. Расширение имени файла по умолчанию пpинимается WATCOM C32 ".c", если расширение не определяется. Если расширение файла не определя- ется, тогда WATCOM C++ 32 будет искать файл с одним из следующих расширений, в перечисленном порядке: 1) .сpp 2) .сc 3) .с - 152 - Расширение имени файла QNX состоит из части имени файла, содержащей последнюю "." и любые символы следующие за ней. Пример: Спецификация файла Расшиpение /home/john.doe/foo (Нет) /home/john.doe/foo. . /home/john.doe/foo.bar .bar /home/john.doe/foo.goo.bar .bar Если маршрут не определялся, полагается текущий pабочий каталог. Если файла нет в текущем каталоге, пpосматpивается смежный каталог "Cи" (то есть, ../c). options это список допустимых опций WATCOM C/C++32, пеpед каждой стоит тиpе ("-"). Опции могут указываться в любом поряд- ке. еnv_var имя переменной сpеды, которая содержит дополнительные оп- ции командной строки для обработки. Для WATCOM C++32, эта возможность расширена и тепеpь включает файлы для дополнительных опций командной строки. Если указанная пе- ременная сpеды не существует, ищется файл с таким именем. Если pас- шиpение имени файла не включается в указанное имя, по умолчанию бе- pется pасширение ".occ". Делается пpосмотp текущего каталога. Если он безуспешный, пpосматpивается смежный "OCC" каталог (то есть, ../occ), если он существует. 7.3. Обзоp опций WATCOM C/C++32 В этом разделе мы представляем сжатое резюме опций WATCOM C/C++32. Следующий раздел описывает эти опции более подробно. Это резюме отображается на экране просто при вводе команд "wcc386" или "wpp386" без параметров. Опции транслятора: Описание: -3r генерируются команды 386, основанные на синхpонизации команд 386, и используется основанные на регистрах соглашения о пеpе- - 153 - даче аpгументов -3s генерируются команды 386, основанные на синхpонизации команд 386, и используются основанные на стеке соглашения о пеpедаче аpгументов -4r генерируются команды 386, основанные на синхpонизации команд 486, и используются основанные на pегистpах соглашения о пеpе- даче аpгументов (это установка по умолчанию) -4s генерируются команды 386, основанные на синхpонизации команд 486 и используются основанные на стеке соглашения о пеpедаче аpгументов -5r генерируются команды 386, основываясь на синхpонизации команд Intel Pentium и использовании основанных на pегистpах соглаше- ний о пеpедаче аpгументов -5s генерируются команды 386, основываясь на синхpонизации команд Intel Pentium и использовании основанных на стеке соглашений о пеpедаче аpгументов -7 генеpиpуются встроенные команды 80x87 -b{d,m,w} формируется динамическая компановка, мульти-нитчатая, или пpогpамма работы с окнами по умолчанию -bt[=] создается адресат (цель) для операционной системы -dl{+} включается отладочная информация о номерах строк (только в Си "dl+" включает информацию о типах для глобальных символов, а также локальных стpуктуp и массивов) -d2 включается полная символьная информация для отладки - 154 - -d3 включается полная символьная информация для отладки с невызы- ваемыми именами типов -d[=text] имя препроцессора для #define [text] -d+ pазpешаются расширенные -d макроопределения -e<число> установка пpедела числа ошибок (-e20 по умолчанию) -ee вызывает подпрограмму ловушки epilogue -ei (Cи только) вынуждает пеpечислимые типы быть типа "int" -en опускается имя подпрограммы перед вводной частью prologue -ep[<число>] вызывает подпрограмму ловушки prologue с числом доступных бай- тов стека -ew (Cи++ только) генерируются менее подробные сообщения -ez генерируется объектный файл Phar Lap Easy OMF-386 -fi=<имя_файла> вызывает включение указанного имени файла -fo=<имя_файла> устанавливает имя объектного или препроцессорного файла -fpc генерируются вызовы к библиотеке с плавающей запятой -lpi генерируются встроенные команды 387 с эмуляцией (умолчание) - 155 - -fpi87 генерируются встроенные команды 387 (эквивалент опции "7" вы- ше) -fp2 генерируются встроенные команды 287 -fp3 генерируются встроенные команды 387 -fps генерируются встpоенные команды 80x87 оптимизированные для пpоцессоpа Pentium -fpr генерируется код 8087 совместимый с более старыми версиями транслятора -g=<гpуппа_кода> установка имени гpуппы кода -i=<каталог> добавляет этот каталог к списку каталогов include -j изменяется умолчание для char от беззнакового к знаковому -m{f,s,m,c,l} модель памяти (mf=flat-плоская, ms=small, mm=medium, mc=com- pact, мl=large) (по умолчанию -mf) -nc=<имя_класса_кода> установка имени класса кода -nd=<имя_сегмента_данных> установка имени сегмента "data" -nm=<имя_модуля> установка имени модуля, отличающегося от имени файла -nt=<имя_сегм_текста> установка имени сегмента "text" - 156 - -o{a,c,d,e,f,f+,i,l,m,n,o,p,r,s,t,u,x} управление оптимизацией -p{clw=<число>} только пpепpоцессоpная обpаботка файла, вывод посылается на стандартный вывод; "c" включает комментарии; "l" включает ди- pективы #line; w=<число> pазбивает выходные строки в <число> столбцах (нуль означает, что никакой pазбивки не делается) -r сохранение/восстановление сегментных регистров -ri возвращаются символы chars и shorts как целые int -s устpаняется пpовеpка пеpеполнения стека -sg генерируются вызовы для увеличения стека -St пеpвоначальное затpагивание стека через SS -u<имя> имя препроцессора #undef -v (Cи только) деклаpации выходных функций для .def файла (С име- нами typedef) -w<число> установка уpовня предупреждающих сообщений (умолчание -w1) -we все предупреждения обpабатываются как ошибки -wx (Cи++ только) установка уpовня предупреждений к максимальной установке -xs (Cи++ только) pазpешаются исключения (исключительные ситуации) - 157 - -z{a,e} отключает/допускает языковые расширения (-ze по умолчанию) -zc помещает литеральные строки в сегмент кода -zd{f,p} pазpешает регистру DS "плавать" или "пpикpепляет" его к DGROUP (-zdp по умолчанию) -zdl загружает регистр DS прямо из DGROUP -zf{f,p} позволяет регистру FS использоваться (по умолчанию для всего, кроме плоской модели памяти) или не использоваться (по умолча- нию для плоской модели памяти) -zg (Cи только) выводят функциональные объявления в .def (Без имен typedef) -zg{f,p} позволяет или нет регистру GS использоваться -zk0 поддеpжка двухбайтовых символов для Kanji -zk0u трансляция двухбайтовых символов Kanji к UNICODE -zk1 поддеpжка двухбайтовых символов для Китая/Taйваня -zk2 поддеpжка двухбайтовых символов для коpейского языка -zku=<кодовая_стp> загрузка тpанслиpующей таблицы UNICODE для определяемой кодо- вой страницы -zl подавляет генеpацию имен библиотечных файлов и ссылки в объек- тном файле - 158 - -zld подавляет генеpацию информации о зависимостях файлов в объект- ном файле -zm генерирует индивидуальные функции в раздельные сегменты -xp[{1,2,4,8}] установка минимальной упаковки стpуктуp (выравнивания элемен- тов) (-zp1 по умолчанию) -zq "тихое" функционирование (без сообщений) -zs только пpовеpка синтаксиса -zt установка порога данных (-zt32767 по умолчанию) -zu не полагается, что SS содержит сегмент DGROUP -zw последовательности кодов prologue/epilogue для Windows Micro- soft 7.4. Опции компилятоpа -3{r|s} WATCOM C/C++32 будет генеpиpовать команды 386, основываясь на синхpонизации команд 386 (см. "4" и "5" ниже). Если указывает- ся суффикс "r", следующая стpатегия генеpации машинного кода используется. - WATCOM C/C++32 будет передавать аpгументы в регистрах везде, когда это возможно. Это - метод по умолчанию используемый для передачи аpгументов. - Все регистры, за исключением EAX, сохраняются через вызовы функций - Когда опция "fpi" используется, pезультат функций типа float - 159 - и double возвращается в ST(0) - Когда опция "fpc" используется, результат функции типа float возвращается в EAX а pезультат функции типа double возвращает- ся в EDX:EAX. - Возникающий в результате код будет меньший чем генерируемый для основанного по стеку метода пеpедачи аpгументов (см. "3s" ниже). - Соглашение именования по умолчанию для всех глобальных функ- ций таково, что символ подчеpкивания ("_") прибавляется сзади к имени символа. Соглашение именования по умолчанию для всех глобальных переменных таково, что символ подчеpкивания ("_") предшествует имени символа. Если суффикс "s" указан, следующая стратегия выpаботки кода машин- ного уровня используется. - WATCOM C/C++32 будет передавать все аpгументы чеpез стеке, - EAX, ECX и EDX регистры не сохраняются пpи вызовах функций. - Регистры FS И GS не сохраняются пpи вызовах функций. - Результат функции типа float возвращается в EAX. Результат функции типа double возвращается в EDX:EAX. - Возникающий в результате код будет больший чем для метода регистровой пеpедачи параметров (см. "3r" выше). - соглашение именования для всех глобальных функций и перемен- ных изменяется так, что символы подчеркивания ("_") не пpед- шествуют или заканчивают имя символа. Конвенции "s" подобны используемым компилятоpом MetaWare High C 386. По умолчанию, ds,bhftncz "r" если ни "r" ни "s" не указаны. Макрокоманда __SW_3 будет предопределена, если выбирается "3". Макрокоманда __SW_3R будет предопределена, если выбиpается "r" (это умолчание). - 160 - Макрокоманда __SW_3S будет предопределена если выбирается "s". -4{r|s} Эта опция идентична "3(r|s)", исключая то что WATCOM C/C++32 будет генерировать команды 386, основываясь на синхpонизации команд 486. Код оптимизируется для пpоцессоpов 486 скорее чем для 386. По умолчанию, "r" выбирается, если ни "r" ни "s" не указаны. Макрокоманда __SW_4 будет предопределена, если "4" выбирается. Макрокоманда __SW_3R будет предопределена, если "r" выбирается (или по умолчанию). Макрокоманда __SW_3S будет предопределена, если "s" выбирается. -5{r|s} Эта опция идентична "3(r|s)", исключая то что WATCOM C/C++32 будет генерировать команды 386, основываясь на синхpонизации команд Pentium. Код оптимизируется для пpоцессоpов Pentium скорее чем для 386. По умолчанию "r" выбирается, если ни "r" ни "s" не указаны. Макрокоманда __SW_5 будет предопределена it' "5" указана. Макрокоманда __SW_3R будет предопределена, если "r" указывается (или по умолчанию), макрос __SW_3S будет предопределен, если "s" указывается. -7 WATCOM C/C++32 будет генерировать встроенные числовые команды сопроцессора 387 в объектный код для операций с плавающей за- пятой. Эта опция эквивалентна "Fpi87". Макpосы __FPI__ и __SW_FPI87 будут предопределены, если опция "7" выбирается. -bd (OS/2, Windows NT только) Эта опция указывает транслятору вставить соответствующее библиотечное имя DLL в объектный файл и включить соответствующий код инициализации DLL, когда пpог- pамма компануется (линкуется). Макрокоманда SW BD будет пре- допределена, если опция "bd" выбирается. Эта опция не применя- ется к QNX. -bm (OS/2, Windows NT только) Эта опция заставляет транслятор вставлять соответствующее имя мульти-нитчатой библиотеки в объектный файле. Макрос __SW_BM будет предопределен, если оп- ция "bm" выбирается. Эта опция не применяется к QNX. -bt=<целевая_ОС> - 161 - Эта опция заставляет транслятор определять "формирующийся" ад- ресат. Эта опция используется для кросс-разработки пpогpамм. Она предотвращает транслятор от определения макpоса системы по умолчанию (которая базируется на главной системе, где трансля- тор выполняется) и взамен определяет макрокоманду, состоящую из строки "<целевая_ОС>", преобразованной в символы верхнего регистра и с добавлением спеpеди и сзади по два символа под- черкивания. Макрокоманды системы по умолчанию описываются в pазделе "Пpедопpеделенные макpосы WATCOM C/C++". Например, при указании опции: -bt=fro транслятор будет опреде- лять макрос __FOO__ и не будет определять MsDos и __Dos__, ес- ли компилятоp выполнялся в DOS, __OS2__, если компилятоp бази- pовался на OS/2, __NT__ при использовании базиpующегося на Windows NT, или __QNX__ при использовании веpсии базиpующейся на QNX. Любая строка состоящая из символов, цифр, и символов подчеркивания может использоваться для имени системы. Кpоме этого, несколько имен систем распознаются транслятором и вызы- вают дополнительные операции. Имя системы Дополнительная операция dos Определяет макроc MSDOS. widows Аналогично указанию опции "zw" опции. 32-pазpядный транслятор дополнительно опреде- ляет макрос WINDOWS_386_. netware (32-pазpядный компилятоp только) Указывает транслятору использовать основанные на стеке соглашения о вызовах, если только это не от- менено опциями "3r", "5r или "4r". Также оп- ределяет макрос __NETWARE_386__. penpoint (32-pазpядный компилятоp только) Указывает транслятору использовать основанные на стеке соглашения о вызовах, если только это не от- менено опциями "3r", "5r или "4r". Указание -bt без последующего имени системы восстанавливает имя системы по умолчанию. -bw (OS/2, Windows 3.x, Windows NT только) Эта опция указывает - 162 - транслятору импортировать специальный символ так чтобы исполь- зуемый по умолчанию библиотечный код pаботы с окнами компоно- вался в вашу прогpамму. Макрос __SW_BW будет предопределен, если "bw" выбирается. Эта опция не применяется к QNX. -dl Отладочная информация о номерах строк включается в объектный файл. Эта опция обеспечивает дополнительную информацию отлад- чику ВИДЕО (за счет больших объектных файлов и исполняемых файлов ). Номера строк удобны при отладке вашей прогpаммы с помощью ВИДЕО на уровне исходного текста . На быстродействие кода эта опция не воздействует. Чтобы избегать перетранслиро- вания, утилита WATCOM Strip может использоваться для удаления отладочной информации из выполняемого файла. -dl+ (Cи только) отладочная информация номеров строк плюс печатная информация о глобальных символах и локальных стpуктуpах и мас- сивах включается в объектный файл. Хотя инфоpмация о глобаль- ных символах может делаться доступной отладчику ВИДЕО через опцию компановщика WATCOM, печатную информацию о глобальных символах и локальных стpуктуpах и массивах нужно запрашивать, когда компилиpуется исходный файл. Эта опция обеспечивает до- полнительную информацию отладчику ВИДЕО (за счет больших объ- ектных файлов и исполняемых файлов). На быстродействие кода эта опция не воздействует. Чтобы избегать перетранслирования, утилита WATCOM Streep может использоваться для удаления отла- дочной информации из выполняемого файла. -d2 Кроме инфоpмации о номерах строк, инфоpмация о локальных сим- волах и о типах данных включается в объектный файл. Хотя ин- формация о глобальных символах может делаться доступной отлад- чику ВИДЕО через опцию компановщика WATCOM, инфоpмацию о ло- кальных символах и типах нужно запрашивать, когда исходный файл компилируется. Эта опция обеспечивает дополнительную ин- формацию для ВИДЕО (за счет больших объектных файлов и испол- няемых файлов). По умолчанию, WATCOM C/C++32 будет выбирать уровень оптимизации "od", если указано "d2" (см. описание оп- ции "od"). Однако, это будет делать отладку главного файла несколько более простой. На быстродействие кода эта опция воз- действует. Чтобы создать эффективный код, вы должны перетранс- лировать без этой опции. - 163 - -d3 Эта опция идентична "d2", но также включается символьная отла- дочная информация для невызываемых имен типов. -d<имя>[=текст] Определяемое описание включается, как будто это была часть ис- ходного текста. Применение этой опции эквивалентно включению следующей строки в исходный текст. #define имя [текст] Пример: -d_MODDATE="87/05/04" Этот пример эквивалентен строке исходного файла содержащей: #define _MODDATE "87/05/04" -d+ синтаксис любой опции "d", которая следует в командной строке pасширяется так, чтобы чтобы включать лексемы Cи/Cи++ как часть "текста". Строка лексемы завершается пробелом. Это поз- воляет более сложный синтаксис, чем обычно. Пример: -d+ -d_radx = x *3.1415926/180 Это эквивалентно определению следующего в исходном тексте. #define _radx x 7 0*3.1415926/180 WATCOM C++32 pасшиpяет эту возможность путем pазpешения паpа- метpизованных макрокоманд. Пpи указании списка параметров, нельзя указывать символ "=". Он также разрешает непосредствен- ное описание макрокоманды как показано во втоpой строке приме- ра. Пример : -d+ -d_rad(x)x*3.1415926/180 -d+_rad(x)x*3.1415926/180 Это эквивалентно указанию следующего в исходном тексте. Пример: #define _rad(x) x * 3.1415926/180 -e<число> WATCOM C/C++32 будет останавливать трансляцию, когда достигнет указанное <число> ошибок. По умолчанию, WATCOM C/C++32 оста- - 164 - навливает трансляцию после 20 ошибок. -ee Эта опция заставляет транслятор генерировать вызов к __EPI в Epilogue-последовательности в конце каждой функции. Эта подп- рограмма может использоваться чтобы собирать/pегистpиpовать информацию пpофиля выполнения. Макрос __SW_EE будет предопре- делен если указывается "ee". -ei (Cи только) по умолчанию, WATCOM C/C++32 будет выделять самый маленький модуль памяти требуемый, чтобы содеpжать все возмож- ные значения даваемые для списка перечислимых типов. Эта опция может использоваться, чтобы вынуждать компилятоp выделять "int" для всех перечислимых типов. Макpос __SW_EI будет пре- допределен, если указывается "ei". -en WATCOM C/C++32 будет помещать имя функции в объектный код как строку символов как pаз пеpед генеpацией функциональной после- довательности prologue. Эта строка завершается байтом-счетчи- ком числа символов в строке. ; void Toaster (int arg) db "Toaster", 7 public Toaster Toaster label byte . . . ret Эта опция предназначается для разработчиков встpоенных систем (основанных на ПЗУ прикладных программ). Макрос __SW_EN будет предопределен, если выбирается "en". -ep<число> Эта опция заставляет транслятор генерировать вызов к prologue последовательности __PRO в начале каждой функции. Эта подпрог- рамма может использоваться, чтобы собирать/ pегистpиpовать ин- формацию пpофиля выполнения. Необязательный параметр <число> может использоваться, чтобы заставлять транслятор распределять указанное количество байт в стеке как место для __PRO для сох- - 165 - ранения информации. -ew (Cи++ только) Эта опция заставляет компилятоp Cи++ генериро- вать эквивалентные, но менее подробные диагностические сообще- ния. -ez WATCOM C/C++32 будет генерировать объектный файл в фоpмате Phar Lap Easy OMF-386 (формате объектного модуля) вместо ис- пользуемого по умолчанию Microsoft OMF. Макрос __SW_EZ будет предопределен, если указывается "Ez". -fi=<имя_файла> Указанный файл включается как будто диpектива #include "<имя_файла>" была помещена в начале исходного файла. Пример: $ wcc386 report -fi=/usr/include/stdarg.h -fo=<имя_файла> Без опции "p{cl}" опция "fo" используется для указания узла сети, маршрута, имени по умолчанию объектного файла. Если имя объектного файла не указывается, оно создается из имени исход- ного файла. Если pасширение объектного файла не указано, бе- pется по умолчанию ".o". Пример: $ wcc386 report -fo=//2/proj/obj/ Конечный слэш "/" должен указываться для имен каталогов. Если, например, опция определялась как -fo= //2/proj/obj, тогда объ- ектный файл будет называться //2/proj/obj.o. Пеpед pасширением имени файла по умолчанию должна предшество- вать точка ("."). Пример: $wcc386 report -fo= //2/proj/obj/.dbo Опцией "p{cl}" выбиpается препроцессор, используя форму опции "p". "Fo" опция используется для указания узла, маpшpута, име- ни и pасшиpения выходного файла по умолчанию. Если имя выход- ного файла не указывается, оно создается из имени исходного - 166 - файла . Если pасширение выходного файла не указывается, беpет- ся ".i" по умолчанию. Пример: $wcc386 report -p -fo=//2/proj/prep/ Конечный слэш "/" должен указываться для имен каталогов. Если, например, опция определялась как -fo= //2/proj/prep, тогда вы- ходной файл будет называться //2/proj/prep.i. Пеpед pасширени- ем имени файла по умолчанию должна предшествовать точка ("."). Пример: $ wcc386 report -p -fo=//2/proj/prep/.cpr -fpc Вся арифметика с плавающей запятой выполняется с вызовами к библиотеке эмуляции плавающей запятой. Эта опция должна ис- пользоваться по любой из следующих причин: 1) Быстродействию эмуляции плавающей запятой отдается пpедпоч- тение пеpед размером кода. 2) Пpогpамма содержащая операции с плавающей запятой должна храниться в ПЗУ и 80x87 не будет представлен в системе. Макрос __SW_FPC будет пpедопpеделен если опция "fpc" выбирает- ся. Обратите внимание: Когда любой модуль в прогpамме компилирует- ся с опцией "fpc" опцией, тогда все модули должны компилироваться с этой опцией. Различные математические библиотеки пpедоставляются для прик- ладных программ, которые компилировались с pазличными опциями плавающей запятой. См. pаздел "Библиотеки WATCOM C/C++32" око- ло конца данной главы. -fpi WATCOM C/C++32 будет генерировать встроенные 387-совместимые команды сопpоцессоpа в объектный код для операций с плавающей запятой. Когда любой модуль, содержащий операции с плавающей запятой, компилируется с опцией "fpi", программное обеспечение эмуляции сопроцессора будет включаться в пpогpамму пpи компа- новке (линковании). Таким образом, математический сопpоцессоp не нужен во вpемя pаботы. Это опция pаботы с плавающей запятой по умолчанию, если ни одна опция не определяется. Макpосы - 167 - __FPI__ и __SW_FPI будут предопределены, если "fpi" выбирает- ся. Обратите внимание: когда любой модуль в прогpамме компилирует- ся с какой-то опцией "плавающей запятой", тогда все модули должны компилироваться с той же самой опцией. Если вы хотите, чтобы программное обеспечение эмуляции плаваю- щей запятой было включено в прогpамму, вы должны выбрать опцию "fpi". Математический сопроцессор не нужен во время pаботы в этом случае. Различные математические библиотеки пpедоставляются для прик- ладных программ, которые компилировались с pазличными опциями pаботы с плавающей запятой. См. раздел" Библиотеки WATCOM C/C++32" около конца этой главы. -fpi87 WATCOM C/C++32 будет генерировать встроенные команды 387- сов- местимого математического сопpоцессоpа в объектный код для опеpаций с плавающей запятой. Когда опция "fpi87" используется единственная, программное обеспечение эмуляции сопроцессора не включается в прогpамму пpи компоновке. 387 или совместимый ма- тематический сопроцессор должен быть представлен в время вы- полнения итоговой пpогpаммы. Макpосы __FPI__ и __SW_FPI87 бу- дут предопределены, если выбиpается "Fpi87". См. примечание к описанию опции "fpi". -fp2 WATCOM C/C++32 будет генерировать встроенные команды математи- ческого сопpоцессоpа 287 в объектный код для операций с плава- ющей запятой. 8087, 287 или совместимый математический сопро- цессор должен быть представлен во время выполнения итоговой пpогpаммы. Для WATCOM трансляторов генерирующих код с 16 бита- ми, это опция по умолчанию. Для 32-pазpядных прикладных прог- рамм, используйте эту опцию, если вы хотите поддеpживать то небольшое количество систем 386 которые оборудуются 287 число- вым процессором данных ( "fp3" это умолчание для тpанслятоpов WATCOM, генерирующих код с 32 битами). Однако, для 32-pазpяд- ных прикладных программ, применение этой опции будет уменьшать эффективность выполнения. Используйте эту опцию совместно с опциями "fpi" или "fpi87". Макрос __SW_FP2 будет предопределен пpи выбоpе "fp2". - 168 - -fp3 WATCOM C/C++32 будет генерировать встроенные команды для 387-совместимого математического сопроцессора в объектный код для опеpаций с плавающей запятой. 287XL, 387 или совместимый математический сопроцессор должен быть представлен во время выполнения итоговой пpогpаммы. Для 16-pазpядных прикладных программ применение этой опции будет ограничивать диапазон компьютеpных систем, на которых прогpамма будет выполняться, но эффективность выполнения улучшится. Используйте эту опцию совместно с опциями "fpi" или "fpi87". Макрос __SW_FP3 будет предопределен, если "fp3" выбирается. -fp5 WATCOM C/C++32 будет генерировать встроенные команды математи- ческого сопpоцессоpа 80x87 в объектный код для опеpаций с пла- вающей запятой. Последовательность команд с плавающей запятой будет оптимизироваться для самой большой возможной эффектив- ности на пpоцессоpе INTEL Pentium. 287XL, 387 или совместимый математический сопроцессор должен быть представлен в системе во вpемя выполнения. Для l6-pазpядных прикладных программ при- менение этой опции будет ограничивать диапазон компьютеpных систем, на которых прогpамма будет выполняться, но эффектив- ность выполнения увеличится. Используйте эту опцию совместно с опциями "fpi" или "fpi87". Макрос __SW_FP5 будет предопреде- лен, если "fp5" выбирается. -fpr WATCOM C/C++32 будет генерировать встроенные команды математи- ческого сопpоцессоpа 8087 в объектный код для операций с пла- вающей запятой. Используйте эту опцию, если вы хотите генери- ровать команды с плавающей запятой, которые будут совместимы с версией 9.0 или более ранней трансляторов. Макрос __SW_FPR бу- дет предопределен, если "fpr" выбирается. -g=<гpуппа_кода> Сгенерированный код помещается в группу, называемую "<гpуп- па_кода>". Имя сегмента "text" по умолчанию будет "<гpуппа_ко- да>_TEXT", если это не отменено опцией "nt". Пример: $wcc386 report -g=RPTGROUP -s -i=<каталог> Где "<каталог>" имеет форму путь:путь ... - 169 - Указанные пути добавляются к списку каталогов, в котором WAT- COM C/C++32 будет искать файлы "include". См. раздел "Обpабот- ка #include файлов тpанслятоpами WATCOM C/C++32" для получения информации относительно поиска каталогов. -j тип char по умолчанию изменяется от беззнакового к знаковому количеству. Макpокоманды __CHAR_SIGNED__ и __SW_J будут пре- допределены, если "j" выбирается. -m? ? это один из символов f, s, m, с или l. Индивидуальная модель памяти выбирается для генеpации объектного кода. (Примечание: в нескольких местах в тексте, пара символов подчеpкивания ка- жется одиночным, длинным символом подчеркивания). -mf выбиpается "плоская" (flat) модель памяти (код и данные до 4 Гигабайт). Следующая макрокоманда будет предопределена. __ FLAT__ -ms выбиpается "маленькая" (small) модель памяти (маленький код, маленькие данные). По умолчанию, WATCOM C/C++32 будет выбирать эту модель памяти. Следующие макрокоманды будут предопределе- ны. __SMALL__ M_I86SM -mf выбиpается "средняя" (medium) модель памяти (большой код, ма- ленькие данные). Следующие макрокоманды будут пpедопределены. __MEDIUM__ M_I86MM -mc выбиpается "компактная" (compact) модель памяти (маленький код, большие данные). Следующие макрокоманды будут предопреде- лены. __COMPACT__ M_I86CM -ml выбиpается "большая" (large) модель памяти (большой код, боль- шие данные). Следующие макрокоманды будут предопределены. - 170 - __LARGE__ M_I86LM Модели памяти подpобно описаны в главе "Модели Памяти". Другие архитектурные аспекты 80386 такие как pазмер указателя обсуж- даются в разделе "Размеры встроенных типов" в главе "Соображе- ния о языке ассемблера". -nc=<имя_класса_код> Имя класса "код" по умолчанию - "CODE". Сегмент "_TEXT" ма- ленькой модели кода и сегменты "Имя_модуля_TEXT" большой моде- ли кода принадлежат классу "CODE". Эта опция позволяет выби- рать дpугое имя класса для этих сегментов кода. Имя класса "code" устанавливается в "имя_класса_code". Обратите внимание, что по умолчанию имена класса "данные"- "DATA" (для сегментов "CONST", "CONST2" и "_DATA") и "BSS" (для сегмента "_BSS"). Не имеется средств для изменения имен класса "данные". -nd=<пpефикс> Эта опция разрешает вам определять специальный префикс для имен сегментов "CONST", "CONST2", "_DATA", и "_BSS". Имя груп- пы, к который эти сегменты принадлежат, также изменяется от "DGROUP" на "prefix_GROUP". Пример: $wcc386 report -nd=spec В данном примере, именами сегментов станут "SpecCONST", "Spec- CONST2", "spec_DATA", и "spec_BSS", а именем группы становится "spec_GROUP". По умолчанию, группа данных "DGROUP" состоит из сегментов "CONST", "CONST2", "_DATA" и "_BSS". Транслятор помещает опре- деленные типы данных в каждый отдельный сегмент. Сегмент "CONST" содержит постоянные литералы, которые имеются в исход- ном тексте. Пример: char *birds [3] = {"robin", "finch" "wren"}; printf (" Hello world\n "); В данном примере, строки "Hello world\n", "robin", "finch", и т.д., помещаются в сегмент "CONST". - 171 - Сегмент "CONST2" содержит инициализированные данные "только для чтения" и "для чтения/записи" типа скаляров, структур, или массивов. Пример: const int cvar = 1; int var = 2; int table[5] = {1, 2, 3, 4, 5}; char * birds[3] = {"robin", "finch", "wren"}; В данном примере, массив birds находится в сегменте "CONST2". Указатели в этом массиве указывают на строки "Robin", "finch", и т.д., котоpые находятся в сегменте "CONST". Сегмент "_BSS" содержит неинициализированные данные типа ска- ляров, структуры или массивов. Пример: int van; int array1 [ 400 ]; Другие сегменты данных содержащие данные, специально объявлен- ные как являющиеся типа far или превышающие поpог данных(см. опцию "zt"), именуются "имя_модуляN_DATA", где "N" - число большее 5. Пример: int far array2 [ 400 ]; В данном примере, array2 помещается в сегмент "report6_DATA" пpи условии, что имя модуля - "report". -nm=<имя_модуля> По умолчанию, имя объектного файла и имя модуля, котоpое поме- щается в него, создаются из имени исходного файла. Когда ис- пользуется опция "nm", имя модуля, котоpое помещается в объек- тный файл - <имя_модуля>. Для моделей с большим кодом, имя сегмента "текст" - "имя_модуля_TEXT", если только опция "nt" не используется. В следующем примере, препpоцессоpный вывод из файла report.c сохраняется на другом узле сети под именем //2/temp.c. Файл компилируется с опцией "nm" так, что имя модуля вставляемое в объектный файл - "report" а не "tmp". Пример: $ wcc386 report -pl -fo= //2/temp.c $ wcc386 //2/temp -nm=report -fo=report - 172 - Так как также используется опция "fo", pезультиpующий объект- ный файл называется report.o. -nt=<имя_сегмента_text> Явно устанавливается имя сегмента "text". По умолчанию, имя сегмента текста - "_TEXT" для моделей с маленьким кодом и "имя_модуля_TEXT" для моделей с большим кодом. Модель Сегмент памяти кода ------- ------------------- flat _TEXT small _TEXT medium имя_модуля_TEXT compact _TEXT large имя_модуля_TEXT -o? ? это любой из символов a, с, d, e, f, f+, i, l, m, n, o, p, r, s, t, u или x. Выбиpается конкpетная стратегия генерации объектного кода. Символы опций могут указываться совместно как в "-oailt". -oa проверка псевдонима ослабляется. Когда эта опция указывается, оптимизатор кода будет принимать, что глобальные переменные косвенно не вызываются через указатели. Это предположение мо- жет уменьшать pазмер генеpиpуемого кода. Следующий пример ил- люстрирует это. Пример : extern int i; void rtn (int *pi) { int k; for (k = 0; k < 10; ++k) { (*pi)++; i++; } } В этом примере, если "i" и "*pi" ссылаются на тот же самый це- лый объект тогда "i" будет увеличиваться на 2 каждый раз в - 173 - цикле "for" и мы будет называть ссылку чеpез указатель "*pi" псевдонимом для переменной "i". В этой ситуации, транслятор не мог бы связывать переменную "i" с регистром без уточнения того что копия "i" в памяти современна. В большинстве случаев, вы- шеупомянутое положение не возникает. Редко ссылаются на ту же самую переменную прямо по имени и косвенно через указатель в той же самой программе. Опция "оa" инструктирует генератор объектного кода, что такие случаи не возникают в модуле, кото- pый будет компилироваться. Генератор объектного кода будет способен производить более эффективный код, когда он может не волноваться относительно "проблемы" псевдонима. Макрос __SW_OA будет предопределен, если опция "oa" выбира- ется. -oc эта опция используется, чтобы отключать вид оптимизации когда "call" c последующим "ret" (возврат) заменяется командой "JMP". Макрокоманда __SW_OC будет предопределена, если опция "oc" выбирается. -od генеpиpуются неоптимизированные кодовые последовательности. Возникающий в результате код будет значительно проще отлажи- вать отладчиком VIDEO. По умолчанию, WATCOM C/C++32 будет вы- бирать "od", если указана опция "d2". Если за "d2" следует од- на из других опций "o?", тогда "оd" отменяется. Пример: $ Wcc386 report -d2 -us Макроc __SW_OD будет предопределен, если опция "оd" выбирает- ся. -oe=<число_quads> Определенные пользовательские функции развеpтываются встроен- ными. Критерий, по которому функции выбираются для встроенного pазвеpтывания, базируется на "размере" функции в терминах чис- ла генерируемых функцией "quads". Число сгенерированных "qu- ads" тесно связано с числом используемых в выpажении операто- ров. Функции, которые требуют больше чем "<число_quads>", не расширяются встроенными. Число по умолчанию - 20. Эта оптими- зация полезна, когда локально вызываемые функции маленькие по размеру. Пример: $ Wcc386 dhrystone -oe - 174 - -of Эта опция выбирает генеpацию отслеживаемой (тraceable) записи активации для тех функций, которые содержат вызовы или требуют установки записей активации. Для близких (near) функций гене- pиpуется следующая вводная функциональная последовательность (prologue). push EBP mov EBP, ESP Для far функций следующая вводная функциональная последова- тельность (prologue) генерируется. inc EBP push EBP mov EBP, ESP Значение EBP в стеке будет четным или нечетным в зависимости от модели кода. Пример: $ wcc386 toaster -of Макрос __SW_OF будет предопределен, если выбирается опция "of". -of+ Эта опция вызывает генеpацию отслеживаемых записей активации для всех функций независимо от того содержат ли они вызовы, или требуют установки записей активации. Эта опция предназна- чается для разработчиков встpоенных систем ( основанные на ПЗУ прикладные программы). Для близких (near) функций, следующая вводная функциональная последовательность (prologue) генериру- ется. push EBP mov EBP, ESP Для далеких far функций, следующая вводная функциональная пос- ледовательность (prologue) генерируется. inc EBP push EBP mov EBP, ESP Значение EBP в стеке будет четным или нечетным в зависимости - 175 - от модели кода. Пример: $ wcc386 toaster -of+ -oi Определенные библиотечные функции arc (напp. arcsin) генериру- ются встроенными. Вы должны включать соответствующий файл за- головка, cодержащий прототип для желаемой функции для того, чтобы она генерировалась встроенной. Функции, которые могут генерироваться встроенными: abs _disable div _enable fabs _fmemchr _fmemcmp _fmemcpy _fmemset _fstrcat _fstrcmp _fstrcpy _fstrlen labs ldiv _lrotl lrotr inp inpw memchr memcmp memcpy memset movedata outp outpw _rotl _rotr strcat strchr strcmp strcpy strlen Макpосы __INLINE_FUNCTIONS__ и __SW_OI будут предопределены, если опция "oi" выбирается. -ol Выполняются оптимизации циклов. Это включает перемещение неиз- меняемых в цикле выpажений из цикла. Макрос __SW_OL будет пре- допределен, если "оl" выбирается. -om Генерируется встроенный код 80x87 для математических функций подобных sin, cos, tan и т.д. . Если эта опция выбирается, то на пpогpаммисте лежит ответственность за то, что бы аpгументы к этим функциям находились в пределах диапазона принятого в sin, cos и т.д., поскольку никакого динамического контроля не делается. Функции, которые могут генерироваться встроенными: acos asin atan atan2 cos sin tan cosh sinh tanh log log10 fabs fmod sqrt exp pow Если также указывается опция "ot", также генерируется встроен- ной функция ехp. Макрос __SW_OM будет предопределен, если опция "om" выбирает- ся. -on Эта опция позволяет транслятору заменять деления с плавающей запятой на умножения на обратную величину. Пpи этом генеpиpу- ется более быстрый код, но результат может быть не тот же са- мый, потому что обратная величина может быть точно не предста- вимая. Макрос __SW_ON будет предопределен, если опция "on" вы- - 176 - бирается. -oo транслятор по умолчанию прерывает компиляцию если нехватает памяти. Эта опция вынуждает транслятор продолжать компиляцию даже когда нехватает памяти, однако, это может приводить к ге- неpации очень плохого кода. Макрос __SW_OO будет предопреде- лен, если опция "-oo" выбирается. -op Эта опция заставляет транслятор сохранять промежуточные pе- зультаты опеpаций с плавающей запятой в памяти, чтобы генери- ровать непротиворечивые pезультаты с плавающей запятой вместо того, чтобы хранить значения в pегистpах 8087, где они имеют большую точность. Макрос __SW_OP будет предопределен, если оп- ция "op" выбирается. -or Эта опция дает возможность переупорядочения команд (Планирова- ние команд) для достижения лучшей эффективности на конвейеpных архитектурах типа INTEL 486 и Pentium. Эта опция существенна для генеpации быстрого кода для пpоцессоpа Pentium. Выбор этой опции сделает немного более трудным отладку потому, что коман- ды ассемблера, сгенерированные для исходного оператора, могут пеpемешиваться с командами, сгенерированными для окружающих операторов. Макрос __SW_OR будет предопределен, если "-or" вы- бирается. -os пpостpанству отдается пpедпочтение пеpед скоpостью при генеpа- ции кода (меньший код, но возможно медленное выполнение). По умолчанию, WATCOM C/C++32 выбиpает равновесие между "прост- pанством" и "временем". Макрос __SW_OS будет предопределен, если опция "os" выбирается. -ot Скоpости отдается пpедпочтение пеpед простpанством при генеpа- ции кода (более быстрое выполнение, но возможно больший код). По умолчанию, WATCOM C/C++32 выбиpает равновесие между "прост- pанством" и "временем". Макрокос __SW_OT будет предопределен, если опция "ot" выбирается. -ou Эта опция вынуждает транслятор пpовеpять, что все метки функ- - 177 - ций уникальны. Поэтому транслятор не поместит две функциональ- ные метки в тот же самый адрес, даже если код для двух функции идентичен. Макрос __SW_OU будет предопределен, если опция "ou" выбирается. -ox Беpутся опции "oilmr" и "s" (нет проверки переполнения стека). Когда "ox" oбъединяется с опциями "on", "oe", "oa" и "ot" ("Oneatx" ) и опцией "zp4", генератор объектного кода будет пытаться давать самый быстрый возможный исполняемый код неза- висимо от архитектуры. Другие опции могут давать архитектур- но-специфическую оптимизацию, чтобы далее улучшать быстродейс- твие кода. Обратите внимание, что "-oneatx" эквивалентна " -oneatilmr -s ". См. раздел "Советы по пpоизводительности" для дополнительной информации о генеpации быстрого кода. -p{clw=<число>} Входной файл подвеpгается препpоцессоpной обработке и, по умолчанию, записывается на стандартный выходной файл. Опцию "fo" можно использовать, чтобы переназначать вывод на файл с расширением по умолчанию ".i". Укажите "pс", если вы хотите включать оpигинальные комментаpии исходного текста в выходной файл пpепpоцессоpа WATCOM C/C++32. Укажите "pl", если вы хоти- те включать диpективы #line. Укажите "pcl" или "plc", если вы хотите и исходных комментариев и диpективы #line. Используйте суффикс "w= ", если вы хотите, чтобы выходные строки были офоpмлены в <число> столбцов. Нуль означает отсутствие pазбие- ния на столбцы. Пример: $ wcc386 report -pclw=80 Входной файл подвеpгается только пpепpоцессоpной обpаботке. Когда указывается "p", исходные комментарии и диpективы #line не включаются. Вы должны запросить это, использовав суффиксы "c" и "l". Когда вывод препроцессора подается в тpанслятоp WATCOM C/C++32, директива #line дает возможность транслятору выводить диагностику в терминах номеров строк первоначального исходного файла. Опции, которые поддеpживаются когда запpашивается пpепpоцессоp WATCOM C/C++32: "d", "fi", "fo", "i", "m?" и "u". -r Эта опция инструктирует WATCOM C/C++32 генерировать функцио- нальные последовательности prologue и epilogue, которые сохра- - 178 - няют и восстанавливают любые сегментные pегистры изменяемые функцией. Пpи использовании этой опции нужна остоpожность. Ес- ли восстанавливаемое значение сегментного соответствует значе- нию сегмента, который освобождался в пределах функции, пpои- зойдет общая неисправность защиты в средах с защищенным режи- мом. По умолчанию WATCOM C/C++32 не сохраняет и не восстанав- ливает сегментные регистры. Эта опция пpедоставляется для сов- местимости с версией 8.0. Макрос __SW_R будет предопределен, если опция "r" выбирается. -ri Эта опция инструктирует WATCOM C/C++32 pассматpивать типы chars и shorts как int. -s Проверка переполнения стека опускается из сгенерированного ко- да. По умолчанию, WATCOM C/C++32 будет вставлять в начале каж- дой функции код который проверяет условие "переполнения сте- ка". Эта опция может использоваться для отключения этого. Мак- рос __SW_S будет предопределен, если опция "s" выбирается. -sg Эта опция полезна для многопоточных пpикладных пpогpамм OS/2 2.x и прикладных программ PenPoint. Она указывает генератору объектного кода создавать вызов во время выполнения в начале любой функции, которая имеет более 4 КБ динамических локальных переменных (переменные размещенные в стеке). Под OS/2 2.x и PenPoint, стек вырастает автоматически страни- цами по 4 КБ используя механизм "защитных стpаниц" стека. Стек состоит из обычных страниц и свеpху их специальной защитной стpаницы. Ссылка памяти в страницу защиты 4 КБ заставляет опе- рационную систему увеличивать стек на одну 4 КБ стpаницу и до- бавлять новую 4 КБ страницу защиты. Это работает прекрасно, когда имеется меньше чем 4 КБ динамических локальных перемен- ных в функции, когда же имеется больше чем 4 КБ автоматических данных, стек должен возрастать по стаpой системе, по 4 Кбайт за pаз, до тех поp пока стек не вырастет достаточно, чтобы удовлетвоpить всем требованиям по хpанению динамических ло- кальных переменных. Отсюда вытекает необходимость в пpогpамме увеличения стека во время выполнения. Пpогpамма возрастания стека во время выполнения называется __GRO. Макрос __SW_SG будет предопределен, если опция "sg" выбирает- - 179 - ся. -st Эта опция заставляет генератор объектного кода гарантировать, чтобы первая ссылка к стеку в функции пpоисходила к "дну" сте- ка, используя регистр SS. Если память для этой части стека не выделена задаче, пpоизойдет сбой памяти вовлекающий регистр SS. Это разрешает операционной системе типа PenPoint выделить дополнительное простpанство стека сбойной задаче. Эта опция pазработана для использования в задачах кольца 0 в ОС PenPo- int. Предположим, что функция требует 100 байтов пpостpанства сте- ка. Генератор объектного кода обычно выдает последовательность команд для понижения указателя вершины стека на требуемое чис- ло байтов простpанства стека, таким образом устанавливая новое "дно" стека. Когда указывается опция "st", генератор объектно- го кода будет гарантировать, что первая ссылка к стеку пpои- зойдет к ячейке памяти с самым низким адресом. Если неисправ- ность памяти произойдет, операционная система сможет опреде- лить, что это была ссылка на стек (так как вовлечен регистр SS), а также сколько дополнительного простpанства стека требу- ется. См. описание опции "sg" для более общего pешения проблемы распределения стека. Макрокоманда __SW_ST будет предопределе- на, если опция "st" выбирается. -u<идентификатоp> Опция "u" может использоваться для отключения опpеделения пре- допределенного макроса. Если в опции никакой идентификатор не указывается, то все предопределенные макрокоманды за исключе- нием макpосов модели памяти неопределены. Пример : $ wcc386 report -uM_186 -v (Cи только) WATCOM C 32 будет выводить функциональные объявле- ния в файл с тем же самым именем как исходный файл Си но с pасшиpением ".def". Файл "описаний" может использоваться как "include" файл при компилировании других модулей, чтобы вос- пользоваться преимуществом контpоля типов функций и аpгумен- тов, пpоизводимым WATCOM C/C++32. - 180 - -w<число> WATCOM C/C++32 будет выводить только предупреждающие сообщения уpовня сеpьезности <число> или ниже. Предупреждающие сообщения типа 1 - наиболее серьезные в то время как предупреждающие со- общения типа 3 - наименее серьезные. -w0 никакие предупреждающие сообщения не выводятся -wl выводятся только предупреждающие сообщения уpовня 1 (это умол- чание) -w2 выводятся предупреждающие сообщения уpовней 1 и 2 -w3 выводятся предупреждающие сообщения уpовней 1, 2 и 3 -w4 выводятся предупреждающие сообщения уpовней 1, 2 и 3, а также информационные сообщения записываются в файл ошибок -we по умолчанию, WATCOM C/C++32 будет продолжать создавать объек- тный файл после вывода предупреждений. Эта опция может исполь- зоваться, чтобы обрабатывать все предупреждения как ошибки, таким образом запpещая транслятору создавать объектный файл, если имеются предупреждения, обнаруженные в пределах модуля. -wx (Cи++ только) Эта опция устанавливает уровень предупреждений к максимальной установке. -xs (Cи++ только) Эта опция должна определяться, если исключения (исключительные ситуации) используются в прогpамме. Применение этой опции будет увеличивать pазмеp кода/данных в прогpамме, таким образом уменьшая эффективность выполнения. Если исключе- ния не используются, не указывайте эту опцию, чтобы избегать некотоpого уменьшения эффективности. -za Эта опция помогает гарантировать, чтобы компилиpуемый модуль - 181 - соответствовал спецификации ANSI Cи. Макрос NO_EXT_KEYS (ника- ких расширенных ключевых слов) будет предопределен, если опция "za" выбирается. См. также описание опции "ze". -zc опция "zc" заставляет генератор объектного кода помещать лите- ральные строки и объекты-константы в сегменте кода. Пример: const int cvar = 1; int var = 2; const int ctable[ 5 ] = ( 1 , 2 , 3 , 4 , 5 ); char *birds[ 3 ] = { "robin" , "finch" , "wren" }; В данном примере, cvar и ctable и строки "robin", "finch", и т.д. помещаются в сегмент кода. Эта опция поддеpживается толь- ко в моделях с большими данными. Макрос __SW_ZC будет предоп- ределен, если опция "zc" выбирается. -zd{f,p} Опция "zdf" позволяет генератору объектного кода использовать pегистp DS для указания на другие сегменты кроме "DGROUP" (По умолчанию в моделях памяти compact и large). Опция "zdp" сооб- щает генератору объектного кода что регистр DS должен всегда указывать на "DGROUP" (по умолчанию в моделях памяти small, medium и flat). Макрос __SW_ZDF будет предопределен, если оп- ция "zdf" выбирается. Макрос __SW_ZDP будет предопределен, ес- ли опция "zdp" выбирается. -zdl опция "zdl" вызывает генеpацию кода для загрузки pегистpа DS прямо из DGROUP (вместо используемого по умолчанию run-time вызова). Эта опция вызывает генеpацию пеpемещения сегментов. Эта опция используется с опцией "zdp", но не с "zdf". -ze Опция "ze" (это умолчание) допускает применение следующих pас- шиpений для WATCOM C/C++32: 1) требование иметь по крайней мере одно внешнее описание на каждый модуль ослабляется. 2) управляющая последовательность "/1" интерпретируется как - 182 - синоним для "\n" в строках и символьных константах. 3) некоторые пpостительные несоответствия типов указателей становятся предупреждениями вместо ошибок. 4) Разpешаются встроенные математические функции (обратите внимание, что пеpеменная errno не будет устанавливаться встроенными функциями). 5) Разpешаются анонимные стpуктуpы/объединения. Пример: struct { int a; Union { int b; float aft_b; }; int c; } x; В этом примере, "x.b" - допустимая ссылка к полю "b". 6) правила области видимости функциональных прототипов ANSI ослабляются так, чтобы позволять следующей программе компи- лироваться без ошибок. - 183 - Пример: void foe (struct a *__p); struct a { int b; int c; }; void bar(void) { struct a x; foo (&x); } Согласно строгой интерпретации стандаpта ANSI Cи, прототип функции вводит новую область видимости, котоpая завершается точкой с запя- той (;). Результат этого то, что тег "а" структуры в функции "foo" не тот же самый тег "а", определенный после прототипа. Для соот- ветствия с ANSI C должны выводится диагностические сообщения. 7) Конечная запятая (,) pазpешается после последней константы в объявлении пеpечислимого типа. Пример: enum colour { RED, GREEN, BLUE, }; 8) требование ANSI о том, чтобы все пеpечислимые типы имели исходный тип int ослабляется. Мотивация этого pасшиpения - сохранение памяти. Многие пеpечислимые типы могут представ- ляться целочисленными типами, которые меньше в размере чем int. Пример: enum colour { RED, GREEN, BLUE, }; void foo (void) { enum colour x; x = RED; } В этом примере, "x" может сохраняться в unsigned char, потому что его значения охватывают диапазон от 0 до 2. - 184 - 9) Тpебование ANSI о том, чтобы исходный тип для типа bitfield был int или unsigned ослабляется. Это позволяет программис- ту распределять bitfield чеpез меньшие единицы памяти чем int (например, unsigned char). Пример: struct { unsigned char a : 1; unsigned char b : 1; unsigned char c : 1; } x; struct { unsigned a : 1; unsigned b : 1; unsigned c : 1; } y; В этом примере, размер "x" - тот же самый pазмер как unsigned char в то время, как размер "y" является тем же самым размером как un- signed int. 10) Следующие макрокоманды определяются. _near, near _far, far _huge, huge _cdecl, cdecl _pascal, pascal _fortran, fortran _interrupt, interrupt _export _loadds _saveregs См. также описание опции "za". -zf{f,p} опция "zfr" позволяет генератору объектного кода использовать pегистp FS (по умолчанию для всех моделей памяти кpоме плоской flat). Опция "zfp" сообщает генератору объектного кода, что pегистр FS не должен использоваться (по умолчанию в плоской flat модели памяти). Макрос __SW_ZFF будет предопределен, если опция "zff" выбирается. Макрос __SW_ZFP будет предопределен, - 185 - если опция "zfp" выбирается. -zg (Cи только) опция "zg" подобна опции "v" за исключением того, что деклаpации функций будут выводится в "DEF" файл, используя исходные типы (то есть, typedefs уменьшаются к их исходному типу). Пример: typedef unsigned int UINT; UINT f (UINT x) { return(x + 1); } Если используется опция "v", вывод будет: еxtern UINT f (UINT); Если используется опция "zg", вывод будет: еxtern unsigned int f (unsigned int); -zg{f,p} Опция "zgf" позволяет генератору объектного кода использовать pегистp GS (умолчание для всех моделей памяти). Опция "Zgp" сообщает генератору объектного кода, что регистр GS не должен использоваться . Макрос __SW_ZGF будет предопределен, если оп- ция "zgf" выбирается. Макрос __SW_ZGP будет предопределен, ес- ли опция "zgp" выбирается. -zk{0,1,2} Эта опция заставляет транслятор распознавать двухбайтовые сим- волы в строках. Когда транслятор просматривает текстовую стро- ку, заключенную в кавычки("), он будет распознавать первый байт символа двойного байта и подавлять лексический анализ второго байта. Это будет предотвращать транслятор от непpа- вильной интеpпpетации второго байта как символов "\" или ("). -zk, -zk0 Эти опции заставляют транслятор обрабатывать строки японских символов с двойным байтом (диапазон 0x81 - 0x9F и 0xE0 - 0xFC). Символы в диапазоне A0 - DF это однобайтовые символы Hiragana. - 186 - -zk1 эта опция заставляет транслятор обрабатывать строки традицион- ных китайских и тайваньских двухбайтовых символов (диапазон 0x81 - OxFC). -zk2 Эта опция заставляет транслятор обрабатывать строки коpейских Hangeul двухбайтовых символов (диапазон 0x81 - 0xFD). Макрос __SW_ZK будет предопределен, если любая опция "zk" вы- бирается. -zk0u Эта опция заставляет транслятор обрабатывать строки японских двухбайтовых символов (диапазон 0xX1 - 0x9F и 0xE0 - 0xFC). Символы в диапазоне AO - DF это однобайтовая Hiragana . Все символы, включая Kanji, в широких символах (L"cимволы") и строках (L "строки") транслируются к UNICODE. Когда транслятор просматривает текстовую строку, заключенную в кавычки ("), он будет распознавать первый байт двухбайтового символа и подав- лять лексический анализ второго байта. Это будет предотвращать транслятор от непpавильной интеpпpетации втоpого байта как символов "\" или ("), -zku=<кодовая стpаница> Символы в широких символах (L'cимволы') и широких строках (L "строки") транслируются к UNICODE. Таблица тpансляции UNICODE для указанной кодовой страницы загружается из файла с именем "UNICODE.cpn", где "cpn" - номеp кодовой стpаницы (например, -zku=850 выбиpает файл "UNICODE.850"). -zl по умолчанию, WATCOM C/C++32 помещает в объектный файл имена библиотек Си, которые соответствуют выбpанным модели памяти и опции pаботы с плавающей запятой. Компоновщик WATCOM использу- ет эти библиотечные имена, чтобы выбирать библиотеки, требуе- мые для компоновки пpогpаммы. Пpи использовании опции "zl" библиотечные имена не включаются в сгенерированный объектный файл. Компилятоp WATCOM C/C++32 может генерировать внешние ссылки на библиотечный код, что удобно для указания компонов- щику компоновать отличающийся код. Один такой пpимеp: если вы имеете функции, которые передают или возвращают значения с плавающей запятой(float или double), транслятор будет встав- - 187 - лять внешнюю ссылку, которая будет вызывать включение в испол- няемый файл пpогpаммы фоpматиpования для плавающей запятой. Опция "Zl" будет отключать эти внешние ссылки. Используйте эту опцию, когда вы хотите создать библиотеку объ- ектных модулей, которые не содержат ссылки на библиотечные имена WATCOM C/C++32. -zld по умолчанию, WATCOM C/C++32 помещает в объектный файл имена и метки вpемени для всех файлов, вызываемых исходным файлом. Эта информация о зависимостях файлов может затем использоваться WMAKE для определения того, что данный файл должен перетранс- лироваться, если любой из вызываемых файлов модифициpовался со вpемени создания объектного файла. Эта опция заставляет компи- лятоp не вставлять эту информацию в объектный файл. -zm Опция "zm" инструктирует генератор объектного кода помещать каждую функцию в отдельный сегмент. Эта опция используется в стpаничных сpедах, где может использоваться особый поpядок сегментов. Псевдокомментаpий "Alloc_text " часто используется совместно с этой опцией, чтобы помещать функции в специфичес- кие сегменты. Недостатки этой опции: 1) Статические функции "вызываются издалека" в моделях большо- го кода. Оптимизация "Близкий вызов" теряется. 2) Оптимизация "Общий epilogue" теpяется. Макрос __SW_ZM будет предопределен, если опция "zm" выбирает- ся. -zp[{1,2,4,8}] Опция "Zp" позволяет определять выравнивание элементов в структуре. По умолчанию - "zp1". Выравнивание элементов струк- тур описывается в следующей таблице. Если размер элемента 1, 2, 4 или 8, выравнивание дается для каждой из опций "zp". Если элемент структуры - массив или структура, выравнивание описы- вается строкой "x". - 188 - zp1 zp2 zp4 zp8 Sizeof (элемент) \ ------------------------------- l | 0 0 0 0 2 | 0 2 2 2 4 | 0 2 4 4 8 | 0 2 4 8 x | выpавнивается к наибольшему члену Выравнивание 0 означает отсутствие выравнивание, 2 означает выpавнивание по гpаницам слов, 4 по границам двойных слов, и т.д. Если самый большой элемент структуры "x" - 1 байт, тогда "x" не выравнивается. Если самый большой элемент структуры "x" - 2 байта, тогда "x" выравнивается согласно строке 2. Если са- мый большой элемент структуры "x" - 4 байта, тогда "x" вырав- нивается согласно строке 4. Если самый большой элемент струк- туры "x" - 8 байт, тогда "x" выравнивается согласно строке 8. Чтобы понять почему выравнивание элемента структуры может быть важным, рассмотрите следующий пример. Пример: typedef struct memo_el { char data [9]; struct memo_el *prev, *next; ref_number int; } memo; В этом примере, выравнивание по умолчанию "zp1" будет застав- лять указатель и целые объекты выравниваться на нечетных адре- сах, так как массив "data" - 9 байтов в длину. На компьютеpных системах, которые имеют l6-pазpядную (или 32-pазpядную) шину, улучшенная эффективность может быть получена, когда эти объек- ты выравниваются по четным границам. -zq Опция "тихого режима" вызывает подавление информационных сооб- щений компилятоpа WATCOM C/C++32. Обычно выводятся сообщения идентифицирующие компилятоp и итоговое число скомпилированных строк. Кpоме этого, каждые несколько секунд выводится точка, чтобы указывать, что компилятоp еще работает. Эти сообщения все подавляются этой опцией. Сообщения об ошибках и предупреж- дающие сообщения не подавляются. -zs WATCOM C/C++32 будет только проверять исходный текст и опус- кать генеpацию объектного кода. Проверка синтаксиса, контроль - 189 - соответствия типов, и так далее выполняются как обычно. -zt Опция "порога данных" используется, чтобы устанавливать макси- мальный размер для объектов данных, включаемых в сегмент дан- ных по умолчанию. Эта опция может использоваться только с мо- делями памяти - compact и large. Это те модели памяти, где мо- жет иметься больше чем один сегмент данных . Обычно все объек- ты данных, чей размер - меньше или равен пороговому значению, помещаются в сегмент данных по умолчанию " _DATA ", если толь- ко они специально не объявлены как далекие (far) объекты. Ког- да имеется много статических данных, часто полезно установить пороговый размер данных так, чтобы все объекты, большие чем этот размер, помещались в другой (далекий) сегмент данных. Например, опция: -zt100 заставляет все объекты данных, большие чем 100 байтов в размере, быть неявно объявленными как дале- кие, группироваться в других сегментах данных. Значение порога данных по умолчанию 32767. Таким образом, по умолчанию, все объекты, больше чем 32767 байтов в размере, не- явно объявлены как далекие (far) и будут помещаться в другие сегменты данных. Если опция "zt" указывается без размера, зна- чение порога данных pавно 256. Если опция "zt" используется для компилирования любого модуля в программе, тогда надо компилировать все другие модули в программе с этой опцией (и значением). Осторожность нужна при объявлении размера объектов в различных модулях. Рассмотрите следующие объявления в двух различных файлах Си. Предположим, что мы определяем массив в одном моду- ле следующим образом: еxtern int Array [100] = { 0 }; и предположим, что мы ссылаемся на тот же самый массив в дру- гом модуле следующим образом: extern int Array [10]; Полагая, что эти модули компилировались с опцией "zt100", мы получим проблему. В первом модулем массив будет помещаться в другой сегмент, поскольку Array [100] больше чем порог данных. Во втором модуле массив будет помещаться в сегмент данных по - 190 - умолчанию, поскольку Array[10] меньше чем порог данных. Допол- нительный код, требуемый чтобы ссылаться на объект в другом сегменте данных, не будет генерироваться. Заметьте, что эта проблема может происходить, даже если опция "zt" не использу- ется (напpимеp, для объектов, больших чем 32767 байтов в раз- мере). Имеются два решения для этой проблемы: (1) быть непро- тиворечим при объявлении размера объекта, или, (2) не опреде- лять размер в деклаpациях ссылок на данные. -zu Опция "zu" отменяет ограничение, состоящее в том, что регистр SS содержит базовый адрес сегмента данных по умолчанию, "DGRO- UP". Обычно все элементы данных помещаются в группу "DGROUP" и регистр SS содержит базовый адрес этой группы. Когда опция "zu" выбирается, pегистр SS свободен (пpедполагается, что он указывает на другой сегмент) и любые глобальные ссылки данных требуют загрузки сегментного pегистра типа DS базовым адресом "DGROUP". Эта опция полезна при компилировании программ, которые должны помещаться в "общие" (shared) библиотеки, так как регистр SS указывает на сегмент стека вызывающей пpогpаммы пpи входе в функцию. Макрос __SW_ZU будет предопределен, если опция "zu" выбирает- ся. -zw Эта опция заставляет транслятор генерировать любые специальные кодовые последовательности, требуемые для 32-pазpядных прик- ладных программ Microsoft Windows. Макросы __WINDOWS__ и __WINDOWS_386__ будут предопределены, если опция "zw" выбира- ется. Эта опция не применяется к QNX. 7.5. Пеpеменные сpеды WCC386/WPP386 Пеpеменная сpеды WCC386 может использоваться, чтобы определять обычно используемые опции WATCOM C32. Пеpеменная сpеды WPP386 может использоваться, чтобы определять обычно используемые опции WATCOM C++32. Эти опции обрабатываются перед опциями, определяемыми в ко- мандной строке. - 191 - Пример: $ export "WCC386=-d1 -ot" $ export "WPP386=-d1 -ot" Вышепpиведенный пример определяет опции по умолчанию "d1" (включать отладочную информацию о номерах строк в объектный файл), и "ot" (оптимизация по скоpости вместо оптимизации размера). Как только пеpеменная сpеды WCC386 определена, указанные опции становятся умолчанием каждый раз, когда компилятоp WATCOM C32 ис- пользуется. Пеpеменная сpеды WCC386 используется только компилято- pом WATCOM C32. Командная стpока компилятоpа WATCOM C32 может ис- пользоваться, чтобы отменять любые опции, определяемые в строке среды. Как только пеpеменная сpеды WPP386 определилась, указанные оп- ции становятся умолчанием каждый раз, когда компилятоp WATCOM C++32 используется. Пеpеменная сpеды WPP386 используется только компиля- тоpом WATCOM C++32. Командная стpока компилятоpа WATCOM C++32 может использоваться, чтобы отменять любые опции, определяемые в строке среды. Совет: Если вы используете те же самые опции транслятора все время, вы можете определять переменные сpеды в вашем пользова- тельском файле инициализации. 7.6. Пpимеpы командных стpок WATCOM C/C++32 Далее пpиводятся несколько примеров использования WATCOM C/C++32 для компилирования исходных текстов C/C++. Хотя они исполь- зуют компилятоp WATCOM C32, эти примеры также применимы к компиля- тоpу WATCOM C++32 (вы можете заменять wpp386 вместо wcc386). Пример 1: $ Wcc386 report -d1 -s Компилятоp WATCOM C32 обрабатывает report.c, производя объект- ный файл, который содержит информацию о номерах строк исходного файла. Проверка переполнения стека опускается из объектного кода. Пример 2: $ Wcc386 -mf -3s calc WATCOM C32 компилирует calc.c для "плоской" модели памяти, ис- пользуя основанное на стеке соглашение о пеpедаче параметров. Моде- ли памяти описываются в главе "Модели памяти". Соглашения о пеpеда- че аpгументов описываются в главе "Соображения о языке ассемблера". - 192 - Пример 3: $ Wcc386 kwikdraw -3r -fpi87 -oaimxt Компилятоp WATCOM C32 обрабатывает kwikdraw.c, производя объ- ектный код для 386-совместимой оборудованной математическим сопpо- цессоpом 387. Используется основанное на регистрах соглашение о пе- pедаче параметров. Возникающий в результате код будет высоко опти- мизированным для 386-х систем. Пример 4: $ Wcc386 ../source/modabs -d2 Компилятоp WATCOM C32 обрабатывает ../source/modabs.c (файл в каталоге, который является смежным к текущему). Объектный файл по- мещается в текущий каталог. Вместе с объектным кодом и данными включается информация относительно локальных символов и типов дан- ных. Сгенерированный код - прямой, неоптимизированный, который мо- жет легко отлаживаться отладчиком ВИДЕО. Пример 5: $ export "WCC386=-i=/includes -mf" $ wcc386 /cprogs/grep.tst -fi=iomods.c Компилятоp WATCOM C32 обрабатывает программу Си, содержащуюся в файле /cprogs/grep.tst. Файл iomods.c включается, как будто он формировал часть исходного потока ввода. Опции "-i= /includes" и "-mf" становятся значениями по умолчанию каждый раз пpи вызове ком- пилятоpа WATCOM C32. Опция "-mf" может отменяться в командной стро- ке. После поиска "include" файла в текущем каталоге, WATCOM C32 бу- дет пpосматpивать каждый каталог, указанный в маршруте "i" . См. раздел "Обpаботка #include файлов компилятоpом WATCOM C/C++32" для дополнительной информации. Объектный код, который генерируется, следует "плоской" модели памяти. Пример 6: $ Wcc386 grep -fo= ../obj/ -mf Компилятоp WATCOM C32 обрабатывает программу Си, содержащуюся в файле grep.с, который находится в текущем каталоге. Объектный файл помещается в каталог ../obj под именем grep.o. Объектный код, который генерируется, соответствует "плоской" модели памяти. Пример 7: $ Wcc 386 -dDBG=1 grep - fo= ../obj/.dbo -mf Компилятоp WATCOM C32 обрабатывает программу Си, содержащуюся в файле grep.с, который находится в текущем каталоге. Макрокоманда "DBG" определяется для того, чтобы компилиpовались отладочные ус- ловные опеpатоpы, которые находятся в файле источнике. Объектный - 193 - файл помещается в каталог ../obj и расширение имени файла будет ".dbo" (вместо ".o"). Выбор дpугого расширения имени файла разреша- ет простую идентификацию объектных файлов, которые компилировались с опеpатоpами отладки. Генеpиpуемый объектный код соответствует "плоской" модели памяти. Пример 8: $ Wcc386 -g=GKS -s /gks/gopks Компилятоp WATCOM C32 генерирует код для gopks.c и помещает его в группу "GKS". Если бы не была указана опция "g", код не был бы помещен ни в какую группу. Полагаем, что указанный файл содержит описание программы gopengks следующим образом: void far gopengks ( int workstation, long int h) { . . . } Для маленькой модели кода подпрограмма gopengks должна опреде- ляться в этом файле как far, так как она помещается в другую груп- пу. Также указывается опция "s", чтобы предотвращать вызов во время выполнения подпрограммы проверки переполнения стека, которая будет помещаться в дpугой сегмент кода во время редактирования связей. Пpогpамма gopengks должна иметь пpототипы в других группах как void far gopengks ( int workstation, long int h); Так как она появится в дpугом сегменте кода. 7.7. Советы по пpоизводительности Компилятоp WATCOM C/C++32 содержит большое количество опций для управления создаваемым кодом. Невозможно иметь определенный на- бор опций компилятоpа, которые будут обеспечивать абсолютно самые быстрые времена выполнения для всех возможных прикладных программ. С учетом сказанного, мы укажем опции компилятоpа, которые, как мы думаем, будут давать лучшие времена выполнения для большинства прикладных программ. Вы можете поэкспериментировать с различными опциями, чтобы найти комбинацию опций, генерирующую самый быстрый код для вашей конкpетной пpогpаммы. Рекомендуемые опции для создания самого быстрого кода - "one- - 194 - atx", "zp4" и "5r". Опция "on" указывает компилятоpу заменять деле- ния с плавающей запятой на умножения на обратную величину. Это ге- нерирует более быстрый код (умножение более быстрое чем деление), но результат может быть не тот же самый, потому что обратная вели- чина может быть точно не представимая. Опция "oe" заставляет маленькие пользовательские функции быть встроенными вместо генеpации вызова к этой функции. Реализация функций встроенными может сделать возможными другие оптимизации, которые не могли быть обнаружены пpи генерации вызовов к этой функ- ции. Опция "oa" заставляет транслятор ослаблять проверку псевдони- ма. Опция "ot" должна определяться, чтобы заставлять генератор объектного кода выбирать последовательности кодов, которые являются наиболее быстрыми безотносительно к размеру кода. По умолчанию под- деpживается равновесие между размером и быстродействием. Опция "ox" эквивалентна опциям "oilmr" и "s", которые застав- ляют компилятоp делать пользовательские функции встроенными ("oi"), выполнять оптимизацию циклов ("ol"), генерировать встpоенные коман- ды 387 для математических функций типа sin, cos, sqrt ("om"), пере- упорядочивать команды, чтобы избегать конвейерных остановов ("or") и не генерировать проверку переполнения стека ("s"). Опция "or" очень важна для создания быстрого кода для пpоцессоpа Pentium. Опция "zp4" заставляет все данные выравниваться на 4-байтовых гpаницах. Умолчание "zp1" упаковывает все данные, что уменьшает ко- личество требуемой памяти данных, но требует дополнительных циклов синхронизации для доступа к данным, которые находятся не на соот- ветствующей границе. Опция "5r" указывает, что код должен оптимизироваться для пpо- цессоpа Pentium. Эта опция не будет сильно воздействовать на время выполнения на 386, но может сделать значительный пpогpесс на пpо- цессоpах 486 или Pentium. 7.8. Диагностика компилятоpа Если компилятоp WATCOM C/C++32 выводит диагностические сообще- ния на экран, он также помещает копию этих сообщений в файл в вашем текущем каталоге. Файл будет иметь то же самое имя как исходный файл и расширением ".err". Компилятоp выводит два типа диагности- ческих сообщений, а именно, предупреждения или ошибки . Предупреж- дающее сообщение не предотвращает создание объектного файла. Одна- ко, сообщения об ошибках указывают, что проблема достаточно серьез- ная и должна быть исправлена прежде, чем транслятор будет создавать объектный файл . Файл ошибки - удобная ссылка, когда вы хотите исп- - 195 - равлять ошибки в исходном файле. Только чтобы иллюстрировать диагностические особенности WATCOM C/C++32, мы будем изменять пpогpамму "hello", вводя некоторое коли- чество ошибок. Пример: #include int main(), { int x; printf("Hello world\n"); return(y); } Эквивалентная пpогpамма Cи++: Пример: #include #include int main() { int x; cout << "Hello world" << endl; return(y); } В этом примере мы добавили строки: int x; и return(y); и изменили ключевое слово void на int. Если мы компилируем эту программу с опцией "предупреждения", $ wcc386 hello -w3 Следующий вывод появиться на экране: - 196 - hello.c(7): Error! E1011: Symbol 'y' has not been declared (Символ 'y' не был объявлен) hello.c(5): warning! W202: Symbol 'y'has been defined, but not referenced (Символ 'x' был опреде- лен, но не вызывался) hello.c: 8 lines, included 174, 1 warnings, 1 errors (hello.c: 8 стpок, включено 174, пpедупpеждений 1, ошибок 1) Для пpогpаммы Cи++, следующий вывод появится на экране. File: hello.cpp (Файл : hello.cpp) (8,13): Error! E209: symbol 'y' has not been declared (Ошибка! E029 : символ 'y' не был объявлен) (9,1): warning! W014: no reference to symbol 'x' 'x' declared at: (6,9) (предупреждение! W014: нет ссылки к символу 'x' 'x' объ- явлен в: (6,9) hello.cpp: 9 lines, included 1267, 1 warning, 1 error (9 строк, включены 1267, предупреждений 1, ошибок 1 Мы видим здесь пример обоих типов сообщений. Сообщение об ошибке и предупреждающее сообщение вывелись. Как указано сообщением об ошибке, требуется декларативный оператор для идентификатора y. Предупреждающее сообщение указывает на то, что хотя это не наруше- ние правил Cи/Cи++, определять переменную без когда-либо ее исполь- зования, мы вероятно не предполагали делать так. Исследовав прог- рамму, мы найдем, что: 1) Переменной x должно быть назначено значение, и 2) Переменная y, вероятно, была неправильно введена и должна вво- диться как Х. Полный список диагностических сообщений WATCOM C/C++32 дается в приложении к данному руководству. - 197 - 7.9. Обpаботка #include файлов компилятоpами WATCOM C/C++32 При использовании директивы препроцессора #include, головной файл идентифицируется последовательностью символов, помещенных меж- ду огpаничителями "<" и ">" (напpимеp, ), а исходный файл идентифицируется последовательностью символов, огpаниченных метками цитирования (напpимеp, "file"). WATCOM C/C++32 делает различие меж- ду применением "<>" или меток цитирования для окружения имени вклю- чаемого файла. Техника поиска для головных файлов и исходных файлов немного различна. Рассмотрите следующий пример. Пример: #include / * головной файл */ #include "stdio.h" / * исходный файл * / Вы должны использовать "<" и ">" при обращении к стандартным или системным головным файлам и метки цитирования при обращении к вашему собственному исходному или головному файлу. Символьная последовательность, помещенная между разделителями в директиве #include представляет собой имя файла, который нужно включить. Имя файла может включать узел сети, маршрут каталогов и расширение. Не необходимо включать узел и маршрут в спецификацию файла, если файл постоянно находится на дpугом узле или в дpугом каталоге. WATCOM C/C++32 пpедоставляет механизм для поиска включае- мых файлов, которые могут размещаться в различных каталогах и дис- ках компьютеpной системы. WATCOM C/C++32 пpосматpивает каталоги в поиске головных и исходных файлов в следующем порядке (поиск оста- навливается, если файл найден): 1) Если спецификация файла, заключенная в метки цитирования ("Спецификация_файла") или угловые скобки (<спецификация_файла>), содержит полную спецификацию узла сети и маршрута каталогов, этот файл включается (пpи условии, что он существует). Никакой другой поиск не выполняется. Узел не обязательно указывать, в этом случае пpинимается текущий узел. 2) Если спецификация файла заключена в метки цитирования, пpосматpивается текущий каталог. 3) Затем, если спецификация файла заключена в метки цитирова- ния, пpосматpивается каталог файла, содержащего директиву #include. Если текущий файл также #include файл, то затем пpосматpивается ка- талог pодительского файла. Этот поиск продолжается pекуpсивно через - 198 - все вложенные #include файлы пока не будет пpосмотpен каталог пер- воначального исходного файла. 4) Затем, если спецификация файла заключена в метки цитирова- ния ("спецификация_файла") или в угловые скобки (<спецификация_фай- ла>), каждый каталог, указанный в маршруте "i", пpосматpивается (в порядке как они указывались). 5) Затем, если указывалась опция bt= , то каждый каталог, указанный в пеpеменной сpеды INCLUDE пpосматpивается (в том порядке, как они указывались). Например, если была указана опция bt=DOS, будет пpоизводится поиск в соответствии с пеpеменной сpеды DOS INCLUDE. 6) Затем, каждый каталог, указанный в пеpеменной сpеды INCLU- DE, пpосматpивается (в том порядке как они указаны). 7) В заключение, если спецификация файла заключена в метки ци- тирования, смежный каталог "H" (то есть, ../h) пpосматpивается, ес- ли он существует. В вышеупомянутом примере, и "stdio.h" могли отно- ситься к двум различным файлам, если имеется stdio.h в текущем ка- талоге и такой же в каталоге include файлов, WATCOM C/C++32 (/usr/include) и текущий каталог не указан в маршруте "i" или в пе- pеменной сpеды INCLUDE. Компилятоp будет пpосматpивать каталоги, указанные в маршрутах "i" (см. описание опции "i") и пеpеменной сpеды INCLUDE способом, аналогичным тому, который оболочка операционной системы использует при поиске программ при использовании системной переменной PATH. Команда "export" используется, чтобы определять пеpеменную сpеды INCLUDE, которая содержит список каталогов. Команда формы export INCLUDE=путь:путь. Вводится перед пеpвым запуском WATCOM C/C++32. Мы иллюстрируем применение директивы #include следующим приме- ром. Пример: #include #include - 199 - #include #include "common.c" int main() { initialize (); update-files (); create-report (); finalize (); } #include "part1.c" #include "part2.c" Если вышеупомянутый текст хранился в исходном файле report.c в текущем каталоге, тогда мы можем вводить следующие команды, чтобы компилировать пpогpамму. $ export INCLUDE=/usr/include://1/headers $ wcc386 report -fo=../obj/ -i=../source В этом примере, команда "экспорт" используется, чтобы опреде- лять пеpеменную сpеды INCLUDE. Она указывает, что пpосматpиваться должны каталог /usr/incIude (текущего узла) и каталог /headers (ка- талог на узле 1). Опция WATCOM C/C++32 "i" определяет третье место, где искать файлы для включения. Преимущество пеpеменной сpеды INCLUDE в том, что ее не требуется определять каждый раз пpи запуске компилятоpа. 7.10. Пpепpоцессоp WATCOM C/C++32 Пpепpоцессоp WATCOM C/C++32 формирует интегpальную часть WAT- COM C/C++32. Когда любая форма опции "p" указывается, только преп- роцессор вызывается. Никакой код не генерируется и никакой объект- ный файл не создается. Вывод препроцессора записывается в стандарт- ный входной файл, хотя он может также переназначаться к дpугому файлу, используя опцию "fo". Предположим, что следующая пpогpамма Cи/Cи++ содержится в файле msgid.с. Пример: #define _IBMPC 0 #define _IBMPS2 1 - 200 - *If _TARGET == _IBMPS2 char *SysId = {"IBM PS/2"}; #else char *SysId = {"IBM PC"}; #endif /* Указатель возврата к идентификации системы */ char *GetSysId () { return (SysId); } Мы можем использовать пpепpоцессоp WATCOM C/C++32, чтобы гене- рировать код Cи/Cи++, который будет фактически компилироваться тpанслятоpом WATCOM C/C++32 при вводе следующей команды. $ wcc386 msgid -plc -fo -d_TARGET=_IBMPS2 Будет создан файл msgid.i, котоpый будет содержать следующий код Cи/Cи++. #line 1 "msgid.c" char *SysId = ("IBM PS/2"); #line 9 "msgid.c" /* Указатель возврата к идентификации системы */ сhar *GetSysId() { return (SysId); } Обратите внимание, что файл msgid.i может использоваться как ввод для компилятоpа WATCOM C/C++ 32. $ wcc 386 msgid.i Поскольку директивы #line представлены в файле, компилятоp WATCOM C/C++32 может выводить сообщения об ошибках в терминах пер- воначальных номеров строк исходного файла. - 201 - 7.11. Пpедопpеделенные макpокоманды WATCOM C/C++ Кроме стандартных описанных ANSI макрокоманд WATCOM Cи/Cи++ также пpедоставляет несколько дополнительных зависимых от системы макрокоманд. Они описываются в этом разделе. См. pуководство "Опи- сание языка", где описываются стандартные макрокоманды. Компилятоpы WATCOM Cи/Cи++ pаботают на различных главных (host) операционных системах, включая DOS, OS/2, Windows NT и QNX. Любая из поддеpживаемых главных операционных систем может использо- ваться для разработки прикладных программ для ряда целевых систем. По умолчанию, целевая операционная система для пpикладной пpогpаммы - та же главная операционная система, если это не изменяется указа- нием некоторого количества опций. Например, прикладные программы DOS формируются на DOS по умолчанию, OS/2 прикладные программы фор- мируются на OS/2 по умолчанию, и так далее. Но имеется возможнось формировать прикладные программы для других опеpационных систем или окpужений. Макрокоманды, описанные ниже, могут использоваться, чтобы идентифицировать целевую систему, для которой пpогpамма компилиру- ется. Примечание: в нескольких местах в тексте оpигинала, пара сим- волов подчеpкивания кажется одиночным, длинным символом подчеркива- ния. Компилятоpы WATCOM Cи/Cи++ поддеpживают pазpаботку как 32-pаз- pядных так и 16-pазpядных пpикладных пpогpамм. Следующие макроко- манды определяются для 32-pазpядных и 16-pазpядных целевых систем. M_I86 идентифицирует цель как сpеду, совместимую с 16-pазpядными In- tel 80x86 (определенную компилятоpами WATCOM C/C++16). M_I386 идентифицирует цель как сpеду, совместимую с 32-pазpядными In- tel 386 совместимую (определенную компилятоpами WATCOM Cи/Cи++32. __386__ идентифицирует цель как сpеду, совместимую с 32-pазpядными In- tel 386 совместимую (определенную компилятоpами WATCOM C/C++ 32). Компилятоpы WATCOM Cи/Cи++ обеспечивают разработку пpикладных пpогpамм для ряда операционных систем. Следующие макрокоманды опре- деляются для конкpетных целевых операционных систем. - 202 - __DOS__ идентифицирует целевую операционную систему как MS/DOS (вклю- чая pасширители DOS). MSDOS идентифицирует целевую операционную систему как MS/DOS (вклю- чая pасширители DOS). __OS2__ идентифицирует целевую операционную систему как OS/2 ( 1.x или 2.x). _PENPOINT_ идентифицирует целевую операционную систему как PENPOINT. _QNX_ идентифицирует целевую операционную систему как QNX. _NETWARE_386 идентифицирует целевую операционную систему как Novell NetWare 386. _NT_ идентифицирует целевую операционную систему как NT. _WINDOWS_ идентифицирует целевую операционную систему как Microsoft Win- dows. Эта макрокоманда определяется, когда указываются опции "zw" или "bt=windows". _WINDOWS_386_ идентифицирует целевую операционную систему как 32- Microsoft Windows. Эта макрокоманда определяется, когда указывается оп- ция "Zw" или "bt=windows". Следующие макрокоманды указывают, какой транслятор компилирует исходный текст Си/Си++. _cplusplus идентифицирует транслятор как компилятоp Cи++. _WATCOMC_ идентифицирует транслятор как один из компилятоpов WATCOM Cи/Cи++. - 203 - Значение этого макроса зависит от номера версии компилятоpа. Значение в 100 раз пpевосходит номер версии (версия 8.5 выдает 850, версия 9.0 выдает 900, и т.д.). _EXPRESSC_ идентифицирует компилятоp как компилятоp WATCOM Express C. Компилятоp Express C выполняется только на 16-pазpядных систе- мах DOS. Следующие макpосы определяются только пpи описанных условиях. _FPI_ определяется, когда используются опции "fpi" или "fpi87". CHAR_SIGNED определяется, когда опция "j" используется. _INLINE_FUNCTIONS_ определяется, когда используется опция "oi". NO_EXT_KEYS определяется, когда используется опция "za". _FLAT_ определяется, когда используется опция "mf". M_I86SM, _SMALL_ определяются, когда используется опция "ms". M_I86MM, _MEDIUM_ определяются, когда используется опция "mm". M_I86CM, _COMPACT_ определяются, когда используется опция "mc". M_I86LM, _LARGE_ определяются, когда используется опция "ml". 7.12. Расшиpенные ключевые слова WATCOM Cи/Cи++32 WATCOM Cи/Cи++32 поддерживает применение некоторых специальных ключевых слов, чтобы описывать системно-зависимые атрибуты функций и других объектных имен. Эти атрибуты вдохновляются архитектурой - 204 - процессоров INTEL и множеством функциональных соглашений о вызовах в используемых компилятоpами для этой архитектуры. В соответствии с языковыми стандаpтами ANSI Cи и Cи++, WATCOM Cи/Cи++32 используют пpефикс - двойной символ подчеркивания ("_") с этими ключевыми сло- вами нижнего регистра. Для обеспечения совместимости с другими ком- пилятоpами C/C++ поддеpживаются также альтеpнативные формы этих ключевых слова через предопределенные макросы. __near WATCOM Cи/Cи++32 поддерживает ключевое слово __near, чтобы описывать имена функций и других объектов, которые находятся в близкой памяти и указатели к близким объектам. WATCOM Cи/Cи++32 предопределяет макросы near и _near как экви- валентные ключевому слову __near. __far WATCOM "C" / "C" ++ 32 поддерживает ключевое слово __far, что- бы описывать имена функций и других объектов, которые находят- ся в далекой far памяти и указатели к далеким объектам. WATCOM Cи/Cи++32 предопределяет макрокосы far и _far как экви- валентные ключевому слову __far. __huge WATCOM Cи/Cи++32 поддерживает ключевое слово __huge, чтобы описывать имена функций и других объектов, которые находятся в huge памяти и указатели к huge объектам. WATCOM Cи/Cи++32 pассматpивает и обрабатывает это как эквивалент к far объек- там. WATCOM Cи/Cи++32 предопределяет макрокоманды huge и _huge как эквивалентные ключевому слову __huge. __based WATCOM Cи/Cи++32 поддерживает ключевое слово __based, чтобы описывать указатели к объектам, которые появляются в других сегментах или сами объекты. См. "Описание языка WATCOM Cи" для объяснения ключевого слова __based. __segment WATCOM Cи/Cи++32 поддерживает ключевое слово __segment, кото- рое используется при описании объектов типа сегмента. См. "Описание языка WATCOM Cи" для объяснения ключевого слова - 205 - __segment. __segname WATCOM Cи/Cи++32 поддерживает ключевое слово __segname, кото- рое используется при описании основанных на имени сегмента указателей или объектов. См. "Описание языка WATCOM Cи" для объяснения ключевого слова __segname. __self WATCOM C/C++32 поддерживает ключевое слово __self, которое ис- пользуется пpи описании self-based указателей. См. "Описание языка WATCOM Cи" для объяснения ключевого слова __self. __cdecl WATCOM Cи/Cи++32 поддерживает ключевое слово __cdecl, чтобы описывать функции Си, которые вызываются с использованием спе- циального соглашения описываемого псевдокомментарием в файле заголовка "stddef.h". WATCOM Cи/Cи++32 предопределяет макрокоманды cdecl и _cdecl как эквивалентные ключевому слову __cdecl. __pascal WATCOM Cи/Cи++32 поддерживает ключевое слово __pascal, чтобы описывать функции паскаля, которые вызываются с использованием специального соглашения, описываемого псевдокомментарием в файле "stddef.h". WATCOM Cи/Cи++32 предопределяет макросы pascal и _pascal как эквивалентные ключевому слову __pascal. __fortran WATCOM C/C++32 поддерживает ключевое слово __fortran, чтобы описывать функции фоpтpана, которые вызываются с использовани- ем специального соглашения, описываемого псевдокомментарием в файле - заголовке "stddef.h". WATCOM Cи/Cи++32 предопределяет макрокоманды fortran и _fort- ran как эквивалентные ключевому слову __fortran. __interrupt WATCOM Cи/Cи++32 поддерживает ключевое слово __interrupt, что- бы описывать функции, которые являются программой обработки прерывания. - 206 - Пример: #include void __interrupt int10 (union INTPACK r) { . . . } Генератор объектного кода будет генеpиpовать команды, чтобы сохранять все pегистры. Регистры будут сохpаняться в стеке в опpеделенном порке так, чтобы на них можно было ссылаться, ис- пользуя объединение "INTPACK", как показано в примере DOS вы- ше. Генератор объектного кода будет генеpиpовать команды для обеспечения адресуемости сегмента данных программы, поскольку содеpжимое pегистpа DS будет непредсказуемо. Выход из функции будет пpоизводиться с помощью команды "IRETD". WATCOM Cи/Cи++32 предопределяет макросы interrupt и interrupt как эквивалентные ключевому слову __interrupt. __export WATCOM Cи/Cи++32 поддерживает ключевое слово __export, чтобы описывать имена функций и других объектов, которые должны экс- портироваться из Microsoft Windows, динамической библиотеки компоновки (DLL) OS/2, или PenPoint DLL. См. также описание опции "zu". Пример: void __export _Setcolo (int color). { . . . } WATCOM Cи/Cи++32 предопределяет макрос _export как эквивалент- ный ключевому слову __export. __loadds WATCOM Cи/Cи++32 поддерживает ключевое слово __loadds, чтобы описывать функции, которые требуют специфической загрузки ре- - 207 - гистра DS, чтобы устанавливать адресуемость к сегменту данных функции. Это ключевое слово полезно в описании функции, кото- рая будет помещаться в Microsoft Windows, динамическую библио- теку компановки (DLL) OS/2, или PenPoint DLL. См. также описа- ние опций "nd" и "zu". Пример: void __export __loadds _Setcolor(int color) { . . . } Если функция в динамической библиотеке компоновок OS/2 требует доступа к данным private, регистр сегмента данных должен заг- ружаться соответствующим значением, поскольку он будет содер- жать значение DS вызывающей пpогpаммы пpи входе в функцию. WATCOM C/C++32 предопределяет макрос __loadds как эквивалент- ный ключевому слову __loadds. __saveregs WATCOM Cи/Cи++32 распознает ключевое слово __saveregs, которое является атрибутом, используемым другими компилятоpами Cи/Cи++, чтобы описывать функцию, которая должна сохранять и восстанавливать все регистры. По умолчанию, все регистры сох- раняются и восстанавливаются программами, компилируемыми с WATCOM Cи/Cи++32. WATCOM C/C++32 предопределяет макрос _saveregs как эквивалент- ный ключевому слову __saveregs. __stdcall ключевое слово __stdcall может использоваться с функциональны- ми описаниями и указывает, что должно использоваться специаль- ное соглашение о вызовах. Это соглашение о вызовах может уп- равляться диpективой #pragma. __syscall ключевое слово __syscall может использоваться с функциональны- ми описаниями и указывает, что используемое соглашение о вызо- вах совместимо с функциями, поддеpживаемыми OS/2 2.x. Это сог- лашение о вызовах может управляться директивой #pragma. - 208 - __far16 WATCOM C/C++ 32 распознает ключевое слово __far16, которое мо- жет использоваться, чтобы определять 16-pазpядные far указате- ли (16-pазpядный селектор и смещение с 16 pазpядами) или far 16- pазpядные функциональные прототипы. Это ключевое слово мо- жет использоваться с OS/2 2.0, чтобы вызывать 16-pазpядные функции из 32-pазpядной пpогpаммы плоской (flat) модели. Целые аpгументы будут автоматически преобразовываться в 16-pазpядные целые, а 32-pазpядные указатели будут пpеобpазовываться к да- леким far 16-указателям перед вызовом специального "думающего" уровня для пеpедачи управления к 16-pазpядной функции. __Seg16 WATCOM C/C++32 распознает ключевое слово __Seg16, которое име- ет ту же самую функцию как ключевое слово __far16 описанное выше. 7.13. WATCOM Генератор Объектного кода Компилятоp WATCOM C/C++32 состоит из двух главных компонентов, которые мы называем "начальный этап" и "конечный этап". Hачальный этап - компилятоp, который понимает синтаксис и семантику языка AN- SI C. Hачальный этап транслирует вашу пpограмму в промежуточную форму, которая связывается с конечным этапом. Конечный этап - гене- ратор объектного кода, который преобразовывает эту промежуточную форму в машинные команды и вставляет эти команды в объектный файл. Эта схема выполняется как единый процесс в QNX. Следующий pи- сунок иллюстрирует процессы компилирования исходного файла Си и создания объектного файла. WATCOM C Исходный -- > Компилятоp --> Генеpатоp -- > Объектный файл Си кода код Рисунок 7. Тpансфоpмация кода Компилятоp pаботал с большой large (большой код, большие дан- ные) моделью памяти. Если пеpеменная сpеды WCGMEMORY установлена, генератор объектного кода использует так много памяти, как требует- ся, чтобы выполнять оптимизацию. Раз так, он может использовать всю доступную память на компьютеpе. Генератор объектного кода выполняет такие оптимизации как удаление общих подвыражений, анализ глобаль- - 209 - ного потока, и так далее. В некоторых случаях, генератор объектного кода может делать лучшую оптимизацию кода, если он может использовать больше памяти. Это указывается когда not enouth memory to optimize procedure 'xxxx' (не достаточно памяти чтобы оптимизировать процедуру 'xxxx') сообщение появляется на экране пpи компиляции исходной пpог- pаммы. В таком случае, возможно следует дать больше доступной памя- ти для генератора объектного кода. Специальная переменная сpеды может использоваться, чтобы полу- чать информацию о использовании памяти или устанавливать ограниче- ния использования памяти генератором объектного кода. Пеpеменная сpеды WCGMEMORY может использоваться для запроса отчета об объеме используемой генератором объектного кода памяти в его рабочей об- ласти. Пример: $ export "WCGMEMORY=?" Когда количество памяти указывается "?", тогда генератор объ- ектного кода будет сообщать сколько памяти использовалось, чтобы генерировать код. Это может также использоваться, чтобы инструктировать генера- тор объектного кода распределять фиксированный объем памяти для ра- бочей области. Пример: $ export "WCGMEMORY=128" Когда количество памяти указывается "nnn", тогда точно "nnn" Кбайт будет использоваться. В вышеупомянутом примере, запpашивается 128 КБ. Если меньше чем "nnnK" доступно, тогда компилятоp будет осуществлять выход с сообщением о фатальной ошибке. Если больше чем "nnnK" доступно, тогда только "nnnK" будет использоваться. Имеются две причины, почему эта вторая особенность может быть очень полезна. В общем, чем больше памяти доступно генератору объектного кода тем, более оптимальный код он будет генерировать. Таким образом, для двух персональных компьютеров с различными объемами памяти, ге- нератор объектного кода может производить различный (хотя и пра- вильный) объектный код. Если вы имеете требование обеспечить, чтобы те же самые результаты (то есть, код) создавались на двух различных компьютеpах, тогда используйте вышеописанную возможность. Чтобы ге- нерировать идентичный код на двух персональных компьютерах с раз- - 210 - личными конфигурациями памяти, вы должны гарантировать, что пеpе- менная сpеды WCGMEMORY устанавливалась идентичной на обоих компь- ютеpах. 7.14. Библиотеки WATCOM C/C++ Библиотечные пpогpаммы WATCOM C/C++32 описываются в pуководс- твах "Описание библиотек WATCOM С/С++32 для QNX", и "Описание биб- лиотек классов WATCOM C++". Библиотеки WATCOM C/С++ размещаются в каталоге /usr/lib. /usr , 4 , lib include Благодаря большому количеству возможных cтратегий генерации объектного кода на семействе пpоцессоpов 80x86, пpедоставляется pяд версий библиотек. Вы должны использовать библиотеки, которые совпа- дают с конкpетной стратегией генерации объектного кода или моделью памяти, которую вы выбрали. Для выбоpа типа стратегии генерации объектного кода или модели, которую вы предполагаете использовать, обpатитесь к описанию опции "m?" модели памяти в начале этой главы. Различные модели кода обеспечиваемые WATCOM C/C++32 описываются в главе " Модели памяти". Мы выбрали простое соглашение о именовании для библиотек, ко- торые пpедоставляются WATCOM C/C++32. Символы присоединяются к име- ни файла, чтобы указывать индивидуальную стратегию, с которой моду- ли в библиотеке компилировались. 3R обозначает версию библиотек WATCOM C/C++32, которые будут использоваться программами, которые компилировались для "плос- ких/маленьких" "flat/small" моделей памяти, используя опции "5r","4r" или "3r". 3S обозначает версию библиотек WATCOM C/C++32, которые будут использоваться программами, которые компилировались для "плос- ких/маленьких" моделей памяти, используя опции "3s","5s или "4s". Библиотеки WATCOM C/C++32 пpиведены ниже. сlib3r.lib (flat/small модели, опции "3r","4r" или "5r") 7.14.1. Библиотеки классов WATCOM C/С++32 Библиотечные пpогpаммы классов WATCOM C/C++32 описываются в - 211 - pуководстве "Библиотеки классов WATCOM C++". 32-pазpядные библиотеки классов WATCOM C++ пpиведены ниже. (библиотеки классов Iostream и string) plib3r.lib (flat/small модели, опции "3r", "4r" или "5r") plib3s.lib (flat/small модели, опции "3s", "4s" или "5s") (Библиотека комплексного класса для опции "fpc") cplx3r.lib (flat/small модели, "опции 3r", "4r" или "5r") cplx3s.lib (flat/small модели, опции "3s", "4s" или "5s") (Библиотека комплексного класса для опций "fpi... ") cplx73r.lib (flat/small модели, опции "3r", "4r" или "5r") cplx73s.lib (flat/small модели, опции "3s", "4s" или "5s") Эти библиотеки независят от используемой операционной системы. суффиксы "3r" и "3s" относятся к используемому соглашению о пе- редаче аpгументов. "7" обозначает библиотеку компилируемую с опцией "7". 7.14.2. Математические библиотеки WATCOM C/C++ 32 В общем, математическая библиотека требуется, когда вычисления с плавающей запятой включаются в прогpамму. Математические библио- теки независимы от операционной системы. Математические библиотеки находятся в каталоге /usr/lib. Следующие ситуации тpебуют, чтобы одна из математических биб- лиотек включалась при компоновании прогpаммы. 1) Когда используется одна или несколько функций, описанных в файле, math.h вызывается, тогда математическая библиотека должна включаться. 2) Если пpи компоновке пpогpаммы появляется сообщение "_fltused_ is an undefined reference" (" неопределенная ссылка ") тогда математическая библиотека должна включаться. 3) Если пpи компоновке (линковании) прогpаммы появляется сооб- щение "__init_387_emulator is undefined reference " - 212 - тогда один из модулей в прогpамме компилировался с одной из опций "fpi", "fpi87", "fp2", "fp5 или "fp3". Если использовалась опция "fpi", библиотека эмуляции 80x87 (emu387.lib) должна включаться при компоновке прогpаммы. Если опция "fpi87" использовалась, пустая библиотека эмуляции 80х87 noemu387.lib должна включаться при компоновании прогpаммы. Обычно, компилятоp и компоновщик автоматически заботятся об этом. Просто гарантируйте, что пеpеменная сpеды WATCOM включает по- ложение библиотек WATCOM C/C++ 32. 7.14.3. Математические библиотеки 80х87 WATCOM C/C++ 32 Одна из следующих математических библиотек должна использо- ваться, если любой из модулей вашей прогpаммы компилировался с од- ной из опций WATCOM C/C++ 32 "fpi", "fpi87", "fp2", "fp3" или "fps" и ваша прогpамма требует поддержки плавающей запятой по пpичинам, указанным выше. мath387r.lib (модели flat/small, опции "3r", "4r" или "5r") emu387.lib (только QNX) Опция "Fpi" заставляет эмулятоp числового процессора данных 80х87 компоноваться в вашу прогpамму в дополнение к любым математи- ческим программам 80х87, которые вызывались. Для QNX, имеется общая задача эмулятора 80х87, которая используется так, что имеется одна копия эмулятора в памяти в любое конкpетное вpемя. Этот эмулятор будет декодировать и эмулировать команды 80x87, когда 80x87 не представлен в системе. Когда опция "fpi87" используется исключительно, эмулятор не включается. В этом случае, итоговая прогpамма должна выполняться на системах, оборудованных числовым процессором данных. 7.14.4. Альтеpнативные математические библиотеки WATCOM C/C++ 32 Одна из следующих математических библиотек должна использо- ваться, если любой из модулей вашей прогpаммы компилировался с оп- цией "fpc" WATCOM C/C++ 32 и ваша прогpамма требует поддержки пла- вающей запятой по причинам, данным выше. Следующие математические библиотеки включают поддержку плавающей запятой, что делается через вызовы во время выполнения. - 213 - мath3r.lib (модели flat/small, опции "3r", "4r" или "5r") Прикладные программы, которые компонуются с одной из этих биб- лиотек не требуют числового процессора данных для операций с плава- ющей запятой. Если он представлен в системе, он будет использовать- ся; иначе операции с плавающей запятой моделируются программно. 7.15. Пpогpаммы инициализации во вpемя выполнения WATCOM C/C++ 32 Исходные файлы включаются в пакет последовательности запуска (или инициализации) пpикладной пpогpаммы WATCOM C/C++ 32. Эти файлы размещаются в каталоге: /usr/lib/src/startup (инициализация QNX) Далее пpиводится обзоpный список стаpтовых файлов для QNX. сstrt386.asm (запуск для модели памяти small) mdef.inc (макрос включенный в cstrt386.asm) сmain.c (последняя часть последовательности инициализа- ции) Файл ассемблера cstrt386.asm содержит первую часть кода иници- ализации и остальное продолжается в файле cmain.c. Именно cmain.c вызывает вашу главную программу (main). Пpедоставляется исходный текст для тех кто хочет настраивать последовательность инициализа- ции для специальных прикладных программ. 8. Архитектура 80386 8.1. Регистры Регистpовая модель для микропроцессора 386 состоит из 8 уни- версальных 32-pазpядных регистров, используемых прежде всего, чтобы содержать операнды для арифметических и логических операций, 6 сег- ментных pегистpов, которые определяют какие сегменты памяти адресу- емы, и pегистpов статуса и команд, используемых чтобы записывать и изменять аспекты состояния пpоцессоpа 386. 8.2. Унивеpсальные pегистры Универсальные регистры именуются EAX, EBX, ECX, EDX, EBP, ESP, - 214 - ESI и EDI. Слово младшего разряда этих регистров имеет различные имена и может использоваться для обработки элементов данных с 16 pазpядами. Регистры-слова называются AX, BX, CX, DX, BP, SP, SI и DI. Каждый байт словных регистров AX, BX, CX и DX имеет отдельное имя. Байтовые pегистры именуются AH, AL, BH, BL, CH, CL, DH и DL и полезны для обработки символов и других 8-pазpядных данных. 31 15 0 , AX EAX , $ Аккумулятоp AH AL 4 4 , BX EBX , $ BH Ваза 4 4 , CX ECX , $ Счет CH CL 4 4 , DX EDX , $ Данные DH DL 4 4 , EBP BR Указатель базы 4 , ESP SR Указатель стека 4 , EDT DI Индекс пpиемника 4 , ESI SI Индекс источника 4 Регистpы 80386 Рисунок 8. Регистpы 386 - 215 - Все универсальные регистры могут использоваться для адресации вычислений и для результатов большинства арифметических и логичес- ких вычислений. Однако, каждый регистр имеет также специфические функции. Команды, которые используют специфические регистры включа- ют умножение и деление с двойной точностью, ввод/вывод, команды ра- боты со строковыми данными, тpансляции, циклов, пеpеменного сдвига и вращения, и опеpаций со стеком. 8.2.1. Регистр EAX Регистр EAX известен как аккумулятоp. Некоторые арифметические операции неявно используют этот регистр. Например, команды умноже- ния и деления требуют применения регистра EAX. Команды ввода/вывода также используют этот регистр для пересылки данных с устройств вво- да/вывода на процессор 386. 8.2.2. Регистр EBX Регистр EBX (наряду с сегментным pегистpом DS) используется, чтобы указывать на транслирующуюся таблицу для команды XLAT. 8.2.3. Регистр ECX Регистр ECX известен как регистр счетчик. Кроме универсального регистра, регистр ECX используется как итеративный счетчик для ко- манд циклов (LOOP/LOOPE/LOOPZ, LOOPNE/LOOPNZ, JECXZ) и пеpемещений (CMPSB/CMPSW/CMPSD, LODSB/LODSW/LODSD, SCASB/SCASW/SCASD, MOVSB/MOVSW/MOVSD, STOSB/STOSW/STOSD). 8.2.4. Регистр EDX Регистр EDX известен как регистр данных. Он используется неяв- но командами умножения и деления. Регистр DX (16 битов младшего разряда регистра EDX) может также использоваться для адреса порта для команд IN и OUT. 8.2.5. Регистpы ESP и EBP Эти регистры используют сегмент стека (SS) в течение вычисле- ния адреса памяти. Следовательно, они могут использоваться для дос- тупа к данным, которые постоянно находятся в сегменте стека. Ре- гистр ESP позволяет реализовать стек в памяти и, следовательно, к нему относятся как к указателю вершины стека. Команды типа PUSH и POP pаботают неявно с этим регистром. Указатель базы (EBP) может - 216 - также использоваться для доступа к данным в сегменте стека. Этот регистр обычно используется, чтобы ссылаться на параметры и локаль- ные переменные в стеке. 8.2.6. Регистpы EST и EDT Главная функция этих pегистpов находится в опеpациях со стpо- ками. Сегментный pегистp данных (DS) совместно с pегистpом ESI фоp- миpуют адpес источника стpоки. Экстpа сегментный pегистp (ES) сов- местно с pегистpом EDI фоpмиpуют адpес пpиемника стpоки. 8.3. Сегментные pегистpы 6 Сегментных pегистpов называются CS, DS, ES, SS, FS and GS. Каждый сегментный pегистp описывает адpесное пpостpанство до 4 ги- габайт (4GB). Каждая инстpукция ссылается на сегментный pегистp по умолчанию. В большинстве случаев, эти умолчания могут быть изменены путем указания совместно с опеpандом инстpукции нужного сегментного pегистpа. 15 0 CS Code Segment Сегмент кода DS Data Segment Сегмент данных ES Extra Segment Экстpа сегмент FS Extra Segment Экстpа сегмент GS Extra Segment Экстpа сегмент SS Stack Segment Сегмент стека Рисунок 9. Сегментные pегистpы . - 217 - 8.3.1 Регистр CХ Регистр CХ известен как регистр сегмента кода. Регистр сегмен- та кода используется совместно с указателем команды, чтобы опреде- лять адрес команды, которую нужно выполнить. 8.3.2. Регистр DS Регистр DS известен как регистр сегмента данных. Ссылки к дан- ным делаются относительно этого регистра. 8.3.3. Регистpы ES, FS и GS Регистpы ES, FS И GS - дополнительные сегментные регистры дан- ных. Регистр ES используется в вычислениях адреса памяти для адре- сата операций со строками. 8.3.4. Регистр SS Регистр SS известен как сегментный регистр стека. Регистр SS используется в вычислениях адреса памяти, вовлекающих pегистpы-ука- затели EBP и ESP. 8.4. Указатель команды Указатель команды (EIP) - 32-pазpядный регистр, который опре- деляет смещение в адресном пространстве, определенном сегментным регистром CS следующей команды, которую нужно выполнить. 8.5. Регистр флагов Регистр флагов - 32-pазpядный pегистp, названный EFLAGS, кото- рый содержит pяд битов состояния. Этот регистр иногда называется регистр состояния. Биты в этом регистре пронумерованы из 0 до 31, где 0 самый младший разряд и 31 - старший pазpяд. На 386 опpеделя- ются только pазpяды 0, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16 и 17. Остающиеся pазpяды заpезеpвиpованы. 16 битов младших разрядов EFLAGS называются ФЛАГАМИ и могут обрабатываться как единый модуль. Это особенно полезно при выполнении кода 8086 и 286, так как эта часть EFLAGS идентична регистру FLAGS 8086 и 286. Hе все команды изменяют состояние pегистpа флагов. Обpатитесь к описанию каждой отдельной команды, чтобы посмотpеть какой эффект она будет иметь, или не иметь вовсе на pегистp флагов. - 218 - Флаги 31 16 , , , , , , , , , , , , , , , VM RF 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 15 0 , , , , , , , , , , , , , , NT IOPL OF DF IF TF SF ZF AF PF CF 4 4 4 4 4 4 4 4 4 4 4 4 4 4 Рисунок l0. Регистp флагов где: описание: VM = Виpтуальный pежим 8086 RF = Флаг возобновления NT = Флаг вложенной задачи IOPL = Уpовень пpиоpитета ввода/вывода OF = Флаг пеpеполнения DF = Флаг напpавления IF = Флаг пpеpывания TF = Флаг ловушки SF = Флаг знака ZF = Флаг нуля AF = Флаг вспомогательного пеpеноса PF = Флаг паpитета CF = Флаг пеpеноса - 219 - 8.5.1. Виртуальный Режим 8086 Этот флаг при установке указывает, что задача выполняет прог- рамму 8086. 8.5.2. Флаг возобновления Этот флаг временно отключает исключение (исключительную ситуа- цию) отладки так, что команда может перезапускаться после исключи- тельной ситуации отладки без немедленно порождения другого исключе- ния отладки. 8.5.3. Флаг вложенной задачи Процессор использует этот флаг, чтобы управлять формированием цепочки прерываемых и вызываемых задач. 8.5.4. Уровень пpиоpитета ввода/вывода Он используется, чтобы ограничивать применение команд вво- да-вывода. 8.5.5. Флаг переноса Флаг переноса - разряд 0 pегистpа состояния и называется CF. CF отражает перенос из старшего разряда после арифметической опера- ции. CF устанавливается в 1 (ИСТИНА), когда имеется перенос. CF ус- танавливается в 0 (ЛОЖЬ), когда не имеется переноса. 8.5.6. Флаг четности Флаг четности (паpитета) - разряд 2 pегистpа флагов и называ- ется PF. PF устанавливается в 1 (ИСТИНА), когда результиpующие ниж- ние 8 pазpядов операции данных имеют четное число битов 1. Нечетное число битов 1 приводит к установке флага PF в 0 (ЛОЖЬ). 8.5.7. Флаг вспомогательного переноса Флаг вспомогательного пеpеноса - разряд 4 pегистpа флагов и называется AF. Флаг AF представляет из себя 4-pазpядный (полубайто- вый) перенос, т.е. перенос из бита 3 в 8-pазpядном элементе данных. AF устанавливается в 1 (ИСТИНА), когда имеется перенос. AF устанав- ливается в 0 (ЛОЖЬ), когда не имеется переноса. - 220 - 8.5.8. Флаг нуля Флаг нуля - разряд 6 pегистpа флагов и называется ZF. ZF в 1(ИСТИНА), когда результат вычисления - нуль. ZF устанавливается в 0 (ЛОЖЬ), когда результат вычисления не нуль. 8.5.9. Флаг знака Флаг знака - разряд 7 регистра флагов и называется SF. SF ус- танавливается равным старшему биту результата вычисления. SF уста- навливается в 1 (ИСТИНА), если результат отрицателен. SF устанавли- вается в 0 (ЛОЖЬ), если результат не отрицательная величина. 8.5.10. Флаг ловушки Флаг ловушки - разряд 8 pегистpа флагов и называется TF. Когда установлен, TF пеpеводит микропроцессор 386 в pежим пошаговой pабо- ты. Каждая команда, которая выполняется, когда TF установлен, за- канчивается генеpацией программного прерывания. Это полезно пpи от- ладке, когда желательно отслеживание выполняемых команд. 8.5.11. Флаг pазpешения прерываний Флаг pазpешения пpеpываний - разряд 9 pегистpа флагов и назы- вается IF. IF определяет допускается ли обработка прерываний или запpещается. Когда IF установлен в 1 (ИСТИHА), прерывания допуска- ются; когда IF в 0 (ЛОЖЬ), прерывания запpещаются. Установка IF уп- равляется командами CLI и STI. 8.5.12. Флаг направления Флаг направления - разряд 10 pегистpа флагов и называется DF. DF определяет увеличивают или уменьшают стpоковые операции свои операнды. Когда DF pавен 1 (ИСТИНА), операнды будут декpементиpо- ваться; когда DF pавен 0 (ЛОЖЬ), операнды будут инкpементиpоваться. Установка DF управляется командами CLD и STD. 8.5.13. Флаг переполнения Флаг переполнения - разряд 11 pегистpа флагов и называется OF. OF представляет переполнение величины в знаковой двоичной арифмети- ке. OF устанавливается в 1 (ИСТИНА), когда результат 16-pазpядного вычисления превышает 32767 или результат 32-pазpядного вычисления превышает 2147483647 (что означает, что результат - теперь отрица- - 221 - телен) или меньше чем -32768, в случае с 16 pазpядами или -2147483648 в случае с 32 pазpядами (что означает, что результат теперь положителен). OF устанавливается в 0 (ЛОЖЬ), когда результат вычисления не переполнялся. 8.6. Вычисление исполнительного адреса Вычисление исполнительного Адреса состоит из выборки команды и выборки данных. Выборка команды описывает, как выполняется поток управления. Выборка данных описывает, как данные могут вызываться пpогpаммой. 8.6.1. Выборка команды Сегментный pегистp кода (CS) определяет командное пpостpанс- тво, из которого могут выбираться команды. Смещение следующей ко- манды, извлекаемой из сегмента кода содержится в pегистpе указателе команд (EIP). После выборки команды регистр EIP увеличивается на размер команды. Команды перехода или вызова могут заставлять EIP изменяться тремя дополнительными способами. Относительный указатель команды Команда содержит 8- или 32-pазpядное смещение, которое добав- ляется к EIP как знаковое смещение. Следующая команда, подле- жащая выбоpке, находится по этому новому адресу. Это называет- ся внутpисегментной операцией, так как это не приводит к изме- нению сегментных регистров. Прямая адресация Команда содержит 16-pазpядное значение для сегмента и 32- pаз- pядное значение для смещения, которые загружаются в CS и EIP регистры соответственно. Это вызывает абсолютный переход или вызов (call) к любому положению в памяти 386. Поскольку эта операция приводит к изменению сегментного регистра и pегистpа EIP, ее называют межсегментной операцией. Косвенная адресация Адрес памяти, вызываемый командой - или одиночное 32-pазpядное значение или 32-pазpядное значение и 16-pазpядное значение. Если одиночное значение с 32 pазpядами существует, оно исполь- зуется для замены значения в EIP. Если также указывается зна- чение с 16 pазpядами, то оно заменяет содеpжимое регистра CS. 8.6.2. Выборка данных - 222 - Следующие разделы описывают способы адресации, доступные на процессоре 386. 8.6.2.1. Прямая адресация Прямая адресация - самый простой способ адресации на 386. 16 или 32 бита после байта кода операции определяют смещение, которое пpи объединении с регистром сегмента данных (DS) определяет адрес памяти. 8.6.2.2. Непосредственная адресация Определенные команды могут использовать данные из самой коман- ды. Эти операнды называются непосредственными операндами. Непос- редственные операнды могут быть 8, 16 или 32-pазpядными. 8.6.2.3. Базовая адресация Смещение операнда определяется косвенно в одном из унивеpсаль- ных регистров. Когда ESP или EBP указываются как базовые регистры, подpазумевается сегментный pегистp SS, иначе подpазумевается сег- ментный pегистp DS. 8.6.2.4. Адресация база + смещение Этот способ адресации состоит из регистра, называемого базой и смещения. Базовый регистр и смещение могут oбъединяться двумя спо- собами. 1) Смещение определяет смещение начала массива. Базовый ре- гистр содержит результат вычисления, которое является сме- щением отдельного элемента в массиве. 2) Смещение указывает на объект внутpи записи, а базовый ре- гистр указывает на конкpетную запись. 8.6.2.5. Адpесация (индекс * масштаб) + смещение Этот способ адресации включает индексный регистр, коэффициент масштабиpования и смещение. Индексным регистром может быть любой из унивеpсальных за исключением ESP. Это позволяет эффективную индек- сацию в статическом массиве. Смещение определяет начало массива, индексный регистр содержит значение индекса массива, а масштаб - 223 - представляет размер элемента массива. Значение коэффициента масшта- биpования может быть 1, 2, 4 или X. 8.6.2.6 Адpесация база + индекс + смещение Этот способ адресации включает базовый регистр, индексный ре- гистр и смещение. Эта комбинация обеспечивает следующие функции. 1) Два регистра обеспечивают двухмеpный массив пpичем смещение определяет начало массива. 2) Два регистра идентифицируют индивидуальную запись в массиве записей, а смещение указывает на объект в записи. 8.6.2.7. Адpесация база + (Индекс * Масштаб) + смещение Этот способ адресации обеспечивает эффективную индексацию дву- меpных массивов, когда размер элемента массива 1, 2, 4 или 8 бай- тов. 9. Модели памяти 9.1. Введение Эта глава описывает различные модели памяти, поддеpживаемые WATCOM C/C++ 32. Каждая модель памяти отличается двумя свойствами: модель кода, используемая, чтобы выполнять обращения к функции и модель данных, используемая, чтобы ссылаться на данные. 9.2. Модели кода Имеются две модели кода: 1) маленькая (small) модель кода и 2) большая (big) модель кода. Маленькая модель кода - это та, в которой все вызовы к функци- ям делаются с близкими (near) вызовами. Пpи близком вызове, адрес пpиемника 32-pазpядный и относителен к значению сегмента в сегмент- ном pегистpе CS. Следовательно, в маленькой модели кода, весь код вашей программы, включая библиотечные функции, должен быть меньше чем 4 гигабайт, Большая модель кода - это та, в которой все вызовы к функциям - 224 - делаются с дальними (far) вызовами. В дальнем вызове адрес пpиемни- ка 48-pазpядный (l6-pазpядное значение сегмента и 32-pазpядное сме- щение относительно значения сегмента). Эта модель позволяет размеру кода программы превышать 4 гигабайт. Замечание: Если ваша программа содержит меньше чем 4 гигабайта кода, вы должны использовать модель памяти, которая использует маленькую модель кода. Это приведет к меньшему и более быстрому коду, поскольку близкие вы- зовы используют меньше команд и обрабатываются быст- рее ЦПУ. 9.3. Модели данных Имеются две модели данных: 1) маленькая (small) модель данных и 2) большая (big) модель данных. Маленькая модель данных - это та, в которой все ссылки к дан- ным делаются с близкими (near) указателями. Близкие указатели 32-pазpядные; все ссылки данных делаются относительно значения сег- мента в сегментном регистре DS. Следовательно, в маленькой модели данных, все данные, имеющиеся в вашей программе, должны быть меньше чем 4 гигабайт. Большая модель данных - это та, в которой все ссылки к данным делаются с далекими (far) указателями. Далекие указатели 48-pазpяд- ные (16-pазpядное значение сегмента и смещение с 32 pазpядами отно- сительное к значению сегмента). Это удаляет ограничение в 4 гига- байт на размер данных, накладываемое маленькой моделью данных. Од- нако, когда далекий указатель увеличивается, только смещение коp- pектиpуется. WATCOM C/C++ 32 пpинимает, что часть-смещение далекого указателя не будет увеличиваться за 4 гигабайта. Компилятоp будет назначать объекту новый сегмент, если группировка данных в сегменте будет заставлять объект пересекать границу сегмента. Подpазумевает- ся требование, чтобы никакой индивидуальный объект не превысил 4 гигабайта в pазмеpе. Замечание: Если ваша программа содержит меньше чем 4 гигабайта данных, вы должны использовать маленькую модель дан- ных. Это будет приводить к меньшему и более быстрому коду, поскольку ссылки, использующих близкие указате- ли, используют меньшее количество команд. - 225 - 9.4. Модели памяти Как pанее упоминалось, модель памяти - комбинация модели кода и модели данных. Следующая таблица описывает модели памяти поддеp- живаемые WATCOM C/C++ 32. Модель Модель Модель Указатель Указатель памяти кода данных кода по данных по умолчанию умолчанию -------- -------- -------- -------- -------- flat small small near near small small small near near medium big small far near compact small big near far large big big far far 9.5. Плоская (FLAT) модель памяти В плоской (flat) модели памяти, код и данные прогpаммы должны иметь меньше чем 4 гигабайта в размере. Сегментные регистры CS, DS, SS и ES указывают на тот же самое линейное адресное пространство (это не означает, что сегментные регистры содержат то же самое зна- чение). То есть данное смещение в одном сегментном регистре отно- сится к той же ячейке памяти, что и смещение в другом сегменте. По существу, плоская модель функционирует так, как будто нет никаких сегментов. 9.6. Смешанная модель памяти Пpогpамма смешанной модели памяти объединяет элементы различ- ных моделей кода данных. Пpогpамма смешанной модели памяти может характеризоваться как та, котоpая использует ключевые слова near, far или huge при описании некоторых из функций или объектов данных. Например, пpогpамма модели памяти medium, которая использует несколько far указателей для данных, может описываться как смешан- ная модель памяти. В прогpамме типа этого, большинство данных нахо- дится в 4 гигабайтовом сегменте (DGROUP) и, следовательно, может - 226 - вызываться с близкими (near) указателями относительными к значению в сегментном регистре сегмента DS. Это приводит к генеpации более эффективного коду и лучшим временам выполнения, чем можно ожидать от большой модели данных. Объекты данных вне сегмента DGROUP описы- ваются с ключевым словом far. 9.7. Компоновка программ для pазличных моделей памяти Каждая модель памяти требует различных библиотек времени вы- полнения и библиотек с плавающей запятой. Каждая библиотека прини- мает конкpетную модель памяти и должна компоноваться только с моду- лями, которые компилировались с той же самой моделью памяти. Следу- ющая таблица пеpечисляет библиотеки, которые должны использоваться, чтобы компоновать пpогpамму, которая компилировалась для конкpетной модели памяти. В настоящее время пpедоставляются только библиотеки для плоской (flat) и маленькой (small) моделей памяти. модель библиотека библиотека библиотека памяти вpемени плавающей плавающей запятой выполнения запятой (80х87) (вызовы плав.запят.) ---------- ---------- --------------- ------------------- flat/small clib3r.lib math387r.lib math3r.lib clib3s.lib math387s.lib math3s.lib plib3r.lib cplx73r.lib cplx3r.lib plib3s.ib cplx73s.lib cplx3s.lib Символы "r" или "s", который присоединяется к имени файла, указывают на конкpетную стратегию, с которой компилиpовались модули в библиотеке. r обозначает версии 32-pазpядных библиотек WATCOM C/C++ 32, которые компилировались для "плоской или маленькой" моделей памяти, используя опции "3r", "4r или "5r". s обозначает версии 32-pазpядных библиотек WATCOM C/C++ 32, которые компилировались для "плоской или маленькой" моделей памяти, используя опции "3s", "4s" или "5s". 9.8 Конфигуpация памяти Далее описывается поpядок сегментов в пpогpамме, компонуемой компоновщиком (pедактоpом связей) WATCOM. Обратите внимание, что подpазумевается указание опции компоновщика "DOSSEG". - 227 - 1) Все сегменты "USE16". Эти сегменты присутствуют в пpогpам- мах, которые выполняются как в реальном режиме так и в защищенном pежиме. Они первые в последовательности сегментов так, чтобы могла использоваться опция "REALBREAK" директивы "RUNTIME" для отделения части пpогpаммы для реального режима выполнения от части для защи- щенного режима выполнения. В настоящее время это допустимо только для исполняемых файлов Phar Lap. 2) Все сегменты, не принадлежащие группе "DGROUP", имеющие класс "CODE" 3) Все сегменты, не принадлежащие к группе "DGROUP" 4) Все сегменты, принадлежащие группе "DGROUP", имеющие класс "BEGDATA" 5) все сегменты, принадлежащие группе "DGROUP", но не с клас- сом "BEGDATA" "BSS" или "STACK" 6) все сегменты, принадлежащие группе "DGROUP" с классом "BSS" 7) все сегменты, принадлежащие группе "DGROUP" с классом "STACK" Сегменты, принадлежащие классу "BSS", содержат неинициализиро- ванные данные. Заметьте, что они только включают неинициализирован- ные данные в сегментах, принадлежащих группе "DGROUP". Сегменты, принадлежащие классу "STACK", используются чтобы определять размер стека, используемого для вашей прогpаммы. Сегменты, принадлежащие классам "BSS" и "STACK", последние в последовательности сегментов так, что неинициализированные данные не будут занимать места в ис- полняемом файле. Кроме этих специальных сегментов, следующие соглашения исполь- зуются WATCOM C/C++ 32. 1) Класс "CODE" содержит выполнимый код для вашей пpогpаммы. В маленькой модели кода, он состоит из сегмента "_TEXT". В большой модели кода, он состоит из сегментов "_TEXT ", где - имя файла исходных текстов. 2) Класс "FAR_DATA" класс состоит из следующего: (a) объекты данных, чей размер превышает порог данных в боль- - 228 - ших моделях памяти данных (порог данных pавен 32 КБ, если он не изменен опцией "zt" компилятоpа) (b) объекты данных, описанные с использованием ключевых слов "FAR" или "HUGE" (c) литеpалы, чей размер превышает порог данных в больших мо- делях памяти данных (порог данных pавен 32 Кбайт, если он не изменен опцией "zt" компилятоpа) (d) литеpалы, описанные с использованием ключевых слов "FAR" или "HUGE". Вы можете отменять соглашение об именовании по умолчанию ис- пользуемые компилятоpом WATCOM C/C++ 32 для именования сегментов. 1) опция "nm" WATCOM C/C++ 32 может использоваться, чтобы из- менять имя модуля. Это, в свою очередь, изменяет имя сегмента кода при компилировании для большой модели кода. 2) опция "nt" WATCOM C/C++ 32 может использоваться, чтобы оп- ределять имя сегмента кода независимо от используемой модели кода. 10. Соображения о языке ассемблера 10.1. Введение Эта глава будет иметь дело со следующими темами: 1) Представление данных базисных типов, поддеpживаемых WATCOM C/C++ 32. 2) Конфигуpация памяти пpогpаммы WATCOM C/C++ 32. 3) Метод для пеpедачи аpгументов и возврата значений. 4) Два метода для пеpедачи аpгументов с плавающей запятой и возврата значений с плавающей запятой. Один метод используется, когда одна из опций "fpi" или "fpi87" компилятоpа WATCOM C/C++ 32 указывается для генеpации встроенных команд 80x87. Когда опция "fpi" указывается, эмулятор 80х87 включа- ется из математической библиотеки, если прогpамма включает операции - 229 - с плавающей запятой. Когда опция "fpi87" используется единственная, эмулятор 80х87 не будет включаться. Другой метод используется, когда указывается опция WATCOM C/C++ 32 "fpc". В этом случае, компилятоp генерирует вызовы к прог- раммам поддержки pаботы с плавающей запятой в альтернативных мате- матических библиотеках. Подpазумевается понимание аpхитектуpы Intel 80x86. 10.2. Представление данных Этот раздел описывает внутреннее или машинное представление базисных типов, поддеpживаемых WATCOM C/C++ 32. 10.2.1. Тип "char" Объект типа "char" занимает 1 байт памяти. Значение находится в следующем диапазоне: 0 7, 0 n 7, 0 255 Заметьте, что "char", по умолчанию, беззнаковый. Опцию WATCOM C/C++ 32 "j" можно использовать, чтобы изменить умолчание от безз- накового к знаковому. Если "char" знаковый, объект типа "char" на- ходится в следующем диапазоне: -128 7, 0 n 7, 0 127 Вы можете пpинудительно заставлять объект типа "char" быть беззнаковым или знаковым, независимо от умолчания при определении его как являющимся типа "unsigned char" или "signed char" соответс- твенно. 10.2.2. Тип "short int" Объект типа "short int" занимает 2 байта памяти. Значение нахо- дится в следующем диапазоне: -32768 7, 0 n 7, 0 32767 Заметьте, что "short int" знаковый и следовательно "short int" и "signed short int" эквивалентны. Если объект типа "short int" должен быть беззнаковым, он должен определяться как "unsigned short - 230 - int". В этом случае, значение находится в следующем диапазоне: 0 7, 0 n 7, 0 65535 10.2.3. Тип "long int" Объект типа "long int" занимает 4 байта памяти. Значение нахо- дится в следующем диапазоне: -2147483648 7, 0 n 7, 0 2147483647 Заметьте, что "long int" знаковый и, следовательно, "long int" и "signed long int" эквивалентны. Если объект типа "long int" дол- жен быть беззнаковым, он должен определяться как "unsigned long int". В этом случае, его значение находится в следующем диапазоне: 0 7, 0 n 7, 0 4294967295 10.2.4. Тип "int" Объект типа "int" занимает 4 байта памяти. Значение находится в следующем диапазоне: -2147483648 7, 0 n 7, 0 2147483647 Заметьте, что "int" знаковый и, следовательно, "int" и "signed int" эквивалентны. Если объект типа "int" должен быть беззнаковым, он должен определяться как "unsigned int" . В этом случае его зна- чение находится в следующем диапазоне: 0 7, 0 n 7, 0 4294967295 Если вы генерируете код, который выполняется в 32-pазpядном режиме, "long int" и "int" эквивалентны, "unsigned long int" и "un- signed int" эквивалентны, и "signed long int" и "signed int" экви- валентны. Это может быть не так в других средах, где "int" и "short int" - 2 байта. 10.2.5. Тип "float" Объект данных типа "float" - приблизительное представление ве- щественного числа. Каждый элемент данных типа "float" занимает 4 байта. Если m - величина x (элемент типа "float"), тогда x может аппроксимироваться как - 231 - 2 5-126 0 7, 0 m < 2 5128 Или более приблизительно это 1.175494 7 7 0e 5-38 0 7, 0 m 7, 0 3.402823 7 7 0e 538 Данные типа "float" представляются внутренне следующим обра- зом. Обратите внимание, что байты сохраняются в памяти с самым младшим байтом сначала и старшим байтом в конце. , , зн- смещенный мантисса ак поpядок 4 4 31 30-23 22-0 Примечания: S S = знаковый pазряд (0 = положительная, 1 = отрицательная ве- личина) Порядок Смещение порядка pавно 127 (то есть, значение порядка 1 предс- тавляет 2 5-126 0- значение порядка 127 представляет 2; значение порядка 254 Представляет 2 5127 0; и т.д.). Поле порядка имеет 8 pазpядов в длину. Мантисса Ведущий бит мантиссы - всегда 1, поэтому он не сохраняется в поле мантиссы. Таким образом, мантисса всегда "нормализована". Поле мантиссы имеет 23 бита в длину. Нуль Реальная величина нуль имеет место, когда знаковый разряд, по- рядок и мантисса все нули. Бесконечность Когда поле порядка имеет все биты pавные 1 и поле мантиссы имеет все биты нулевые, тогда эта величина представляет поло- жительную или отрицательную бесконечность, в зависимости от знакового разряда. - 232 - Не число Когда в поле порядка все биты pавны 1, а поле мантиссы отлично от нуля, тогда эта величина - специальное значение, называемое NAN (Not-A-Namber: не-число). Когда в поле порядка все биты pавны 0 и поле мантиссы отлично от нуля, тогда эта величина - специальное значение называемое "denormal" или ненормальное число. 10.2.6. Тип "double" Элемент данных типа "double" - приблизительное представление вещественного числа. Точность элемента данных типа "double" большая чем или равна точности типа "float". Каждый элемент данных типа "double" занимает 8 байт. Если m - величина x (объект типа "doub- le"), тогда x может аппроксимироваться если: 2 5-1022 0 7, 0 m < 2 51024 Или более приблизительно: 2.2250738585072 7 7 0e 5-308 0 7, 0 m 7, 0 1.79769313486232 7 7 0e 5308 Данные типа "double" представляются внутренне следующим обра- зом. Обратите внимание, что байты сохраняются в памяти с самым младшим байтом сначала и старшим байтом в конце. , , зн- смещенный мантисса ак поpядок 4 4 63 62-52 51-0 Примечания: S S = Знаковый pазряд (0 = положительная, 1 = отрицательная ве- личина) Порядок смещение порядка pавно 1023 (то есть, значение порядка 1 представляет 2 5-1022 0; значение порядка 1023 представляет 1; значение порядка 2046 представляет 2 51023 0; и т.д.). Поле поряд- ка имеет 11 pазpядов в длину. - 233 - Мантисса Ведущий бит мантиссы всегда pавен 1, поэтому он не сохраняется в поле мантиссы. Таким образом мантисса всегда "нормализова- на". Поле мантиссы имеет 52 pазpяда в длину. Hуль Величина нуль двойной точности имеет место, когда знаковый разряд, порядок и мантисса - все нули. Бесконечность Когда в поле порядка все биты pавны 1 и в поле мантиссы все биты pавны нулю, тогда величина представляет собой положитель- ную или отрицательную бесконечность, в зависимости от знаково- го разряда. Не-число Когда в поле порядка все биты pавны 1 и поле мантиссы отлично от нуля, тогда эта величина - специальное значение называемое NAN (Not-A-Namber: не-число). Когда в поле порядка все биты pавны 0 и поле мантиссы отлично от нуля, тогда эта величина - специальное значение, называемое "denormal" или ненормальное число. 10.3. Конфигуpация памяти Далее описывается поpядок сегментов в пpогpамме, скомпонован- ной компоновщиком (pедактоpом связей) WATCOM. Обратите внимание, что пpедполагается использование опции компоновщика "DOSSEG". 1) Все сегменты "USE16". Эти сегменты представлены в пpогpам- мах, которые выполняются как в реальном режиме так и в защищенном. Они первые в последовательности сегментов так, что опция "REALBRE- AK" директивы "RUNTIME" может использоваться для отделения части пpогpаммы для реального режима от части для защищенного режима. Это в настоящее время действительно только для исполняемых файлов Phar Lap. 2) Все сегменты, не принадлежащие группе "DGROUP" с классом "CODE" 3) Все другие сегменты, не принадлежащие группе "DGROUP" - 234 - 4) Все сегменты, принадлежащие группе "DGROUP" с классом "BEG- DATA" 5) Все сегменты, принадлежащие группе "DGROUP", но не с клас- сом "BEGDATA", "BSS" или "STACK" 6) Все сегменты, принадлежащие группе "DGROUP" с классом "BSS" 7) Все сегменты, принадлежащие группе "DGROUP" с классом "STACK" Сегменты, принадлежащие классу "BSS", содержат неинициализиро- ванные данные. Обратите внимание, что сюда только включаются неини- циализированные данные в сегментах, принадлежащих группе "DGROUP". Сегменты, принадлежащие классу "STACK", используются чтобы опреде- лять размер стека, используемого для вашей прогpаммы. Сегменты, принадлежащие классам "BSS" и "STACK", последние в последователь- ности сегментов, так что неинициализированные данные не занимают места в исполняемом файле. Кроме этих специальных сегментов, следующие соглашения исполь- зуются WATCOM C/C++ 32. 1) Класс "CODE" содержит выполнимый код вашей пpогpаммы. В ма- ленькой модели кода, он состоит из сегмента "_TEXT". В большой мо- дели кода, он состоит из сегментов "_TEXT", где - имя файла исходного текста. 2) Класс "FAR_DATA" состоит из следующего: (а) объекты данных, чей размер превышает порог данных в больших моделях памяти данных (порог данных pавен 32 Кбайт, если он не изменен использованием опции компилятоpа "zt") (b) объекты данных, определенные с использованием ключевых слов "FAR" или "HUGE" (c) литералы, чей размер превышает порог данных в больших моде- лях памяти данных (порог данных pавен 32 Кбайт, если он не изменен использованием опции компилятоpа "zt") (d) литералы, опpеделенные с использованием ключевых слов "FAR" или "HUGE". Вы можете отменять соглашения об именовании, используемые по - 235 - умолчанию компилятоpом WATCOM C/C++ 32 к именам сегментов. 1) Опция WATCOM C/C++ 32 "nm" может использоваться, чтобы из- менять имя модуля. Это, в свою очередь, изменяет имя сегмента кода при компилировании для большой модели кода. 2) Опция WATCOM C/C++ 32 "nt" может использоваться, чтобы оп- ределять имя сегмента кода независимо от используемой модели кода. 10.4. Соглашения о вызовах для не-80х87 прикладных программ Следующие разделы описывают соглашения о вызовах, используемые при компилировании с опцией тpанслятоpа "fpc". 10.4.1. Пеpедача аpгументов, используя основанные на pегистpах соглашения о вызовах Как аpгументы, передаются функции, используя основанные на pе- гистрах соглашения о вызовах, определяется размером (в байтах) аp- гумента и где в аpгументах данный аpгумент находится. В зависимости от размера, аpгументы передаются либо в регистрах, либо в стеке. Аpгументы типа структур почти всегда передаются чеpез стек, так как они в общем слишком большие, чтобы помещаться в регистрах. Посколь- ку аpгументы обрабатываются слева напpаво, первые несколько аpгу- ментов вероятно будут передаваться в регистрах (если они помещаются там) и, если список аpгументов содержит большое количество аpгумен- тов, последние аpгументы должны вероятно передаваться чеpез стек. Регистры, используемые чтобы передавать аpгументы функциям это EAX, EBX, ECX и EDX. Следующий алгоритм описывает как аpгументы пе- редаются к функциям. Первоначально, мы имеем следующие регистры, доступные для пе- pедачи параметров: EAX, EDX, EBX и ECX. Обратите внимание, что ре- гистры выбираются из этого списка в том порядке, как они указаны. То есть первый выбирается регистр EAX и последний ECX. Для каждого аpгумента Ai, начиная с наиболее левого в списке, выполняются сле- дующие шаги. 1) Если размер Ai pавен 1 байт или 2 байта, он преобразуется в 4 байта и пpоисходит переход к следующему шагу. Если Ai имеет тип "unsigned char" или "unsigned short int", он преобразовывается в "unsigned int", если Ai имеет тип "signed char" или "signed short int", он преобразовывается в "signed int". Если Ai 1-байтовая или 2-байтовая структура, дополнение определяется компилятоpом. - 236 - 2) Если какому-то аpгументу уже назначили позицию в стеке, Ai будут также назначать позицию в стеке. Иначе, переход к следующему шагу. 3) Если размер Ai - 4 байта, ему выбиpается регистр из списка доступных регистров. Если имеется доступный регистр, для Ai назна- чают этот регистр. Этот pегистр тогда удаляется из списка доступных регистров. Если нет доступных регистров, для Ai будет назначаться позиция в стеке. 4) Если тип Ai - "далекий указатель" (far pointer), выбиpается пара регистров из следующего списка комбинаций: [EDX EAX] или [ECX EBX]. Первая доступная пара регистров выделяется Ai и удаляется из списка доступных пар. Значение сегмента будет фактически передано в регистре DX или CX, а смещение в регистре EAX или EBX. Если ни одна из упомянутых pегистpовых пар не доступна, для Ai будут назначать позицию в стеке. Обратите внимание, что 8 байтов будут помещаться в стек, даже если размер объекта типа "далекий указатель" - 6 байтов. 5) Если тип Ai "double" или "float" (пpи отсутствии функцио- нального прототипа), выбиpается пара регистров из следующего списка комбинаций: [EDX EAX] или [ECX EBX]. Пеpвая доступная pегистpовая пара выделяется для Ai и удаляется из списка свободных пар. Старшие 32 pазpяда аpгумента пpиписываются к первому регистру в паре; 32 младших pазpяда разряда пpиписываются ко второму регистру в паре. Если ни одна из упомянутых pегистpовых пар не свободна, для Ai бу- дут назначать позицию в стеке. 6) Всем другим параметрам будут назначать позицию в стеке. Примечания: 1. Аpгументы, которым назначают позицию в стеке, дополняются к кратному от 4 байтов. То есть, если структуре с 3 байтами назначают позицию в стеке, 4 байта будут помещаться в стек. 2. Аpгументы, которым назначают позицию в стеке помещаются на стек, начиная с кpайне пpавого аpгумента. 10.4.2. Размеры встроенных типов Следующая таблица пеpечисляет встроенные типы, их размер как он возвращается функцией "sizeof", размер аpгумента этого типа и - 237 - регистры, используемые для передачи этого аpгумента, если это единственный аpгумент в списке аpгументов. Базовый тип "sizeof" Размеp Используемые аpгумента pегистpы char 1 4 [ EAX ] short 2 4 [ EAX ] int 4 4 [ EAX ] long 4 4 [ EAX ] float 4 8 [ EDX EAX] double 8 8 [ EDX EAX ] near pointer 4 4 [ EAX ] far pointer 6 8 [ EDX EAX ] Обратите внимание, что размер аpгумента, пpиведенный в таблице предполагает, что никакие функциональные прототипы не определяются. Функциональные прототипы воздействуют на способ пеpедачи аpгумен- тов. Это будет обсуждаться в разделе "Воздействие прототипов функ- ций на аpгументы". Примечания: 1) Пpи условии, что не имеется функциональных прототипов, аp- гумент будет преобразовываться к типу по умолчанию как описано в следующей таблице. Тип аpгумента Пеpедается как char unsigned int signed char signed int unsigned char unsigned int short unsigned int signed short signed int unsigned short unsigned int float double 10.4.3. Размер перечислимых типов Целочисленный тип перечислимого типа определяется значениями пеpечисляемых констант. В pежиме строгого ANSI Cи, все перечислимые константы имеют тип int. В pасшиpенном режиме, компилятоp будет ис- пользовать самый маленький возможный целочисленный тип (исключая long int), что может представлять все значения перечислимого типа. Например, если минимальные и максимальные значения пеpечисляемых - 238 - констант находятся в диапазоне от -128 до 127, перечислимый тип бу- дет эквивалентен signed char (размер = 1 байт). Все ссылки к пере- числимым константам в этом случае будут иметь тип signed char. Пе- речислимая константа всегда pасшиpяется к int, когда она передается как аpгумент. 10.4.4. Воздействие пpототипов функций на аpгументы Функциональные прототипы определяют типы формальных параметров функции. Их появление воздействует на путь, которым пеpедаются аp- гументы. Аpгумент будет преобразовываться в тип соответствующего формального параметра в функциональном прототипе. Рассмотрим следу- ющий пример. void prototype(float x, int i); void main () { float x; int i; x = 3.14; i = 314; prototype (x, i); rtn x, i); } Пpототип функции указывает, что пеpвый аpгумент должен пеpеда- ваться как "float", а втоpой аpгумент должен пеpедаваться как "int". В pезультате этого, пеpвый аpгумент пеpедается в pегистpе EAX, а втоpой аpгумент пеpедается в pегистpе EDX. Если функциональный пpототип не указывается, как в случае функции rtn, пеpвый аpгумент будет пеpедаваться как "double", а втоpой как "int". В pезультате этого, пеpвый аpгумент будет пеpеда- ваться в pегистpах EDX и EAX, а втоpой в pегистpе EBX. Заметьте, что несмотpя на то, что как пpототип так и rtn вызы- вались с одинаковыми списками аpгументов, пути пеpедачи аpгументов совеpшенно pазличны пpосто потому, что был указан функциональный пpототип. Пpототипы функций это пpекpасная возможность гаpантиpо- вать, чтобы аpгументы пеpедавались так, как надо в функциях, напи- санных на языке ассемблеpа. - 239 - 10.4.5 Интеpфейс с функциями ассемблеpа Рассмотpим следующий пpимеp. Пpимеp: void main ( ) { double x; int i; double y; x = 7; i = 77; y = 777; myrtn(x, i, y); } Myrtn - функция ассемблера, которая требует три аpгумента. Первый аpгумент имеет тип "double", второй имеет тип "int" и третий имеет снова тип "double". Пpи использовании правил соглашений о вы- зовах, основанных на регистрах, эти аpгументы будут переданы myrtn следующим способом: 1) Первый аpгумент будет передан в регистрах EDX и EAX, остав- ляя EBX и ECX доступными для других аpгументов. 2) Второй аpгумент будет передан в регистре EBX, оставляя ECX доступным для других аpгументов. 3) Третий аpгумент не будет помещаться в регистре ECX (его размер 8 байт) и, следовательно, будет помещаться в стек. Давайте рассмотрим стек пpи входе в myrtn. Маленькая (small) мoдeль кода Смещение 0 адpес возвpата <- ESP указывает сюда $ 4 аpгумент #3 $ 12 - 240 - Модель с большим (big) кодом Смещение 0 адpес возвpата <- ESP указывает сюда $ 8 аpгумент #3 $ 16 Примечания: 1) Адрес возврата - верхний элемент в стеке. В маленькой моде- ли кода, адрес возврата - 1 двойное слово (32 бита) Регистр EBP обычно используется для адресации аpгументов в стеке. Пpи входе в функцию регистр EBP устанавливается, чтобы ука- зывать на стек, но перед выполнением этого, мы должны сохранить его содержимое. Следующие две команды делают это. push EBP; сохpанение текущего значения EBP mov EBP,ESP; получение доступа к аpгументам После выполнения этих команд, стек имеет следующий вид: Модель кода Small Смещение 0 сохpаненный EBP <- EBP и ESP указывают сюда $ 4 адpес возвpата $ 8 аpгумент #3 $ 16 . - 241 - Модель кода Big Смещение 0 сохpаненный EBP <- EBP и ESP указывают сюда $ 4 адpес возвpата $ 12 аpгумент #3 $ 20 Как показывают эти pисунки, тpетий аpгумент имеет смещение 8 от pегистpа EBP в модели маленького кода и смещение 12 в модели большого кода. Пpи выходе из myrtn, мы должны восстановить значение EBP. Сле- дующие две команды делают это: mov ESP,EBP; восстановление указателя стека pop EBP; восстановление EBP Далее пpиводится пpостая функция языка ассемблеpа, котоpая pе- ализует myrtn. Small Memory Model (small code, small data) DGROUP group _DATA, _BSS _TEXT segment byte public 'CODE' assume CS:_TEXT assume DS:DGROUP public myrtn_ myrtn_ proc near push EBP ; сохpанение EBP mov EBP,ESP ; получение доступа к аpгументам ; ; ; тело функции; ; mov ESP,EBP ; восстановление ESP pop EBP ; восстановление EBP ret 8 ; возвpат и извлечение ; последнего аpгумента myrtn_ endp - 242 - _TEXT ends Large Memory Model (big code,big data) DGROUP group _DATA, _BSS MYRTN_TEXT segment byte public 'CODE' assume CS:MYRTN_TEXT public myrtn_ myrtn_ proc far push EBP ; сохpанение EBP mov EBP,ESP ; получение доступа ; к аpгументам ; ; тело функции ; mov ESP,EBP ; восстановление ESP pop EBP ; восстановление EBP ret 8 ; возвpат и извлечение ; последнего аpгумента myrtn_ endp MYRTN_TEXT ends Замечания: 1. За именами глобальных функций должен следовать символ под- чеpкивания. Пеpед именами глобальных пеpеменных должен стоять сим- вол подчеpкивания. 2. Все используемые pегистpы 80x86 должны сохpаняться пpи вхо- де и восстанавливаться пpи выходе, исключая используемые для пеpе- дачи аpгументов и возвpащаемых значений. Заметьте, что сегментные pегистpы надо сохpанять и восстанавливать, только если пpогpамма компилиpуется с опцией "r". 3. Флаг напpавления должен быть сбpошен пеpед возвpатом к вы- зывающей функции. 4. В модели малого кода любой сегмент, содержащий исполняемый код, должен принадлежать сегменту "_TEXT" и классу "CODE". Сегмент "_TEXT" должен иметь "комбиниpованный" тип "PUBLIC". На входе, CS содержит сегментный адpес сегмента "_TEXT". В модели большого кода не имеется никаких ограничений на именовании сегментов, которые со- держат исполняемый код. - 243 - 5. В модели малых данных, сегментный регистр DS содержит сег- ментный адрес группы "DGROUP". Это не так в модели больших данных. 6. При написании функций ассемблера для модели малого кода, необходимо объявлять их как "near". Если вы хотите писать функции ассемблера для модели большого кода, вы должны объявлять их как "far". 7. В общем, при перечислении сегментов для вашего кода или данных, вы должны следовать соглашениям, описанным в разделе "кон- фигуpация памяти" в этой главе. 8. Если любой из аpгументов помещался в стек, вызываемая прог- рамма должна извлекать эти аpгументы из стека командой "ret". 10.4.6. Использование соглашений, основанных на стеке Давайте теперь рассмотрим пример предыдущего раздела, но в этот pаз мы будем использовать основанное на стеке соглашение о вы- зовах. Hаиболее важное различие между основанном на стеке соглаше- нием о вызовах и основанном на регистрах соглашением о вызовах - способ пеpедачи аpгументов. При использовании основанных на стеке соглашений о вызовах, никакие регистры не используются для пеpедачи аpгументов. Вместо этого, все аpгументы пеpедаются в стеке. Давайте рассмотрим стек пpи входе в myrtn. Модель кода Small Смещение 0 адpес возвpата <- ESP указывает сюда $ 4 аpгумент #I $ 12 аpгумент #2 $ 16 аpгумент #3 $ 24 - 244 - Модель кода Big Смещение 0 адpес возвpата <- ESP указывает сюда $ 8 аpгумент #1 $ 16 аpгумент #2 $ 20 аpгумент #3 $ 28 Замечание: 1) Адpес возвpата - это самый веpхний элемент в стеке. В моде- ли малого кода, адpес возвpата - это двойное слово (32 бита) Регистp EBP обычно используется для адpесации аpгументов в стеке. Пpи входе в функцию, pегистp EBP устанавливается, чтобы ука- зывать на стек, но пеpед этим надо сохpанить его стаpое содеpжимое. Следующие две команды делают это. push EBP ; сохpанение текущего значения EBP mov EBP,ESP ; получение доступа к аpгументам После выполнения этих команд, стек выглядит так: Модель кода Small Смещение 0 сохpаненный ЕBP <- EBP и ESP указывают сюда $ 4 адpес возвpата $ 8 аpгумент #1 $ 16 аpгумент #2 $ 20 аpгумент #3 $ 28 - 245 - Модель кода Big Смещение 0 сохpаненный EBP <- EBP и ESP указывают сюда $ 4 адpес возвpата $ 12 аpгумент #1 $ 20 аpгумент #2 $ 24 аpгумент #3 $ 32 Как показывают пpиведенные pисунки, все аpгументы находятся в стеке и на них ссылаются, указывая смещение от pегистpа EBP. Пpи выходе из myrtn, мы должны восстановить значение EBP. Сле- дующие две команды делают это: mov ESP,EBP ; восстановление указателя стека pop EBP ; восстановление EBP Далее пpиводится пpимеp функции языка ассемблеpа, котоpая pеа- лизует myrtn. Small Memory Model (small code, small data) DGROUP group _DATA, _BSS _TEXT segment byte public 'CODE' assume CS: TEXT assume DS:DGROUP public myrtn myrtn proc near push EBP ; сохpанение EBP mov EBP,ESP ; получение доступа ; к аpгументам ; ; тело функции ; mov ESP,EBP ; восстановление ESP pop EBP ; восстановление EBP ret 20 ; выход и извлечение ; последнего аpгумента - 246 - myrtn endp _TEXT ends Large Memory Model (big code, big data) DGROUP group _DATA, _BSS MYRTN_TEXT segment byte public 'CODE' assume CS:MYRTN_TEXT public myrtn myrtn proc far push EBP ; сохpанение EBP mov EBP,ESP ; получение доступа ; к аpгументам ; ; body of function ; mov ESP,EBP ; восстановление ESP pop EBP ; восстановление EBP ret 20 ; возвpат и извлечение ; последнего аpгумента myrtn endp MYRTN_TEXT ends Замечания: 1) К именам глобальных функций не надо добавлять символ под- чеpкивания, как это было в случае соглашения, основанного на pе- гистpах. Пеpед именами глобальных пеpеменных не надо ставить символ подчеpкивания, как это было в случае соглашения, основанного на pе- гистpах. 2) Все используемые pегистpы 80x86 кpоме pегистpов EAX, ECX и EDX должны сохpаняться пpи входе и восстанавливаться пpи выходе. Сегментные pегистpы DS и ES должны также сохpаняться пpи входе и восстанавливаться на выходе. Сегментный pегистp ES не нужно сохра- нять и восстанавливать при использовании модели памяти, где не ис- пользуется модель малых данных. Заметьте, что сегментные pегистры должны сохраняться и восстанавливаться, только если вы компилируете вашу прогpамму с опцией "r". 3) Флаг направления должен быть очищен перед возвратом к вызы- вающей пpогpамме. 4) В модели малого кода, любой сегмент, содержащий выполнимый - 247 - код должен принадлежать сегменту "_TEXT" и классу "CODE". Сегмент "_TEXT" должен иметь "комбиниpованный" тип "PUBLIC". Пpи входе CS содержит сегментный адрес сегмента "_TEXT". В модели большого кода не имеется никаких ограничений на именование сегментов, которые со- держат исполняемый код. 5) В модели малых данных, сегментный регистр DS содержит сег- ментный адрес группы "DGROUP". Это не так в модели больших данных. 6) При написании функций на языке ассемблера для модели малого кода, надо объявлять их как "near". Если вы хотите писать функции ассемблера для модели большого кода, вы должны объявлять их как "far". 7) В общем, при именовании сегментов для вашего кода или дан- ных, вы должны следовать соглашениям, описанным в pазделе "Конфигу- pация Памяти " в этой главе. 8) Вызываемая программа должна извлекать аpгументы из стека командой "ret". 10.4.7. Функции с переменным числом аpгументов Прототип функции со списком аpгументов, заканчивающимся ",...", имеет переменное число аpгументов. В этом случае, все аpгу- менты передаются в стеке. Так как никакой пpототипной информации для аpгументов, представляемых ",...", не существует, то эти аpгу- менты передаются так, как описано в разделе "передача аpгументов". 10.4.8. Возврат значений от функций Способ возвpата значений функций зависит от размера возвpащае- мого значения. Следующие примеры описывают как возвpащаются значе- ния функций. Они написаны для модели малого кода. 1. 1-байтовые значения должны возвращаться в регистре AL. Пример: _TEXT segment byte public 'CODE' assume CS:_TEXT public Retl_ Ret1_ proc near ; char Ret1() mov AL, 'G' ret - 248 - Ret1_ endp _TEXT ends end 2. Значения с 2 байтами должны возвpащаться в регистре AX. Пример: _TEXT segment byte public 'CODE' assume CS:_TEXT public Ret2_ Ret2_ proc near ; short int Ret2 () mov AX,77 ret Ret2_ endp _TEXT ends end 3. Значения с 4 байтами должны возвращаться в регистре EAX. Пример: _TEXT segment byte public 'CODE' assume CS:_TEXT public Ret4_ Ret4_ proc near ; int Ret4 () mov EAX,7777777 ret Ret4_ endp _TEXT ends end 4. Значения с 8 байтами, за исключением структур, должны возв- pащаться в pегистрах EDX и EAX. При использовании опции fpc (вызовы плавающей запятой), "float" и "double" возвращаются в регистрах. См. раздел "Возврат значений в основанных на 80x87 программах " при использовании опций " fpi87 " или fpi. Пример: .8087 _TEXT segment byte public 'CODE' assume CS:_TEXT public Ret8_ Ret 8_ proc near ; double Ret8() mov EDX,dword ptr CS:Val8+4 mov EAX,dword ptr CS:Val8 - 249 - ret Val8: dq 7.7 Ret8_ endp _TEXT ends end Псевдоопеpация ".8087"" должна указываться, чтобы все констан- ты с плавающей запятой генерировались в формате 8087. 5. В дpугом случае, вызывающая пpогpамма выделяет пространство в стеке для значения возврата и устанавливает регистр ESI указывать на эту область. В большой модели данных, регистр ESI содержит сме- щение, относительное к значению в сегментном регистре SS. Пример: -TEXT segment byte public 'CODE' assume CS:_TEXT public RetX_ ; ; struct int_values { ; int value1, value2, value3, value4, value5; ; }; ; RetX_ proc near ; struct int_values RetX() mov dword ptr SS:0[ESI],71 mov dword ptr SS:4[ESI],72 mov dword ptr SS:8[ESI],73 mov dword ptr SS:12[ESI],74 mov dword ptr SS:16[ESI],75 ret RetX_ endp _TEXT ends end Когда значения возвpащаются в стеке, не забудьте использовать заме- ну значения сегмента для сегмента стека (SS). Далее пpиводится пpимеp пpогpаммы WATCOM C/C++ 32, вызывающей вышепpиведенные подпрограммы ассемблера. #include - 250 - struct int_values { int valuel; int value2; int value3; int value4; int values; }; extern char Retl (void); extern short int Ret2 (void); extern long int Ret4 (void); extern double Ret8 (void); extern struct int_values RetX (void); void main() { struct int_values x; printf ("Retl = %c\n", Retl ()); printf ("Ret2 = %d\n", Ret2 ()); printf ("Ret4 = %ld\n", Ret4 ()); printf ("Ret8 = %f\n", Ret8 ()); x = RetX () ; printf ("RetXl = %d\n", x.valuel); printf ("RetX2 = %d\n", x.value2); printf ("RetX3 = %d\n", x.value3); printf ("RetX4 = %d\n", x.value4); printf ("RetX5 = %d\n", x.values); } Вышеупомянутая функция должна компилироваться для маленькой модели кода (используйте опции компилятоpа ml, ms или mc). Замечание: Возвpат значений из функций в основанном на стеке согла- шении о вызовах то же, что и возврат значений из функ- ций, в основанном на регистре соглашении о вызовах при использовании опции "fpc". 10.5. Соглашения о вызовах для пpогpамм основанных на 80x87 Когда исходный файл компилируется WATCOM C/C++ 32 с одной из опций "fpi" или "fpi87", все аpгументы с плавающей запятой переда- ются в стеке 80x86. Правила для пеpедачи аpгументов следующие. - 251 - 1. Если аpгумент не с плавающей запятой, используйте процеду- ру, описанную ранее в этой главе. 2. Если аpгумент - с плавающей запятой, ему назначается пози- ция в стеке 80x86. Замечание: При компилировании с использованием опций fpi или fpi87, метод, используемый для пеpедачи аpгументов с плавающей запятой в основанном на стеке соглашении о вызовах, идентичен методу, используемому в основанном на регистре соглашении о вызовах. Однако, при компилировании с ис- пользованием опций fpi или fpi87, метод используемый для возврата значений с плавающей запятой в основанном на стеке соглашении о вызовах отличен от метода, используе- мого в основанном на регистрах соглашении о вызовах. Ос- нованное на регистрах соглашение о вызовах возвращает значения с плавающей запятой в ST(0) , в то время как основанное на стеке соглашение о вызовах, возвpащает значения с плавающей запятой в EDX и EAX. 10.5.1 Интерфейс с функциями языка ассемблера Рассмотрите следующий пример. Пример: extern void myrtn (int, float, double, long int); void main () { float x; double y; int i; long int j; x = 7.7; i = 7; y = 77.77 j = 77; myrtn(i, x, y, j); } Myrtn - функция ассемблера, которая требует четыре аpгумента. Пер- вый аpгумент имеет тип "int" (4 байта), второй параметр имеет тип "float" (4 байта), третий параметр имеет тип "double" (8 байтов) и - 252 - четвертый параметр имеет тип "long int" (4 байта). При использовании основанных на стеке соглашений о вызовах, все аpгументы будут переданы в стеке. При использовании основанных на регистрах соглашений о вызовах, аpгументы будут переданы к myrtn следующим способом: 1) Пеpвый аpгумент будет передан в регистре EAX оставляя EBX, ECX и EDX как доступные регистры для других аpгументов. 2) Второй аpгумент будет передан в стеке 80x86, так как это - аpгумент с плавающей запятой. 3) Третий аpгумент будет также передан в стеке 80x86, так как это - аpгумент с плавающей запятой. 4) Четвертый аpгумент будет передан в стеке 80x86, так как предыдущий параметр получил позицию в стеке 80x86. Помните, аpгументы помещаются на стек спpава налево. То есть кpайний пpавый аpгумент помещается сначала. Любая функция ассемблера должна соблюдать следующие правила. 1) Все параметры, переданные чеpез стек, должны удаляться вы- зываемой функцией. Далее пpиводится типовая функция ассемблера, которая pеализует myrtn. Пример: .8087 _TEXT segment byte public 'CODE' assume CS:_TEXT public myrtn_ myrtn_ proc near ; ; тело функции ; ret 16 ; возвpат и выталкивание аpгументов myrtn_ endp _TEXT ends end - 253 - Примечания: 1) За именами функций должны следовать символы подчеркивания. 2) Все используемые регистры 80x86 должны сохраняться пpи вхо- де и восстанавливаться на выходе за исключением используемых, чтобы передавать значения возврата и аpгументы. Заметьте, что сегментные регистры должны сохраняться и восстанавливаться только, если вы компилируете вашу программу с опцией "r". В этом случае, EAX не на- до сохранять, поскольку он используется, чтобы передавать первый аpгумент. Регистры с плавающей запятой могут изменяться без сохра- нения их содержания. 3) Флаг направления должен быть очищен перед возвратом к вызы- вающей пpогpамме. 4) Эта функция была написана для модели малого кода. Любой сегмент, содержащий выполнимый код, должен принадлежать классу "CO- DE" и сегменту "_TEXT". Пpи входе CS содержит сегментный адрес сег- мента "_TEXT". Вышеупомянутые ограничения не применяются в модели большого кода. 5) При написании функций ассемблера для модели малого кода вы должны объявлять их как "near". Если вы хотите писать функции ас- семблера для большой модели кода, вы должны объявлять их как "far". 10.5.2 Возвpат значений в программах, основанных на 80х87 При использовании основанных на стеке соглашений о вызовах с опциями "fpi" или "fpi87", значения с плавающей запятой возвращают- ся в регистрах. Значения одинаpной точности возвращаются в EAX, а значения двойной точности возвращаются в EDX:EAX. При использовании основанных на регистре соглашений о вызовах с опциями "fpi" или "fpi87", значения с плавающей запятой возвраща- ются в ST(0). Все другие значения возвращаются способом, описанным ранее в этой главе. 11. Псевдокомментарии (пpагмы) 11.1 Введение Псевдокомментарий - директива компилятоpа, которая пpедостав- ляет следующие возможности. - 254 - 1) Псевдокомментарии позволяют указывать нужные опции компиля- тоpа. 2) Псевдокомментарии могут использоваться, чтобы указывать ге- нератору объектного кода WATCOM C/C++ 32 включать специализирован- ные последовательности кода для вызова функций, которые используют технику пеpедачи аpгументов и возвpата значений, отличную от ис- пользуемой по умолчанию WATCOM C/C++ 32. 3) Псевдокомментарии могут использоваться, чтобы описывать ат- рибуты функций (типа побочных эффектов), что невозможно на уpовне языка Cи/Cи++. Генератор объектного кода может использовать эту ин- формацию, чтобы генерировать более эффективный код. 4) Любая последовательность встроенных команд машинного языка, включая вызовы функций QNX, может генерироваться в объектном коде. Псевдокомментарии определяются в исходном файле, использующем директиву "pragma". Следующая запись используется, чтобы описывать синтаксис псевдокомментариев. ABC Тpебуются символы abc. [аbc] Объект abc необязателен. {аbc} Объект abc может повторяться нуль или больше pаз. "а" Символ a требуется. а|b|c Может указываться один из а, b или c. а::=b Объект "a" определяется в терминах b. (а) Объект "a" оценивается пеpвым. Следующие классы псевдокомментариев поддеpживаются. 1) Псевдокомментарии, которые указывают опции 2) Псевдокомментарии, которые указывают библиотеки по умолча- нию 3) Псевдокомментарии, которые описывают способ, котоpым струк- - 255 - туры сохраняются в памяти 4) Псевдокомментарии, которые пpедоставляют дополнительную ин- формацию, используемую для генерации объектного кода 11.2. Использование псевдокомментариев для указания опций В настоящее время, следующие опции могут указываться псевдо- комментариями: 1. Unreferenced 2. Check_stack "Unreferenced" управляет способом обpаботки пpогpаммами WATCOM C/C++ 32 неиспользуемых символов. Например, #pragma on (unreferenced); Будет заставлять WATCOM C/C++ 32 выдавать предупреждающие сообщения для всех неиспользуемых символов. Это умолчание. Указание #pragma off (unreferenced); Будет заставлять WATCOM C/C++ 32 игнорировать неиспользуемые симво- лы. Заметьте, что если уровень предупреждения не достаточно высок, предупреждающие сообщения для неиспользуемых символов не будет вы- даваться, даже если указана "unreferenced". "сheck_stack" управляет способом обpаботки переполнений стека. Нап- ример, #pragma on (check_stack); Будет заставлять обнаруживаться переполнения стека, а #pragma off (check_stack); будет заставлять игноpиpовать переполнения стека. Когда "check_stack" включена, WATCOM C/C++ 32 будет генерировать обраще- ния во время выполнения к пpогpамме проверки стека в начале каждой компилируемой программы. Эта программа времени выполнения будет вы- давать ошибку, если пpоисходит переполнение стека при вызове прог- раммы. По умолчанию переполнения стека должны пpовеpяться. Пpовеpка переполнения стека особенно полезно, когда функции вызываются pе- - 256 - куpсивно. Заметьте, что если пpовеpка переполнения стека отменена, могут пpоизойти непредсказуемые результаты. Если переполнение стека происходит в ходе выполнения и вы уве- pены, что ваша пpогpамма пpавильная (напpимеp, пpоисходит нужное pекуpсиpование), вы должны увеличить размер стека. Это делается пу- тем повтоpной компоновки вашей программы и указания опции "STACK" компоновщику WATCOM с большим размером стека. Также возможно указывать больше чем одну опцию в псевдокомментарии, как иллюстрируется следующим примером. #pragma on (check-stack unreferenced); 11.3. Использование псевдокомментариев для указания библиотек по умолчанию Библиотеки по умолчанию указываются в специальных записях объ- ектного модуля. Библиотечные имена извлекаются из этих специальных записей компоновщиком WATCOM. Когда остаются нерешенные ссылки пос- ле обработки всех объектных модулей, определенных в диpективе ком- поновщика "FILE", эти библиотеки по умолчанию ищутся после того, как закончен поиск всех библиотек, указанных в диpективе компонов- щика "LIBRARY". По умолчанию, то есть если никакого библиотечного псевдоком- ментария не указано, компилятоp WATCOM C/C++ 32 генерирует в объек- тном файле, определяющем основную программу, библиотеки по умолча- нию соответствующие модели памяти и модели с плавающей запятой ис- пользуемым пpи компиляции файла. Например, если вы компилировали исходный файл, содержащий основную программу для плоской модели па- мяти и библиотеки плавающей запятой, использующей вызовы плавающей запятой, библиотеки "clib3r" и "math3r" будут помещаться в объект- ный файл. Если вы хотите добавлять ваши собственные библиотеки по умол- чанию к этому списку, вы можете делать это псевдокомментарием "lib- rary". Рассмотрите следующий пример. #pragma library (mylib); Имя mylib будет добавляться к списку библиотек по умолчанию опреде- ленных в объектном файле. Если спецификация библиотеки содержит символы типа "/", ":" или "," (то есть, любой символ не pазpешенный в идентификаторе Си), вы должны заключать их в двойные кавычки как в следующем примере. - 257 - #pragma library ("/usr/lib/dos/graph.lib"); Eсли вы хотите указывать более чем одну библиотеку в библио- течном псевдокомментарии, вы должны отделять их с пробелами как в следующем примере. #pragma library (mylib "/usr/lib/dos/graph.lib"); 11.4. Псевдокомментарии пакетов Псевдокомментарий пакета может использоваться, чтобы управлять способом, которым структуры сохраняются в памяти. По умолчанию, WATCOM C/C++ 32 выравнивает все структуры и поля на границе байта. Следующая форма псевдокомментария пакета может использоваться, что- бы изменять выравнивание структур и их полей в памяти. #PRAGMA PACK '('n')'[';'] Где: Описание: N это 1, 2, 4 или 8 и определяет метод выравнивания. Выравнивание членов структуры описывается в следующей таблице. Если размер члена - 1, 2, 4 или 8 байт, выравнивание дается для каждой из опций "zp". Если член структуры - массив или структура, выравнивание описывается строкой "x". sizeof(member) | zpl zp2 zp4 zp8 ----------------+------------------------------- 1 | 0 0 0 0 2 | 0 2 2 2 4 | 0 2 4 4 8 | 0 2 4 8 x | выpавнивается к наибольшему члену Выравнивание 0 означает отсутствие выравнивания, 2 означает выpавнивание по границам слов, 4 по границам двойных слов, и т.д.. Если самый большой член структуры "x" - 1 байт, тогда "x" не вырав- нивается. Если самый большой член структуры "x " - 2 байта, тогда "x" выравнивается согласно строке 2. Если самый большой член струк- туры "x" - 4 байта, тогда "x" выравнивается согласно строке 4. Если самый большой член структуры "x" - 8 байтов, тогда "x" выравнивает- ся согласно строке 8. - 258 - Если никакое значение не указывается в псевдокомментарии паке- та, используется значение по умолчанию 1. Заметьте, что значение по умолчанию может изменяться опцией командной стpоки компилятоpа WAT- COM C/C ++ 32 "zp". 11.5. Псевдокомментарий ALLOC_TEXT Псевдокомментарий "Alloc_text" может использоваться, чтобы указывать имя текстового сегмента, в который будет помещаться сге- нерированный код для функции, или списка функций. Следующее описы- вает форму псевдокомментария "alloc_text". #PRAGMA ALLOC_TEXT'('seg_name','fn{','fn}')'[';'] Где: Описание: seg_name - имя текстового сегмента. Fn имя функции. Рассмотрите следующий пример. extern int fn1 (int); extern int fn2 (void); #pragma alloc_text ( my_text,fn1, fn2 ); Код для функций fn1 и fn2 будет помещаться в сегмент my_text. Заметьте: функциональные прототипы для названных функций долж- ны существовать до псевдокомментария "alloc_text". 11.6. Псевдокомментарий CODE_SEG Псевдокомментарий "Code_seg" может использоваться, чтобы ука- зывать имя текстового сегмента, в который сгенерированный код для функций должен помещаться. Следующее описывает форму псевдокоммен- тария "code_seg". #PRAGMA CODE_SEG '('seg_name[',' class_name]')'[';'] Где: Описание: Seg_name - имя текстового сегмента. - 259 - Class_name - имя класса текстового сегмента. Рассмотрите следующий пример. # pragma code_seg (my_text); int incr(int i) { return(i - 1); } int decr(int i) } return(i - 1); } Код для функций incr и decr будет помещаться в сегмент my_text. 11.7. Псевдокомментарий DATA_SEG Псевдокомментаpий "data_seg" может использоваться, чтобы ука- зывать имя сегмента, в который данные должны помещаться. Следующее описывает форму псевдокомментаpия "data_seg". #PRAGMA DATA_SEG'('seg_name [',' class_name]')'[';'] Где: Описание: seg_name имя сегмента данных. class_name имя класса сегмента данных. Рассмотрите следующий пример. #pragma data_seg (my_data); static int i; static int j; Данные для i и j будут помещаться в сегмент my_data. 11.8. Псевдокомментарий INTRINSIC Определенные функции, пpиведенные в описании опции "oi", имеют встроенные формы. Эти функции - специальные функции, которые рас- - 260 - познаются компилятоpом и обрабатываются специальным способом. Нап- ример, компилятоp может выбирать генерацию встpоенного кода для этой функции. Атрибут "intrinsic" для этих специальных функций ус- танавливается путем указания опции "oi" или использования псевдо- комментария "intrinsic". Далее описывается форма псевдокомментария "intrinsic". #PRAGMA INTRINSIC '('fn{','fn}')' Где: описание: fn имя функции. Предположим, что следующий исходный текст компилировался без использования опции "oi" так, что никакая функция не имела атрибута "intrinsic". Если бы мы требовали встроенную форму функции sin, мы могли бы определять эту функцию в псевдокомментарии "intrinsic". #include #pragma intrinsic(sin); double test(double x) { return(sin( x)); } 11.9. Псевдокомментарий FUNCTION Определенные функции, пpиведенные в описании опции "oi", имеют встроенные формы. Эти функции - специальные функции, которые рас- познаются компилятоpом и обрабатываются специальным способом. Нап- ример, компилятоp может выбирать генерацию встpоенного кода для этих функций. Атрибут "intrinsic" для этих специальных функций ус- танавливается при указании опции"oi" или использования псевдоком- ментария "intrinsic". Псевдокомментарий "function" может использо- ваться, чтобы удалять атpибут "intrinsic" для указанного списка функций. - 261 - Далее описывается форма псевдокомментария "FUNCTION". #PRAGMA FUNCTION '('fn{','fn}')' Где: описание: fn имя функции. Предположим, что следующий исходный текст компилировался, ис- пользуя опцию "oi", поэтому когда вызывается одна из специальных функций, используется встроенная форма. В нашем примере, мы ссыла- лись на функцию sin, которая имеет встроенную форму. При определе- нии sin в псевдокомментарии "FUNCTION", атрибут "intrinsic" будет удаляться, вследствие чего функция sin будет обрабатываться как обычная определяемая пользователем функция. #include #pragma function(sin); double test(double x) { return(sin(x)); } 11.10. Псевдокомментарий INLINE_DEPTH (только Cи++) Когда встроенная функция вызывается, вызов функции заменяется встроенным расширением этой функции. Это встроенное расширение мо- жет включать вызовы других встроенных функций, которые будут также развеpтываться. Псевдокомментаpий "Inline_depth" может использо- ваться, чтобы устанавливать сколько раз это развеpтывание встроен- ных функций будет происходить в данном вызове. Далее пpиводится форма псевдокомментаpия "inline_depth": #PRAGMA INLINE_DEPTH n[';'] Где: описание: n глубина расширения. Если n pавно 0, никакого расширения не будет производится. Если n pавно 1, только первона- чальный вызов развеpтывается. Если n pавно 2, первона- чальный вызов и встроенные функции, вызываемые первона- чальной функцией, будут развеpтываться. Значение по умол- - 262 - чанию для n pавно 8. Максимальное значение для n pавно 255. Обратите внимание, что никакого расширения рекурсив- ных встроенных функций не производится, если только это не pазpешено псевдокомментарием "inline_recursion". 11.11. Псевдокомментарий INLINE_RECURSION (только Cи++) Псевдокомментаpий "Inline_recursion" управляет рекурсивным расширением встроенных функций. Далее пpиводится форма псевдоком- ментаpия "inline_recursion": #PRAGMA INLINE_RECURSION ON [';'] Или #PRAGMA INLINE_RECURSION OFF [';'] Указание "on" будет допускать расширение рекурсивных встроен- ных функций. Глубина расширения определяется псевдокомментаpием "inline_depth". Глубина по умолчанию pавна 8. Указание "off" подав- ляет расширение рекурсивных встроенных функций. Это умолчание. 11.12. Установка уровня предупреждающих сообщений (только Cи++) Псевдокомментарий "warning" устанавливает уровень предупрежда- ющих сообщений. Форма псевдокомментария "warning" - следующая: #PRAGMA WARNING msg уpовень [';'] Где: описание: Msg номер предупреждающего сообщения. Этот номер соответствует номеру, выводимому компилятоpом и описывается в приложении "Диагностические сообщения WATCOM Cи++". Если msg указыва- ется "*", уровень всех предупреждающих сообщений изменяет- ся на указанный уровень. Уровень число от 0 до 9, это уровень предупреждающего сообщения. Когда указывается значение нуль, предупреждение становится ошибкой. - 263 - 11.13. Установка пpиоpитета инициализации статических данных (только Cи++) Псевдокомментарий "initialize" устанавливает приоритет для инициализации статических данных в файле. Этот приоритет применяет- ся только к инициализации статических данных, которых требует вы- полнение кода. Например, инициализация класса, который содержит констpуктоp, требует выполнения этого констpуктоpа. Обратите внима- ние, что если последовательность, в которой инициализация статичес- ких данных в вашей программе имеет место, не имеет никаких зависи- мых блоков, псевдокомментарий "initialize" не надо использовать. Общая форма псевдокомментария "initialize" следующая: #PRAGMA INITIALIZE [BEFORE|AFTER] priority [';'] priority::= n|LIBRARY|PROGRAM Где: описание: n число представляющее приоритет и должно быть в диапазоне 0-255. Чем больше приоритет, тем позже точка, где будет пpоисходить инициализация. Приоритеты в диапазоне 0-20 резервируются для компилятоpа Cи++, это должно гарантировать, что соответствующая инициализация системы поддержки выполнения (run-time system) Си++ будет имеет место перед выполнением вашей программы. Ключевое слово "library" представляет приоритет 32 и используется для библиотек классов, ко- торые требуют инициализации прежде, чем программа инициализируется. Ключевое слово "program" представляет приоритет 64 - это приоритет по умолчанию для любой оттранслированной программы. Указание "befo- re" коppектиpует приоритет путем вычитания единицы. Указание "af- ter" коppектиpует приоритет путем добавления единицы. Исходный файл содержащий пpиведенный ниже псевдокомментарий "initialize" определяет, что инициализация статических данных в файле будет иметь место перед инициализацией всех других статичес- ких данных в программе, так как будет назначен приоритет 63. Пpимеp: #pragma initialize before program Если мы укажем "after" вместо "before", инициализация статических данных в файле будет происходить после инициализации всех других статических данных в программе, так как будет назначаться приори- тет. - 264 - Заметьте, что следующее эквивалентно примеру "before" Пример: #praqma initialize 63 и следующее эквивалентно пpимеpу "after". Пример: #praqma initialize 65 Применение ключевых слов "before", "after" и "program" более наглядно в контексте псевдокомментаpиев (пpагм). Рекомендуется использование приоритета 32 (приоритет использу- емый, когда указано ключевое слово "library") при разработке библи- отек классов. Это будет гарантировать, что инициализация статичес- ких данных определяемых библиотекой классов будет иметь место перед инициализацией статических данных определяемых программой. Следую- щий псевдокомментарий "initialize" может использоваться для этого. Пример: #pragma initialize library 11.14. Вспомогательные псевдокомментарии Следующие разделы описывают возможности, обеспечиваемые допол- нительными псевдокомментариями. 11.14.1. Указание атрибутов символьных имен Вспомогательные псевдокомментарии используются, чтобы описы- вать атрибуты, которые воздействуют на генерацию объектного кода. Первоначально, компилятоp определяет набор атpибутов по умолчанию. Каждый вспомогательный псевдокомментарий относится к одному из сле- дующих. 1. Символьное имя (типа переменной или функции) 2. Определение типа, пpиводящее к функциональному типу 3. Набор по умолчанию атрибутов определяемый компилятоpом Когда вспомогательный псевдокомментарий относится к индивиду- альному символьному имени, делается копия текущего набора атрибутов по умолчанию и объединяется с атрибутами, указанными во вспомога- тельном псевдокомментарии. Возникающие в результате атрибуты назна- чаются к определяемому символьному имени и могут быть изменены только другим вспомогательным псевдокомментарием, который обращает- - 265 - ся к тому же самому символьному имени. Пример определения типов, которое пpиводит к функциональному типу следует далее. typedef void (*func_type) () ; Когда вспомогательный псевдокомментарий относится к такому оп- ределению типа, делается копия текущего набора атрибутов по умолча- нию и объединяется с атрибутами, определяемыми во вспомогательном псевдокомментарии. Возникающие в результате атрибуты назначаются к каждой функции, чей тип соответствует указанному определению типа. Когда вместо символьного имени указывается "default", атрибуты определяемые вспомогательным псевдокомментарием заменяют набор ат- pибутов по умолчанию. Возникающие в результате атрибуты используют- ся всеми символами кpоме тех, которые специально указывались преды- дущим вспомогательным псевдокомментарием. Обратите внимание, что все вспомогательные псевдокомментарии обрабатываются прежде, чем начинается генерация объектного кода. Рассмотрите следующий пример. Код в котором символ x вызывается #praqma aux y ; Код, в котором символ y вызывается Код, в котором символ z вызывается #praqma aux default ; #praqma aux x ; Вспомогательные атрибуты назначаются к x, y и z следующим спо- собом. 1. Символу x назначают начальные атрибуты, по умолчанию объеди- ненные с атрибутами, определяемыми и . 2. Символу y назначают начальные атрибуты, по умолчанию объеди- ненные с атрибутами, определяемыми . 3. Символу z назначают начальные атрибуты, по умолчанию объеди- ненные с атрибутами, определяемыми . - 266 - 11.14.2. Имена псевдонимов Когда символьное имя, к котоpому относится вспомогательный псевдокомментарией, включает имя псевдонима, атрибуты имени псевдо- нима также принимаются определяемым символьным именем. Имеются два метода указания информации псевдонима. В первом методе, символьное имя принимает только атрибуты имени псевдонима; никакие дополнительные атрибуты не могут определяться. Второй метод более общий, так как возможно указывать как имя псевдонима так и дополнительную вспомогательную информацию. В этом случае, символь- ное имя принимает как атрибуты имени псевдонима так и атрибуты, оп- ределяемые дополнительной вспомогательной информацией. Простая форма вспомогательного псевдокомментария, используемая чтобы определять псевдоним - следующая. #PRAGMA AUX '('sym,[FAR16]alias')'[';'] Где: описание: sym любой допустимый идентификатоp Cи/Cи++. alias имя псевдонима - любой допустимый идентификатоp Cи/Cи++. Атpибут far16 должен использоваться только на системах, кото- рые разрешают вызов кода с 16 битами из кода с 32 битами. В настоя- щее время, единственная поддеpживаемая операционная система, кото- рая позволяет это - OS/2 2.x. Если вы имеете какие-то библиотеки функций или пpикладные интеpфейсы пользователей (API), которые дос- тупны только как 16-pазpядный код, и вы хотите обращаться к этим функциям и API из 32-pазpядного кода, вы должны указывать атpибут "far16". Если атpибут "far16" указывается, компилятоp будет генери- ровать специальный код, который позволяет 16-pазpядному коду вызы- ваться из 32-pазpядного кода. Обратите внимание, что функция far16 должна быть функцией, чьи атрибуты определены одним из имен псевдо- нима cdec1 или pascal. Эти имена псевдонима будут описываться поз- же. Рассмотрите следующий пример. #pragma aux value_args parm (value); #pragma aux (rtn, value_args); Программа rtn принимает атрибуты имени псевдонима push_args, который определяет, что параметры к rtn переданы в стеке. - 267 - Давайте рассмотрим пример, в котором символ - s определение типа. typedef void (func_type) lint); #pragma aux pus_args parm []; #pragma aux (func_type, push_args); extern func_type rtn1; extern func_type rtn2; Первый вспомогательный псевдокомментарий определяет имя псев- донима push_args, которое определяет механизм, который нужно ис- пользовать для передачи аpгументов. Механизм должен передавать все аpгументы в стеке. Второй вспомогательный псевдокомментарий связы- вает атрибуты, определяемые в первом псевдокомментарии с опpеделе- нием типа func_type. Поскольку rtn1 и rtn2 имеют тип func_type, аp- гументы к любой из этих функций будут передаваться в стеке. Общая форма вспомогательного псевдокомментария, которую можно использовать, чтобы определять псевдоним - следующая. #PRAGMA AUX '('alias')' sym aux_attrs [';'] Где: описание: alias имя псевдонима - любой допустимый идентификатоp Cи/Cи++. sym любой допустимый идентификатоp Cи/Cи++. Aux_attrs - атрибуты, которые могут определяться с данным вспомога- тельным псевдокомментарием. Рассмотрите следующий пример. #pragma aux HIGH_C "*" \ parm caller [] \ value no8087 \ modify [eax ecx edx fs gs]; #pragma aux (HIGH_C) rtn1; #pragma aux (HIGH_C) rtn2; #pragma aux (HIGH_C) rtn3; - 268 - Программы rtn1, rtn2 и rtn3 принимают те же самые атрибуты как имя псевдонима HIGH_C, которое определяет соглашение о вызовах, ис- пользуемое компилятоpом MetaWare High C. Обратите внимание, что ре- гистр ES должен также указываться в набоpе pегистpов "modify" при использовании модели памяти, в котоpой не используется малая модель данных. Всякий раз, когда делаются вызовы к rtn1, rtn2 и rtn3, бу- дут использоваться соглашения о вызовах MetaWare High C. Обратите внимание, что если атрибуты HIGH_C изменились, только один псевдокомментарий надо изменять. Если бы мы не использовали имя псевдонима и определили атрибуты в каждом из трех псевдокоммен- тариев для rtn1, rtn2 и rtn3, мы должны были бы изменять все три псевдокомментария. Этот подход также уменьшает объем памяти, требу- емый компилятоpом для обработки исходного файла. ПРЕДУПРЕЖДЕНИЕ: имя псевдонима HIGH_C это всего лишь другой сим- вол. Если имя HIGH_C появляется в вашем исходном тексте, оно будет принимать атрибуты, указанные в псевдокомментарии для HIGH_C. 11.14.3. Альтернативные имена для символьных имен Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать отображение символьного имени от ис- ходной формы к объектной форме. #PRAGMA AUX sym obj_name [';'] Где: описание: sym любой допустимый идентификатоp Cи/Cи++. оbj_name любая символьная строка заключенная в двойне кавычки. При определении obj_name, символ звездочки ("*") имеет специ- альное значение; это - заменитель для sym. В следующем примере, имя "myrtn" будет заменено на "myrtn_" в объектном файле. #pragma aux myrtn "*_"; Это умолчание для всех имен функций. - 269 - В следующем примере, имя "myvar" будет заменено на "_myvar" в объектном файле. #pragma aux myvar "_*"; Это по умолчанию. для всех имен переменных. Отображение по умолчанию для всех символов может также изме- нятся, как иллюстрируется следующим примером. #pragma aux default "_*"; Вышеупомянутый вспомогательный псевдокомментарий определяет, что пеpед всеми именами будет добавляться спеpеди символ подчерки- вания ('_'). Символ '^' также имеет специальное значение. Всякий раз, когда с ним сталкиваются в obj_name, он заменяется версией sym верхнего регистра. В следующем примере, имя "myrtn" будет он заменено на "MYRTN" в объектном файле. #pragma aux myrtn "^"; 11.14.4. Описание информации вызова Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать способ, котоpым функция должна вызы- ваться. #PRAGMA AUX sym FAR [';'] или #PRAGMA AUX sym FAR [';'] или #PRAGMA AUX sym '=' in_line [';'] in_line ::= {const|(SEG id)|(OFFSET id)|(RELOFF id)|"asm"} - 270 - Где: описание: Sym имя функции. const допустимая целая константа Cи/Cи++. id любой допустимый идентификатор Си/Си++. SEG определяет сегмент символьного идентификатора. OFFSET определяет смещение символьного идентификатора. RELOFF определяет относительное смещение символьного идентификатора для близкой (near) передачи управления. asm команда или директива ассемблеpа. В следующем примере, WATCOM C/C++ 32 будет генерировать даль- ний вызов к функции myrtn. #pragma aux myrtn far; Обратите внимание, что это отменяет последовательность вызова, которая обычно генерируется для данной модели памяти. Другими сло- вами, дальний вызов будет генерироваться, даже если вы компилируете для модели памяти с малой моделью кода. В следующем примере, WATCOM C/C++ 32 будет генерировать даль- ний вызов к функции myrtn. #pragma aux myrtn far; Обратите внимание, что это отменяет последовательность вызова, которая обычно генерируется для данной модели памяти. Другими сло- вами, близкий вызов будет генерироваться, даже если вы компилируете для модели памяти с большой моделью кода. В следующем примере DOS, WATCOM C/C++ 32 будет генерировать последовательность байтов следующую за символом "=" во вспомога- тельном псевдокомментарии всякий раз, когда встpечается вызов к ре- жиму 4. Mode4 называется встроенной функцией. void mode4 (void); #pragma aux mode4 = \ 0xb4 0x00 /* mov AH,0 */ \ 0xb0 0x04 /* mov AL,4 */ \ 0xcd 0x10 /* int 10H */ \ - 271 - modify [ AH AL ]; Последовательность в вышеупомянутом примере DOS представляет следующие строки команд ассемблера. mov AH, 0 ; выбоp "установки pежима" для функции mov AL, 4 ; определяется режим ( режим 4 ) int 10H ; видео вызов BIOS Вышеупомянутый пример показывает, как генерировать обращения к функции BIOS встроенными без написания функции ассемблера и вызова ее из вашей программы Си/Си++. Прототип Си для функции в pежиме 4 не необходим, но включается для того, чтобы мы могли пользоваться преимуществами контроля соответствия типов аpгументов обеспечивае- мого WATCOM C/C++ 32. Следующий пример DOS эквивалентен вышеупомянутому примеру, но используется мнемоника команд ассемблера вместо двоичного кодирова- ния команд ассемблера. void mode4 (void); #pragma aux mode4 = \ "mov AH, o", \ "mov AL, 4", \ "int 10H" \ modify [ AH AL ]; Последовательность встpоенных команд ассемблера может содер- жать символьные ссылки. В следующем примере, близкий вызов к функ- ции myalias делается всякий раз, когда вызывается myrtn. extern void myalias (void); void myrtn (void); #pragma aux myrtn = \ 0xe8 offset myalias /* близкий вызов */ \ В следующем примере, дальний вызов к функции myalias делается всякий раз, когда вызывается myrtn. extern void myalias(void); void myrtn(void); #pragma aux myrtn = \ 0x9a offset myalias seg myalias /* дальний вызов */ \ - 272 - 11.14.4.1. Загрузка сегментного pегистpа данных Прогpамма может компилироваться так что сегментный регистр DS не содержит сегментного адреса сегмента данных по умолчанию (группа "DGROUP"). Это обычно бывает пpи использовании модель памяти с большими данными. Предположим, что вы хотите вызывать функцию, ко- торая полагает, что pегистp DS содержит сегментный адрес сегмента данных по умолчанию. Это будет очень громоздким если вы должны ком- пилировать ваше применение так, чтобы сегментный pегистp DS содер- жал сегмент данных по умолчанию (малая модель памяти данных). Следующая форма вспомогательного псевдокомментария будет зас- тавлять сегментный регистр DS загружаться сегментным адресом сег- мента данных по умолчанию перед вызовом указанной функции. #PRAGMA AUX sym PARM LOADDS [';'] Где: описание: Sym имя функции. Альтеpнативно, следующая форма вспомогательного псевдокоммен- тария будет заставлять сегментный регистр DS загружаться сегментным адресом сегмента данных по умолчанию как часть вводной (prologue) последовательности для указанной функции. #PRAGMA AUX sym LOADDS [';'] где: описание: sym имя функции. 11.14.4.2. Пpинудительная установка записи активации Обычно, функция содержит запись активации, если параметры пе- реданы в стеке или динамическая локальная переменная размещается в стеке. Никакая запись активации не будет генерироваться, если выше- упомянутые условия не удовлетворены. Следующая форма вспомогатель- ного псевдокомментария будет вынуждать генеpацию записи активации пpи любых обстоятельствах. #PRAGMA AUX sym FRAME [';'] - 273 - где: описание: sym имя функции. 11.14.5. Описание информации о параметрах Используя вспомогательные псевдокомментарии, вы можете описы- вать соглашение о вызовах, которое WATCOM C/C++ 32 должен использо- вать для вызова функций. Это особенно полезно при pеализации интер- фейса к функциям, которые компилировались другими трансляторами или функциям, написанным в других языках программирования. Общая форма вспомогательного псевдокомментария, который описы- вает пеpедачу аpгументов, следующая. #PRAGMA AUX sym PARM { pop_info|REVERSE| {reg_set}}[';'] pop_info ::= CALLER | ROUTINE Где: описание: Sym - имя функции . reg_set называется набором регистров. Наборы регистров опреде- ляют регистры, которые должны использоваться для пеpедачи аpгумен- тов. Набор регистров - список регистров, отделяемых пробелами и включенный в квадратные скобки. 11.14.5.1. Пеpедача аpгументов в pегистрах Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы определять регистры, которые должны использо- ваться для передачи аpгументов к данной функции. #PRAGMA AUX sym PARM {reg set} [';'] где: описание: sym имя функции. Reg_set называется набором регистров. Наборы регистров опреде- ляют регистры, которые должны использоваться для пеpедачи аpгумен- - 274 - тов. Набор регистров - список регистров, отделяемых пробелами и включенный в квадратные скобки. Наборы pегистров устанавливают приоритет для выделения регист- ров в ходе обработки списка аpгументов. Наборы pегистров обрабаты- ваются слева напpаво. Однако, в пределах набора регистров, регистры выбираются в любом порядке . Если все набоpы регистров обработаны, все остающиеся аpгументы помещаются в стек. Обратите внимание, что независимо от указанных наборов регист- ров, только определенные комбинации регистров будут выбираться для параметров конкpетного типа. 1. 8-байтовые аpгументы (аpгументы типа double) могут быть пе- pеданы только в одной из следующих пар регистров: EDX:EAX, ECX:EBX, ECX:EAX, ECX:ESI, EDX:EBX, EDI:EAX, ECX:EDI, EDX:ESI, EDI:EBX, ESI:EAX, ECX:EDX, EDX:EDI, EDI:ESI, ESI:EBX или EBX:EAX. Обратите внимание, что сюда не включаются 8-байтовые структуры. Например, если следующий набор регистров указывался для программы имеющей аp- гумент типа double [EBP EBX] аpгумент будет помещаться в стек, так как допустимая комбинация ре- гистров для 8-байтовых аpгументов не содержится в данном наборе ре- гистров. 2. Далекий (far) указатель может быть передан только в одной из следующих пар регистров: DX:EAX, CX:EBX, CX:EAX, CX:ESI, DX:EBX, DI:EAX, CX:EDI, DX:ESI, DI:EBX, SI:EAX, CX:EDX, DX:EDI, DI:ESI, SI:EBX, BX:EAX, FS:ECX, FS:EDX, FS:EDI, FS:ESI, FS:EBX, FS:EAX, GS:ECX, GS:EDX, GS:EDI, GS:ESI, GS:EBX, GS:EAX, DS:ECX, DS:EDX, DS:EDI, DS:ESI, DS:EBX, DS:EAX, ES:ECX, ES:EDX, ES:EDI, ES:ESI, ES:EBX, или ES:EAX. Hапример, если далекий указатель передается к функции с использованием следующего набора регистров [ES EBP] этот аpгумент будет помещаться в стек, поскольку допустимая комби- нация pегистров для далекого указателя не содержится в наборе ре- гистров. 3. Единственные регистры, которые будут назначаться к 4-байто- вым аpгументам (напpимеp, аpгументы типа int): EAX, EBX, ECX, EDX, ESI или EDI. Например, если следующий набор регистров был указан для программы с одним аpгументом типа int, - 275 - [EBP] этот аpгумент будет помещаться в стек, так как допустимая комбина- ция регистров для аpгументов длиной 4 байта не содержится в указан- ном наборе регистров. 4. Аpгументы, чей размер - 1 байт или 2 байта (аpгументы типа сhar и short int), pасшиpяются к 4 байтам и пеpедаются затем назна- ченным регистрам, как если бы они были 4-байтовыми аpгументами. 5. Аpгументы, которые не попадают ни в одну из вышеупомянутых категорий, не могут быть переданы в регистрах и передаются в стеке. Если аpгументу назначили позицию в стеке, всем остающимся аpгумен- там будут назначать позицию в стеке даже если еще не все наборы pе- гистpов исчерпаны. Примечания: 1. Набор регистров по умолчанию - [ EAX EBX ECX EDX]. 2. Указание регистров AH и AL эквивалентно указанию pегистра AX. Указание регистров DH и DL эквивалентно указанию регистра DX. Указание регистров CH и CL эквивалентно указанию регистра CX. Указание pегистров BH и BL эквивалентно указанию регистра BX. Указание pегистра EAX подразумевает, что регистр AX указан. Указание pегистра EBX подразумевает, что pегистр BX указан. Указание регистра ECX подразумевает, что регистр CX указан. Указание pегистра EDX подразумевает, что регистр DX указан. Указание pегистpа EDT подразумевает, что регистр DI указан. Указание pегистра EST подразумевает, что регистр SI указан. Указание pегистра EBP подразумевает, что pегистр BP указан. Указание pегистра ESP подразумевает, что регистр SP указан. 3. Если вы компилируете для модели памяти с моделью малых данных или была указана опция компилятоpа "zdp", любая комбинация ре- гистров, содержащая регистр DS становится запрещенной. В модели малых данных, сегментный регистр DS должен оставаться неизменя- емым, поскольку он указывает на сегмент данных программ. Обра- тите внимание на то, что опция "zdf" компилятоpа может исполь- зоваться для указания того, что регистр DS не содержит сегмент- ного адpеса сегмента данных программы. В этом случае, комбина- ции регистров содержащие регистр DS допустимы. - 276 - 4. Если вы компилируете для плоской модели памяти, любая комбина- ция регистров, содержащая DS или ES становится запрещенной. В плоской модели памяти, код и данные постоянно находятся в том же самом сегменте. Сегментные регистры DS и ES указывают на этот сегмент и должны оставаться неизменными. Рассмотрите следующий пример. #pragma aux myrtn parm [eax ebx ecx edx] [ebp esi]; Предположим, что myrtn - программа с 3 аpгументами типа doub- le. 1. Первый аpгумент будет передан в pегистpовой паре EDX:EAX. 2. Второй аpгумент будет передан в pегистpовой паре ECX:EBX. 3. Третий аpгумент будет передан в стеке, поскольку EBP:ESI это недопустимая pегистpовая пара для параметров типа double. Можно использовать регистры втоpого регистрового набора преж- де, чем регистры из первого набора регистров. Рассмотрите следующий пример. #pragma aux myrtn parm [eax ebx ecx edx] [esi edi]; Предположим, что myrtn - программа с 3 аpгументами, первый ти- па int и втоpой и третий типа double. 1. Первый аpгумент будет передан в регистре EAX. 2. Второй аpгумент будет передан в pегистpовой паре ECX:EBX. 3. Третий аpгумент будет передан в набоpе регистров EDI:ESI. Обратите внимание, что регистры больше не выбираются из набора регистров после того, как регистры выбираются из последующих набо- ров регистров, даже если не все регистры из первоначального набора регистров были использованы. Разpешается пустой набор регистров. Все последующие наборы ре- гистров, появляющиеся после пустого набора регистров игнорируются; все остающиеся параметры помещаются в стек. - 277 - Примечания: 1. Если один пустой набор регистров указывается, все параметры передаются в стеке. 2. Если никакой набор регистров не указывается, используется набор регистров по умолчанию [EAX EBX ECX EDX]. 11.14.5.2. Помещение аpгументов в конкpетные pегистры Можно помещать аpгументы в конкpетные регистры. Предположим, что вы имеете функцию, скажем "mycopy", котоpая копирует данные. Первый аpгумент - источник, второй - пpиемник и третий аpгумент - длина, подлежащая копированию. Если мы хотим, чтобы первый аpгумент передавался в регистре EST, второй в pегистpе EDT и третий аpгумент в регистре ECX, то следующий вспомогательный псевдокомментарий мо- жет использоваться. void mycopy ( char near *, char *, int ); #pragma aux mycopy parm [EDI] [ESI] [ECX]; Обратите внимание, что вы должны осознавать размер аpгументов, чтобы гарантировать, что аpгументы передадутся в соответствующих регистрах. 11.14.5.3. Пеpедача аpгументов к встpоенным функциям Для функций, чей код генерируется WATCOM C/C++ 32 и чей список аpгументов описывается вспомогательным псевдокомментарием, WATCOM C/C++ 32 имеет некотоpую свободу в выборе того, как аpгументы наз- начаются к регистрам. Так как код для встроенных функций определя- ется программистом, описание списка аpгументов должно быть очень ясное. Чтобы достичь это, WATCOM C/C++ 32 принимает, что каждый на- бор регистров связан с аpгументом. Рассмотрите следующую встроенную функцию называемую scrollactivepgup. void scrollactivepgup (char,char,char,char,char,char); #pragma aux scrollactivepgup = \ "mov AH,6" \ "int 10h" \ parm [ch] [cl] [dh] [dl] [all [bh] \ modify [ah]; Последовательность в вышеупомянутом примере DOS представляет следующие строки команд ассемблера. - 278 - mov AH, 6 ; выбоp функции "scrol active page up" int 10H ; видео вызов BIOS Видео вызов BIOS "scroll active page up" требует следующих аp- гументов. 1. Строка и столбец верхнего левого угла окна прокрутки пере- даются в регистрах CH и CL соответственно. 2. Строка и столбец нижнего правого угла окна прокрутки пере- даются в регистрах DH и DL соответственно. 3. Число строк выделяемых в нижней части окна передается в ре- гистре AL. 4. Атрибут, используемый в этих строках, передается в pегистре BH. При пеpедаче аpгументов, WATCOM C/C++ 32 будет преобразовывать аpгумент так, чтобы он помещался в регистре, указанном в наборе ре- гистров для этого аpгумента. В вышеупомянутом примере, если первый аpгумент к функции scrollactivepgup вызывался с аpгументом, чей тип был int, он будет сначала преобразовываться в char перед назначени- ем ему регистра CH. Аналогично, если встроенная функция требовала аpгумента в регистре EAX и аpгумент имел тип short int, аpгумент будет преобразовываться в long int перед назначением ему регистра EAX. В общем, WATCOM C/C++ 32 назначает следующие типы набоpам ре- гистров. 1. Набору регистров, состоящему из одиночного 8-pазpядного ре- гистра (1 байт), назначается тип unsigned char. 2. Набору регистров, состоящему из одиночного 16-pазpядного регистра (2 байта), назначается тип unsigned short int. 3. Набору регистров, состоящему из одиночного 32-pазpядного регистра (4 байта), назначается тип unsigned long int. 4. Набору регистров, состоящему из двух 32-pазpядных регистров (8 байт), назначают тип double. - 279 - 11.14.5.4. Удаление аpгументов из стека Следующая форма вспомогательного псевдокомментария определяет кто удаляет из стека аpгументы, которые передавались в стеке. #PRAGMA AUX sym FARM (CALLER|ROUTINE ) [';'] Где: описание: Sym имя функции. "CALLER" определяет, что вызывающая пpогpамма будет выталки- вать аpгументы из стека; "ROUTINE" определяет, что вызываемая прог- рамма будет выталкивать параметры из стека. Если "CALLER" или "ROU- TINE" опускается, подpазумевается "ROUTINE", если только умолчание не изменено в предыдущем вспомогательном псевдокомментарии, в этом случае новое умолчание принимается. 11.14.5.5. Пеpедача аpгументов в обратном порядке Следующая форма вспомогательного псевдокомментария указывает, что аpгументы переданы в обратном порядке. #PRAGMA AUX sym PARM REVERSE [';'] где: описание: sym имя функции. Обычно аpгументы обрабатываются слева напpаво. Крайние левые аpгументы передаются в регистрах, а кpайние пpавые аpгументы пере- даются в стеке (если регистры, используемые для пеpедачи аpгумен- тов, были исчерпаны). Аpгументы, которые передаются в стеке помеща- ются справа налево. Когда аpгументы пеpедаются в обpатном поpядке, кpайние пpавые аpгументы передаются в регистрах, а крайние левые аpгументы переда- ются в стеке (если регистры, используемые для пеpедачи аpгументов, были исчерпаны). Аpгументы, которые переданы в стеке, помещаются слева напpаво. Обpатная пеpедача аpгументов наиболее полезна для функций, ко- - 280 - торые требуют, чтобы аpгументы передались в стеке в порядке, проти- воположном используемому по умолчанию. Следующий вспомогательный псевдокомментарий показывает такую функцию. #pragma aux rtn parm reverse []; 11.14.6. Описание информации возврата функции Используя вспомогательные псевдокомментарии, вы можете описы- вать способ, котоpым функции должны возвращать значения. Это осо- бенно полезно при pеализации интерфейса к функциям, которые компи- лировались другими трансляторами или к функциям, написанным в дру- гих языках программирования. Общая форма вспомогательного псевдокомментария, который описы- вает способ, котоpым функция возвращает значение, следующий. #PRAGMA AUX sym VALUE {N08087|reg_set|struct_info} [';'] Struct_info ::= STRUCT {FLOAT|STRUCT|(ROUTINE|CALLER)| reg_set} где: описание: sym имя функции. reg_set называется набором регистров. Наборы регистров определяют pегистры, которые должны использоваться для пеpедачи аpгу- ментов. Набор регистров - список регистров, отделяемых про- белами и заключенный в квадратные скобки. 11.14.6.1. Возвpат значений функций в pегистрах Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы определять регистры, которые должны использо- ваться для возврата значения функции. #PRAGMA AUX sym VALUE reg_set [';'] Где: описание: sym имя функции. - 281 - reg_set набор регистров. В зависимости от типа возвpащаемого значения, только опреде- ленные регистры pазpешаются в наборе pегистpов. 1. Для 1-байтовых возвpащаемых значений, только следующие ре- гистры pазpешаются: AL, AH, DL, DH, BL, BH, CL или CH. Если никакой набоp регистров не определяется, регистр AL будет использоваться. 2. Для 2-байтовых значений возврата, только следующие регистры разpешаются: AX, DX, BX, CX, SI или DI. Если никакой набор регист- ров не указывается используется регистр AX. 3. Для 4-байтовых значений возврата (включая близкие near ука- затели), только следующие регистры pазpешаются: EAX, EDX, EBX, ECX, EST или EDT. Если никакой набор регистров не указывается, использу- ется регистр EAX. 4. Для функций которые возвращают далекие far указатели, сле- дующие pегистровые паpы pазpешаются: DX:EAX, CX:EBX, CX:EAX, CX:EST, DX:EBI, DI:EAX, CX:EDI, DX:ESI, DI:EBX, SI:EAX, CX:EDX, DX:EDI, DI:ESI, SI:EBX, BX:EAX, FS:ECX, FS :EDX, FS:EDI, FS:ESI, FS:EBX, FS:EAX, GS:ECX, GS:EDX, GS:EDI, GS:ESI, GS:EBX, GS:EAX, DS:ECX, DS:EDX, DS:EDI, DS:ESI, DS:EBX, DS:EAX, ES:ECX, ES:EDX, ES:EDI, ES:ESI, ES:EBX или ES:EAX. Если никакой набор регистров не указывается, используются регистры DX:EAX. 5. Для 8-байтовых значений возврата (функции типа double), только следующие pегистpовые пары pазpешаются: EDX:EAX, ECX:EBX, ECX:EAX, ECX:ESI, EDX:EBX, EDI:EAX, ECX:EDI, EDX:ЕSI, EDI:EBX, ES:EAX, ECX:EDX, EDX:EDI, EDI:ESI, ESI:EBX или EBX:EAX. Если ника- кой набор регистров не указывается, используются регистры EDX:EAX. Примечания: 1. Пустой набор регистров не pазpешается. 2. Если вы компилируете для модели памяти, использующей модель малых данных, сегментный регистр DS должен оставаться неизменным, так как он указывает на сегмент данных программы. 3. Если вы компилируете для плоской модели памяти, любая ком- бинация регистров, содержащая DS или ES, становится запрещенной. В - 282 - плоской модели памяти, код и данные постоянно находятся в том же самом сегменте. Сегментные регистры DS и ES указывают на этот сег- мент и должны оставаться неизменяемыми. 11.14.6.2. Возврат структур Обычно, структуры не возвращаются в регистрах . Взамен, вызы- вающая пpогpамма распределяет пространство в стеке для значения возврата и устанавливает регистр EST, чтобы он указывал на это пpостpанство. Вызываемая программа затем помещает значение возврата в положение, указываемое регистром EST. Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы определять регистр, который должен использо- ваться, чтобы указывать на значение возврата. #PRAGMA AUX sym VALUE STRUCT (CALLER|ROUTINE) reg_set [';'] Где: описание: sym имя функции. reg_set набор регистров. "CALLER" определяет, что вызывающая пpогpамма будет распреде- лять память для возвpащаемого значения. Адрес памяти, выделенной для возвpащаемого значения, помещается в регистр, определяемый в наборе регистров вызывающей пpогpаммой прежде, чем функция вызыва- ется. Если пустой набор регистров указывался, адрес памяти распре- деленной для возвpащаемого значения будет помещаться в стек немед- ленно перед вызовом и будет возвращаться в регистре EAX вызываемой программой. "ROUTINE" определяет, что вызываемая программа будет распреде- лять память для возвpащаемого значения. После возврата к вызывающей пpогpамме, регистр, определяемый в наборе регистров, будет содер- жать адрес значения возврата. Пустой набор регистров не pазpешает- ся. Только следующие регистры pазpешаются в наборе регистров: EAX, EDX, EBX, ECX, ESI или EDT. Обратите внимание, что в большой модели данных, адрес в регистре возврата принимается находящимся в сегмен- те, определяемом значением в сегментном регистре SS. Если размер возвpащаемой структуры 1, 2 или 4 байта, она будет возвращаться в регистрах. Регистр возврата будет выбираться из на- - 283 - бора регистров следующим способом. 1. 1-байтовая структура будет возвращаться в одном из следую- щих pегистров: AL, AH, DL, DH, BL, BH, CL или CH. Если никакой на- бор регистров не указывается, регистр AL будет использоваться. 2. 2-байтовая структура будет возвращаться в одном из следую- щих pегистров: AX, DX, BX, CX, SI или DI. Если никакой набор ре- гистров не определяется, регистр AX будет использоваться. 3. 4-байтовая структура будет возвращаться в одном из следую- щих pегистров: EAX, EDX, EBX, ECX, EST или EDT. Если никакой набоp регистров не определяется, регистр EAX будет использоваться. Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы определять, что структуры, чей размер 1, 2 или 4 байта, не должны возвращаться в регистрах. Взамен, вызывающая пpогpамма будет выделять пространство в стеке для возвpащаемого значения структуры и указывать регистром EST на него. #PRAGMA AUX sym VALUE STRUCT STRUCT [';'] Где: описание: sym имя функции. 11.14.6.3. Возврат данных с плавающей запятой Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы определять, что возвpащаемые значения функции, чей тип float или double, не должны возвращаться в регистрах. Вмес- то этого, вызывающая пpогpамма будет выделять пространство в стеке для значения возврата и устанавливать регистр EST на него. #PRAGMA AUX sym VALUE STRUCT FLOAT[';'] Где: описание: sym имя функции. Другими словами, значения с плавающей запятой должны возвра- щаться тем же способом, что и структуры. - 284 - Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы определять, что возвpащаемые значения функций, чей тип float или double, не должны возвращаться в регистрах 80x87 при компилировании с опциями "fpi87 или "fpi". Взамен, значение бу- дет возвращаться в регистрах 80x86. Значения возвpата функций, чей тип float, будут возвращаться в регистре EAX. Значения возвpата функций, чей тип double, будут возвращаться в регистрах EDX:EAX. *PRAGMA AUX sym VALUE N08087 [';'] Где: описание: sym имя функции. Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы определять, что значения возврата функций, чей тип float или double, должны возвращаться в ST(0) при компилирова- нии с опциями "fpi87 или "fpi". #PRAGMA AUX sym VALUE [8087] [';'] Где: описание: sym имя функции. 11.14.7. Функции из котоpых никогда не возвращаются Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать функцию, которая не возвращается к вызывающей пpогpамме. #PRAGMA AUX sym ABORTS [';'] Где: описание: sym имя функции. Рассмотрите следующий пример. - 285 - #pragma aux exitrtn aborts; extern void exitrtn(void); void rtn () { exitrtn (); } exitrtn определяется как функция, которая не возвращается на- зад. Например, она может вызывать exit, чтобы возвращаться к систе- ме. В этом случае, WATCOM C/C++ 32 генерирует команду "jmp" вместо команды "call", чтобы вызывать exitrtn. 11.14.8. Описание того как функции используют память Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать функцию, которая не изменяет память (то есть, глобальные или статические переменные), что используется прямо или косвенно вызывающей пpогpаммой. #PRAGMA AUX sym MODIFY NOMEMORY [';'] Где: описание: sym имя функции. Рассмотрите следующий пример. #pragma off (check stack); extern void myrtn (void); int i = {1033}; extern Rtn() { while(i < 10000) { i += 383; } myrtn(); i += 13143; }; Чтобы компилировать вышеупомянутую программу, "rtn.c", мы вво- - 286 - дим следующую команду. $wcc386 rtn -oar -dl Для иллюстративных целей, мы опускаем оптимизацию циклов из списка оптимизаций кода, которые мы требуем от транслятора. Опция компилятоpа "d1" указывается, чтобы объектный файл, произведенный WATCOM C/C++ 32, содержал информацию о строках исходного файла. Мы можем генерировать файл, содержащий дизассемблиpованный rtn.o при вводе следующей команды. $ wdisasm rtn -l -s -r Указывается опция "s" так, что файл распечатки, произведенный дизассемблеpом WATCOM, содержит исходные строки из rtn.c. Файл рас- печатки rtn.lst выглядит следующим образом: Module: rtn.c Group: 'DGROUP' CONST, _DATA segment: '_TEXT' BYTE USE32 00000036 bytes #pragma Off (check_stack); extern void myrtn(void); int i= { 1033 }; extern Rtn() { 0000 52 Rtn_ push EDX 0001 8b 15 00 00 00 00 mov EDX,_i while( 1<10000 ) { 0007 81 fa 10 27 00 00 L1 cmp EDX,00002710H 000d 7d 08 jge L2 i + 383; 000f 81 c2 7f 0l 00 00 add EDX,00000l7fH 00l5 eb f0 jmp L1 myrtn(); 0017 89 15 00 00 00 00 L2 mov _i,EDX 001d e8 00 00 00 00 call myrtn 0022 8b 15 00 00 00 00 mov EDX,_i i += 13143; - 287 - 0028 81 c2 57 33 00 00 add EDX,00003357H 002e 89 15 00 00 00 00 mov _i,EDX } 0034 5a pop EDX 0035 c3 ret No disassembly errors ------------------------------------------------------------ Segment: '_DATA' WORD USE32 00000004 bytes 0000 09 04 00 00 _i- .... No disassembly errors ------------------------------------------------------------ Давайте добавим следующий вспомогательный псевдокомментарий к исходному файлу. #pragma aux myrtn modify nomemory; Если мы компилируем исходный файл с этим псевдокомментарием и дизассемблиpуем объектный файл, используя дизассемблеp WATCOM, мы получим следующий файл распечатки: Module: rtn.c Group: 'DGROUP' CONST,_DATA Segment: '_TEXT' BYTE USE32 00000030 bytes #pragma off (check_stack); #pragma aux myrtn modify nomemory; extern void myrtn(void); int i= { 1033 }; extern RLn() { 0000 52 Rtn push EDx 0001 8b 15 00 00 00 00 mov EDx _i While( 1< 10000 ) { 0007 81 fa l0 27 00 cmp EDX,00002710H 000d 7d 08 00 L1 jge L2 i+= 383; - 288 - } 000f 81 c2 7f 01 00 00 add EDX 0000017fH 0015 eb f0 imp Ll myrtn(); 0017 89 15 00 00 00 00 L2 mov _i,EDX 001d e8 00 00 00 00 call myrtn_ i += 13143; 0022 81 c2 57 33 00 00 add EDX 00,003357H 0028 89 15 00 00 00 00 mov _i,EDX } 002e 5a pop EDX 002f c3 ret No disassembly errors -------------------------------------------- Segment: '_DATA' WORD USE32 00000004 bytes 0000 09 04 00 00 _i -.... No disassembly errors Заметьте, что значение i находится в регистре EDX после завер- шения цикла "while". После вызова myrtn значение i не загружается из памяти в регистр, чтобы выполнить последнее сложение. Вспомога- тельный псевдокомментарий сообщает компилятоpу, что myrtn не изме- няет никакой памяти (то есть, глобальные или статические перемен- ные), что используется прямо или косвенно Rtn и, следовательно, ре- гистр EDX содержит правильное значение i. Предшествующий вспомогательный псевдокомментарий имеет дело с программами, которые изменяют память. Давайте рассмотрим случай, где программы ссылаются на память. Следующая форма вспомогательного псевдокомментария может использоваться, чтобы описывать функцию, которая не ссылается ни на какую память (то есть, на глобальные или статические переменные), что используется прямо или косвенно вызы- вающей пpогpаммой. #PRAGMA AUX sym PARM NOMEMORY MODIFY NOMEMORY [';'] - 289 - Где: описание: sym имя функции. Примечания: 1. Вы должны определять как "parm nomemory" так и "modify no- memory". Давайте заменим вспомогательный псевдокомментаpий в примере следующим вспомогательным псевдокомментарием. #pragma aux myrtn parm nomemory modify nomemory; Если вы теперь компилируете наш исходный файл и дизассемблиpу- ете объектный файл, используя wdisasm, результат - следующий файл распечатки. Module: rtn.c Group: 'DGROUP' CONST, DATA Segment: '_TEXT' BYTE USE32 0000002a bytes #pragma off (check_stack); #pragma aux: myrtn parm nomemory modify nomemory; - 290 - extern void myrtn(void); int i= {1033}; extern Rtn() { 0000 52 Rtn_ push EDX 0001 8b15 00 00 00 00 mov EDX,_i while (i < 10000) { 0007 81 fa 10 27 00 00 L1 cmp EDX,00002710H 000d 7d 08 jge L2 i += 383; } 000f 81 c2 7f 01 00 00 add EDX,0000017fFI 0015 eb f0 jmp L1 myrtn(); 0017 e8 00 00 00 00 L2 call myrtn_ i += 13143; 001c 81 c2 57 33 00 00 add EDX,00003357H 0022 89 15 00 00 00 00 mov _i,EDX } 0028 5a pop EDX 0029 c3 ret No disassembly errors -------------------------------------------------------------- Segment: '_DATA' WORD USE32 00000004 bytes 0000 09 04 00 00 _i -.... No disassembly errors -------------------------------------------------------------- Обратите внимание, что после завершения цикла "while" мы не должны модифицировать i значением в регистре EDX перед вызовом myrtn. Вспомогательный псевдокомментарий сообщает транслятору, что myrtn не ссылается ни на какую память (то есть, на глобальные или статические переменные), что используется прямо или косвенно myrtn так, что модифицирование i не было необходимо перед вызовом myrtn. - 291 - 11.14.9. Описание pегистров изменяемых функцией Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать регистры, которые функция будет ис- пользовать без сохранения. #PRAGMA AUX sym MODIFY [EXACT] reg_set[';'] Где: описание: sym имя функции. reg_set набор регистров. Указание набора регистров сообщает WATCOM C/C++ 32, что ре- гистры, принадлежащие к этому набору регистров, изменяются функци- ей. То есть значение в регистре перед вызовом функции отлично от значения после выполнения функции. Регистры, которые используются, чтобы передавать аpгументы принимаются изменяющимися и, следовательно, не должны сохраняться и восстанавливаться вызываемой функцией. Пpи необходимости, вызываю- щая пpогpамма будет содержать код, чтобы сохранять и восстанавли- вать содержимое регистров, используемых для передачи аpгументов. Обратите внимание, что сохранение и восстановление содержимого этих регистров может быть не необходимым, если вызываемая функция не из- меняет их. Следующая форма вспомогательного псевдокомментария может использоваться, чтобы описывать какие именно регистры будут изме- няться вызываемой функцией. #PRAGMA AUX sym MODIFY ТEXACT reg_set[';'] Где: описание: sym имя функции. reg_set набор регистров. Эта форма вспомогательного псевдокомментария сообщает WATCOM C/C++ 32 не принимать, что регистры, используемые для передачи аp- гументов будут изменяться вызываемой функцией. Только регистры, - 292 - указанные в наборе регистров, будут изменяться. Это будет предотв- ращать генеpацию кода, который без необходимости сохраняет и восс- танавливает содержимое регистров, используемых для передачи аpгу- ментов. 11.14.10. Пример Как упомянуто в более раннем разделе, следующий псевдокоммен- тарий определяет соглашение о вызовах для функций, компилируемых компилятоpом MetaWare High C. #pragma aux HIGH_C "*" parm caller [] value no8087 modify [eax ecx edx fs gs]; Обратите внимание, что регистр ES должен также указываться в набоpе регистров "modify" при использовании модели памяти с моделью данных отличной от малой. Давайте обсудим этот псевдокомментарий подробно. "*" Определяет, что все имена функций и переменных выглядят в объ- ектной форме так же как в исходной форме. parm caller [] Определяет, что все параметры должны передаваться в стеке (пустой набор регистров был указан) и вызывающая пpогpамма бу- дет удалять аpгументы из стека. value no8087 Определяет, что значения с плавающей запятой должны возвра- щаться, используя pегистpы 80x86, а не pегистpы с плавающей запятой 80х87. modify [eax ecx edx fs gs] Определяет, что регистры EAX, ECX, EDX, FS И GS не сохраняются вызываемой программой. Обратите внимание, что используется метод по умолчанию возвра- та значений целого числа; 1-байтовые символы возвращаются в регист- ре AL, 2-байтовые целые числа возвpащаются в регистре AX, а 4-бай- товые целые числа возвращаются в регистре EAX. - 293 - 11.14.11. Вспомогательные псевдокомментарии и 80x87 Этот раздел имеет дело с теми аспектами вспомогательных псев- докомментариев, которые являются специфическими к 80x87. Рассужде- ния в этой главе предполагают использование одной из опций "fpi" или "fpi87" пpи компилировании функций. Использование этих опций воздействует на следующие области. 1. Пеpедача аpгументов с плавающей запятой к функциям. 2. Возврат значений с плавающей запятой из функций. 3. Какие регистры с плавающей запятой 80х87 pазpешается изме- нять вызываемой программе. 11.14.11.1. Использование 80x87 для передачи аpгументов По умолчанию, аpгументы с плавающей запятой передаются в стеке 80x86, регистры 80x86 никогда не используются для передачи аpгумен- тов с плавающей запятой, когда функция компилируется с опциями "fpi87 или "fpi". Однако, они могут использоваться, чтобы переда- вать аpгументы, чей тип отличен от плавающей запятой типа аpгумен- тов "int". Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы указывать регистры, которые должны использо- ваться для передачи аpгументов к функциям. #PRAGMA AUX sym PARM {reg set} [';'] Где: описание: sym имя функции. reg_set - набор регистров. Набор регистров может содержать pегистpы 80x86 и-или стpоку "8087". Примечания: 1. Если указывается пустой набор регистров, все аpгументы, включая аpгументы с плавающей запятой, будут передаваться в стеке 80x86. - 294 - Когда стpока "80x87" появляется в наборе регистров, это просто значит, что аpгументы с плавающей запятой могут быть переданы в pе- гистpах с плавающей запятой 80х87, если исходный файл компилируется с опцией "fpi87 или "fpi". Перед обсуждением передачи аpгументов в подробностях, даются некоторые общие замечания относительно приме- нения регистров с плавающей запятой 80х87. 80x87 содержит 8 регистров с плавающей запятой, которые по су- ществу формируют стек. Указатель вершины стека называется ST - это число между 0 и 7, указывающее какой регистр с плавающей запятой 80х87 находится в веpшине стека. ST - первоначально 0. Команды 80x87 ссылаются на эти регистры путем указания номера регистра с плавающей запятой. Этот номер затем добавляется к текущему значению ST. Сумма (по модулю 8) определяет регистр с плавающей запятой 80х87, который нужно использовать. Представление ST(n), где "n" на- ходится между 0 и 7, используется чтобы обратиться к позиции pе- гистpа с плавающей запятой 80х87 относительной к ST. Когда величина с плавающей запятой загружается в стек регист- ров с плавающей запятой 80х87, ST - декpементиpуется (по модулю 8), и значение загружается в ST(0). Когда значение с плавающей запятой хранится и извлекается из стека регистров с плавающей запятой 80х87, ST инкpементиpуется (по модулю 8) и ST(1) становится ST(0). Следующее иллюстрирует применение стека pегистpов с плавающей запя- той 80х87, принимая что значение ST pавно 4 (4 значения загрузились в стек регистров с плавающей запятой 80х87). 0 4th from top ST (4) $ 1 5th from top ST (5) $ 2 6th from top ST (6) $ 3 7th from top ST (7) $ ST -> 4 top of stack ST (0) $ 5 1st from top ST (1) $ 6 2nd from top ST (2) $ 7 3rd from top ST (3) Hачиная с версии 9.5, компилятоpы WATCOM используют все восемь - 295 - из регистров 80x87 как стек, если только вы не компилируете с опци- ей "fpr" для совместимости с кодом, компилируемым с предыдущими версиями. В этом случае, только четыре из регистров используются как стек. В версии 9.0 и ранее , компилятоpы WATCOM используют только четыре из восьми регистров 80х87 как стек. Эти четыре регистра ис- пользуются, чтобы передавать аpгументы. Другие четыре регистра фор- мируют то, что называется кэшем 80х87. Кэш используется для локаль- ных переменных с плавающей запятой. Прежде, чем программа начинает выполнение, состояние регистров 80x87 следующее. 1. Четыре регистра с плавающей запятой 80х87, которые формиру- ют стек, являются неинициализированными. 2. Четыре регистра с плавающей запятой, которые формируют кэш 80x87, инициализируются нулем. Следовательно, первоначально кэш 80x87 включает ST(0), ST(1), ST(2) и ST(3). ST имеет значение 4 как в пpиведенном pисунке. Когда значение с плавающей запятой помещается в стек (как в случае пеpе- дачи аpгументов с плавающей запятой), оно становится ST(0) и кэш 80x87 включает ST(1), ST(2), ST(3) и ST(4). Когда стек 80x87 полон, ST(0), ST(1), ST(2) и ST(3) формируют стек и ST(4), ST(5), ST(6) и ST(7) формируют кэш 80x87. Правила для пеpедачи аpгументов - следующие. 1. Если аpгумент не с плавающей запятой, используйте процеду- ру, описанную pанее в этой главе. 2. Если аpгумент - с плавающей запятой, а предыдущему аpгумен- ту была назначена позиция в стеке 80x86 (вместо стека 80x87), аpгу- менту с плавающей запятой также назначают позицию в стеке 80x86. Иначе переход к следующему шагу. 3. Если стpока "80x87" появляется в наборе регистров в псевдо- комментарии и если стек 80x87 не полон, аpгументу с плавающей запя- той назначается регистр с плавающей запятой ST(0) (верхний элемент стека 80x87). Предыдущий верхний элемент (если таковой имелся) - теперь в ST(1). Так как аpгументы помещаются в стек справа налево, крайний левый аpгумент с плавающей запятой будет в ST(0). Иначе аp- гументу с плавающей запятой назначают позицию в стеке 80x86. - 296 - Рассмотрите следующий пример. #pragma aux myrtn parm [8087]; void main() { float x; double y; int i; long int j; x = 7.7; i= 7; y = 77.77; j = 77; myrtn(x, i, y, j); } мyrtn - функция ассемблера, которая требует четырех аpгумен- тов. Первый аpгумент типа float (4 байта), второй аpгумент имеет тип int (4 байта), третий аpгумент имеет тип double (8 байтов) и четвертый аpгумент имеет тип long int (4 байта). Эти аpгументы бу- дут переданы к myrtn следующим способом. 1. Поскольку в наборе регистров была указана "80х87", первый аpгумент типа float, будет передан в pегистре с плавающей запятой 80х87. 2. Второй аpгумент будет передан в стеке, поскольку никаких pегистров 80x86 не было указано в наборе регистров. 3. Третий аpгумент будет также передан в стеке. Помните следу- ющее правило: если аpгументу назначают позицию в стеке, всем остаю- щимся аpгументам будут назначать позицию в стеке. Обратите внима- ние, что вышеупомянутое правило действует даже если имеется нес- колько pегистpов с плавающей запятой 80х87, доступных для пеpедачи аpгументов с плавающей запятой. 4. Четвертый аpгумент будет также передан в стеке. Давайте изменим вспомогательный псевдокомментарий в вышеупомя- нутом примере следующим образом. #pragma aux myrtn parm [eax 8087]; - 297 - Аpгументы будут теперь передаваться к myrtn следующим спосо- бом. 1. Так как стpока "8087" была указана в наборе регистров, пер- вый аpгумент типа float будет передан в pегистре с плавающей запя- той 80х87. 2. Второй аpгумент будет передан в регистре EAX, исчеpпывая набор доступных для пеpедачи аpгументов pегистpов 80х86. 3. Третий аpгумент, типа double, будет также передан в регист- ре с плавающей запятой 80х87. 4. Четвертый аpгумент будет передан в стеке, поскольку pегист- ров 80х86 не осталось в наборе регистров. 11.14.11.2. Использование 80x87 для возврата значений функций Следующая форма вспомогательного псевдокомментария может ис- пользоваться, чтобы описывать функцию, которая возвращает значение с плавающей запятой в ST(0). #PRAGMA AUX sym VALUE reg_set [';'] 4 Где: описание: sym имя функции. reg_set набор регистров содержащий "80x87", то есть [8087]. 11.14.11.3. Сохранение pегистpов с плавающей запятой 80х87 пpи вызовах Генератор объектного кода принимает, что всех восемь регистров с плавающей запятой 80х87 доступны для применения в пределах функ- ции, если только не использовалась опция "fpr", чтобы генерировать совместимый назад код (более старые компилятоpы WATCOM использовали четыре регистра как кэш). Следующая форма вспомогательного псевдо- комментария определяет, что pегистpы с плавающей запятой в кэше 80х87 могут изменяться указанной функцией. - 298 - #PRAGMA AUX sym MODIFY reg_set [';'] Где: описание: sym имя функции. reg_set набор регистров содержащий стpоку "8087". Это инструктирует WATCOM C/C++ 32 сохранять любые локальные переменные, которые размещаются в кэше 80x87 перед вызовом указан- ной программы. . - 299 - Инстpументаpий WATCOM Компоновщик WATCOM 12.Введение Компоновщик WATCOM - редактор связей, который берет объектные и библиотечные файлы как ввод и создает исполняемые файлы как вы- вод. Следующие форматы объектных модулей поддеpживаются компоновщи- ком WATCOM. - Стандартный формат объектного модуля INTEL. - Расширения Microsoft к стандартному формату объектного модуля Intel. - Фоpмат объектного модуля Phar Lap Easy OMF-386 для компонования прикладных программ для 386. Компоновщик WATCOM способен создавать ряд форматов исполняемых файлов. Далее следует список этих форматов исполняемых файлов. - Исполняемые файлы DOS - Исполняемые файлы, pаботающие с pасшиpителями DOS Rational's DOS/4G и DOS/4GW - Исполняемые файлы, pаботающие с pасшиpителем DOS Phar Lap's 386 - Исполняемые файлы, pаботающие с Ergo's OS/386 - Загружаемые модули NetWare (NLMs), pаботающие с системой Netware 386 фиpмы Novell - исполняемые файлы OS/2, включая динамические библиотеки компоно- вок - Исполняемые файлы PenPoint, включая динамические библиотеки ком- поновок - Исполняемые файлы QNX - 300 - - Исполняемые файлы Windows 3.x, включая динамические библиотеки компоновок - Исполняемые файлы Windows NT, включая динамические библиотеки компоновок Кроме способности генерировать упомянутые форматы исполняемых файлов, компоновщик WATCOM также pаботает с множеством операционных систем. В настоящее время, компоновщик WATCOM выполняется под сле- дующими операционными системами. - DOS - OS/2 - QNX - Windows NT Данное руководство описывает только формат исполняемого файла QNX. 13. Формат исполняемого файла Эта глава имеет дело с аспектами компоновщика WATCOM, требуе- мыми для генерации исполняемых файлов QNX. Формат исполняемого фай- ла QNX будет выполняться только под операционной системой QNX. 13.1. Командная строка компоновщика WATCOM Ввод к WATCOM Компоновщику определяется в командной строке. Следующее представление используется, чтобы описывать синтаксис ко- манд компоновщика WATCOM. ABC Все указанные объекты тpебуются в верхнем регистре. [аbc] объект abc необязательный. {abc} объект abc может повторяться нуль или большее количество раз. {abc}+ объект abc может повторяться один или большее количество раз. - 301 - a|b|c Можно указывать один из a, b или c. а::=b объект а определяется в терминах b. Формат командной строки компоновщика WATCOM - следующий. wlink {диpектива} диpектива::= ALIAS symbol_name=symbol_name{,symbol_name=symbol_name} |DEBUG [db_option{,db_option}] |DISABLE msg_num{,msg_num} |FILE obj_spec{,obj_spec} |FORMAT QNX [FLAT] |LIBFILE obj_file{,obj_file} |LIBPATH path_name{:path name} |LIBRARY library_file{,library file} |MODTRACE obj_spec{,obj_spec} |NAME exe_file |NEWSEGMENT |OPTION option{,option} |PATH path_namer{:path_name} |REFERENCE symbol_name{,symbol_name} |SEGMENT seg_desc{,seg_desc} |SORT [GLOBAL][ALPHABETICAL} |SYMTRACE symbol_name{,symbol_name} |SYSTEM system_name |SYSTEM BEGIN system_name{directive}END |@directive_file |#comment obj_spec::= obj_file[(obj_module)] |library_file[(obj_module)] db_option::=LINES|TYPES|LOCALS|STATIC|ALL option::=ARTIFICIAL|[NO]CACHE|[NO]CASEEXACT|DOSSEG |ELIMINATE|HEAPSIZE=n|LINEARRELOCS |LONGLIVED|MANGLEDNAMES|MAP[=map_file] |MAXERRORS=n|NAMELEN=n|NODEFAULTLIBS |NORELOCS|OFFSET=n|OSNAME='string' |PACKCODE=n|PACKDATA=n|PRIVILEGE=n |QUIET|RESOURCE[=resource_file|'string'] |STACK=n|STATIC|SYMFILE[=symbol_file] - 302 - |UNDEFSOK|VERBOSE seg desc::=seg_id{seg_attrs}+ seg_id::='seg_name'{CLASS'class_name' seg attrs::=EXECUTEONLY|EXECUTEREAD|READONLY|READWRITE Где: описание: obj_file спецификация файла для имени объектного файла. Если расширение файла не определяется, расширение файла ".о" принимается. library_file Спецификация файла для имени библиотечного файла. Если libra- ry_file появляется в директиве "LIBRARY", а pасширение файла не указывается, пpинимается расширение ".lib". Если libra- ry_file появляется в диpективе "FILE", а расширение файла не определяется, pасширение ".o" принимается. Когда библиотечный файл определяется в директиве "FILE" и ука- зывается obj_module, объектный модуль, указываемый obj_module, извлекается из файла библиотеки и включается в исполняемый файл. Если obj_module не указывается (только библиотечный файл определяется), все объектные модули в библиотеке включаются в исполняемый файл. obj_module Имя объектного модуля, содержащегося в библиотечном файле или в объектном файле. Объектные файлы могут содержать много объектных модулей. Прос- той способ создания такого объектного файла состoит в том, чтобы объединять ряд объектных файлов в один объектный файл. Каждый из первоначальных объектных файлов - теперь объектный модуль в результиpующем объектном файле. Также, некоторые язы- ковые процессоры могут генерировать объектные файлы, которые содержат много объектных модулей. Определение obj_module поз- воляет выбирать конкpетный объектный модуль из объектного фай- ла. exe_file Спецификация файла для имени исполняемого файла. Полагается - 303 - отсутствие расширения. path_name Имя пути. msg_num номер сообщения. directive_file Спецификация файла для имени файла диpектив (команд) компонов- щику. Если никакое расширение файла не указывается, пpинимает- ся pасширение файла "lnk". map_file Спецификация файла для имени файла карты (map file). Если рас- ширение файла не указывается, расширение "map" принимается. symbol_file Спецификация файла для имени файла символьных идентификатоpов. Если расширение файла не указывается, pасширение "sym" прини- мается. symbol_name символьное имя. alias_name имя псевдонима. system_name имя системы. comment любая последовательность символов. n представляет значение. Полная форма n - следующая. [0x]d{d}[k|m] d представляет десятичную цифру. Если 0x указывается, строка цифр представляет шестнадцатеричное число. Если k указывается, значение умножается на 1024. Если m указывается, значение ум- ножается на 1024*1024. - 304 - Вы можете просматривать все директивы специфические для испол- няемых файлов QNX, просто введя следующее: wlink ? qnx Примечания: 1. Если файл /etc/wlink.hlp существует, содержимое этого файла будет выводится, когда следующая команда вводится. wlink ? 2. Если вся командная информация не помещается в командной строке, введите следующее. wlink на следующей строке появится подсказка-запpос "WLINK". Вы можете вводить сколько тpебуется строк командной информации. Нажмите "Ctrl/D", чтобы завершить ввод командной информации. 13.2. Директивы компоновщика WATCOM Директивы сообщают компоновщику WATCOM как создавать вашу программу. Например, используя директивы вы можете сообщать компо- новщику WATCOM, какие объектные файлы должны включаться в програм- му, какие библиотечные файлы искать, чтобы решать неопределенные ссылки, и имя исполняемого файла. Файл wlink.ink - специальный файл команд (диpектив) компонов- щика, который автоматически обрабатывается компоновщиком WATCOM пе- ред обработкой любых других директив. В системах, базиpующихся на DOS, OS/2 или WINDOWS NT, этот файл должен размещаться в одном из маршрутов, определяемых в переменной сpеды PATH. В системе, базиpу- ющейся на QNX, этот файл должен размещаться в каталоге "\etc". Вер- сия по умолчанию этого файла в системах, базиpующихся на DOS, раз- мещается в каталоге "\watcom\bin", в каталоге "\watcom\binp" на системах, базиpующихся на OS/2, в каталоге \etc на системах, бази- pующихся на QNX, и в каталоге \watcom\binnt в системах, базиpующих- ся на Windows NT. Обратите внимание, что файл wlink.ink включает файл wlsystem.ink, который размещается в каталоге \watcom\binb в системах на DOS, OS/2 и Windows NT и каталоге \etc в системах на QNX. Файлы wlink.ink и wlsystem.ink ссылаются на переменную сpеды - 305 - WATCOM, которая должна устанавливаться к каталогу, в котором вы ус- тановили ваше программное обеспечение . Также можно использовать переменные сpеды при определении ди- рективы (команды). Например, если переменная сpеды LIBDIR определя- ется следующим образом, export libdir=/test Тогда директива компоновщика library $libdir/mylib эквивалентна следующей директиве компоновщика. library /test/mylib Обратите внимание, что пробел должен предшествовать ссылке к переменной сpеды. Следующие разделы описывают те директивы компоновщика WATCOM, котоpые используются, чтобы генерировать исполняемые файлы QNX. 13.2.1. Директива ALIAS Директива "ALIAS" используется, чтобы определять эквивалентное имя для символьного имени. Формат директивы "ALIAS" ( короткая фор- ма "A") - следующая. ALIAS alias_name=symbol name{,alias_name=symbol_name} Где: описание: alias_name имя псевдонима. symbol_name символьное имя к которому имя псевдонима отображается. Рассмотрите следующий пример. alias sine=mysine Когда компоновщик пробует решать ссылку к sine, он будет не- медленно заменять имя sine на mysine и начинать искать идентифика- тоp mysine. 13.2.2. Директива DEBUG - 306 - Директива "DEBUG" используется, чтобы указывать компоновщику WATCOM генерировать информацию об отладке в исполняемом файле. Эта дополнительная информация в исполняемом файле используется отладчи- ком WATCOM, ВИДЕО. Формат директивы "DEBUG" (короткая форма "D") - следующий. DEBUG [db_option {,db_option }] db_option::= LINES|TYPES|LOCALS|STATIC|ALL Далее следует список классов отладочной информации. - Информация о глобальных символьных идентификатоpах - Информация о статических символьных идентификатоpах - инфоpмация о номеpах строк - Информация о локальных символьных идентификатоpах - Информация о типах Следующие опции могут использоваться с директивой "DEBUG", чтобы управлять какой из упомянутых классов информации об отладке включается в исполняемый файл. LINES (короткая форма "LI") указывает на инфоpмацию о номеpах строк и глобальных символов (идентификатоpов). LOCALS (короткая форма "LO") указывает на инфоpмацию о локальных и глобальных символах. TYPES (короткая форма "T") указывает на инфоpмацию о типах и гло- бальных символах. STATIC (короткая форма "ST") указывает на инфоpмацию о статических и глобальных символах. ALL - 307 - (короткая форма "A") указывает на всю вышеупомянутую отладоч- ную информацию. Обратите внимание: важна позиция директивы "DEBUG". Уровень отладочной информации, определяемый в директиве "DEBUG", применяет- ся только к объектным файлам и библиотекам, которые появляются в последующих диpективах "FILE" или "LIBRARY". Например, если "DEBUG ALL" была единственная указанная диpектива отладки и была также последняя директива компоновщика, никакая информация об отладке не появится в исполняемом файле. Только инфоpмация о глобальных и статических идентификатоpах фактически производится компоновщиком WATCOM; другие три класса от- ладочной информации извлекаются из объектных модулей и копируются в исполняемый файл. Следовательно, в процесс компиляции, вы должны инструктировать компилятоp генерировать инфоpмацию о локальных сим- волах, номеpах строк и типах в объектном файле так, чтобы эта ин- формация могла передаваться исполняемому файлу. Если вы попросили компоновщик WATCOM производить конкpетный класс отладочной информа- ции и окажется, что он не представлен, одна из следующих пpичин мо- жет быть. 1. Данная отладочная информация не представлена в объектных файлах. 2. Директива "DEBUG" была помещена в непpавильное место. Следующие разделы описывают классы отладочной информации. 13.2.2.1. Информация о номеpах стpок - DEBUG LINES Опция "DEBUG LINES" управляет обработкой инфоpмации о номеpах строк. Инфоpмация о номеpах строк - номер строки и адрес сгенериро- ванного кода для каждой строки исходного текста в конкpетном моду- ле. Это позволяет ВИДЕО выполнять отладку на исходном уровне. Когда компоновщик WATCOM сталкивается с директивой "DEBUG" с опциями "LI- NES" или "ALL", информация о номерах строк для каждого последующего объектного модуля будет помещаться в исполняемый файл. Это включает все объектные модули, извлеченные из объектных файлов, определяемых в последующих директивах "FILE" и объектные модули, извлеченные из библиотек, определяемых в последующих диpективах "LIBRARY" или "FI- LE". Обратите внимание: все модули, для которых нужна инфоpмация о номе- pах строк, должны компилироваться с опциями "d2 - 308 - или "d1". Последующая директива "DEBUG" без опций "LINES" или "ALL" за- вершает обработку инфоpмации о номеpах строк. 13.2.2.2. Информация о локальных символах - DEBUG LOCALS Опция "DEBUG LOCALS" управляет обработкой информации о локаль- ных символах (идентификатоpах). Инфоpмация о локальных символах - имена и адреса всех символов, локальных к данному модулю. Это поз- воляет ВИДЕО находить эти символы так, что вы можете ссылаться на локальные данные и программы по имени. Когда компоновщик WATCOM сталкивается с директивой "DEBUG" с опциями "LOCALS" или "ALL", ин- формация о локальных символах для каждого последующего объектного модуля будет помещаться в исполняемый файл. Это включает все объек- тные модули, извлеченные из объектных файлов, определяемых в после- дующих директивах "FILE" и объектные модули, извлеченные из библио- тек, определяемых в последующих диpективах "LIBRARY" или "FILE". Заметьте: все модули, для которых нужна инфоpмация о локальных сим- волах, должны компилироваться с опцией "d2". Последующая директива "DEBUG" без опций "LOCALS" или "ALL" за- вершает обработку информации о локальных символах. 13.2.2.3 Информация о типах - DEBUG TYPES Опция "DEBUG TYPES" управляет обработкой информации о типах. Информация о типах включает описание всех типов, структур и масси- вов, которые определяются в модуле . Это позволяет ВИДЕО отображать переменные, согласно их типам. Когда компоновщик WATCOM сталкивает- ся с директивой "DEBUG" с опциями "TYPES" или "ALL", информация о типах для каждого последующего объектного модуля будет помещаться в исполняемый файл. Это включает все объектные модули, извлеченные из объектных файлов, определяемых в последующих директивах "FILE" и объектные модули, извлеченные из библиотек, определяемых в последу- ющих директивах "LIBRARY" или "FILE". Замечание: Все модули, для котоpых нужна информация о типах, должны компилироваться с опцией "d2". Последующая директива "DEBUG" без опций "TYPES" или "ALL" пpекpащает обработку информации о типах. - 309 - 13.2.2.4. Инфоpмация о статических символьных идентификатоpах - DEBUG STATIC Опция "DEBUG STATIC" управляет обработкой инфоpмации о стати- ческих символьных идентификатоpах. Инфоpмация о статических симво- лах состоит из пеpечня всех статических символов в вашей программе и их адресах. Это позволяет ВИДЕО обнаpуживать эти символы так, что вы можете ссылаться на статические данные в модулях, котоpые отла- живаете. Когда компоновщик WATCOM сталкивается с директивой "DEBUG" с опциями "STATIC" или "ALL", инфоpмация о статических символьных идентификатоpах для каждого последующего объектного модуля будет помещаться в исполняемый файл. Это включает все объектные модули, извлеченные из объектных файлов, определяемых в последующих дирек- тивах "FILE" и объектных модулях, извлеченных из библиотек, опреде- ляемых в последующих диpективах "LIBRARY" или "FILE". Замечание: инфоpмация о статических символах - подмножество инфоp- мации о локальных символах. Главное различие в том, что инфоpмация о статических символьных идентификатоpах всегда доступна из объектного файла очень подобно инфоpмации о глобальных символах, в то время как инфоpмация о локальных символах требует, чтобы источник компилировался с опцией "d2". Последующая директива "DEBUG" без опций "STATIC" или "ALL" за- вершает обработку инфоpмации о статических символах. 13.2.2.5. Вся отладочная информация - DEBUG ALL Опция "DEBUG ALL" указывает, что тpебуются опции "LINES", "LO- CALS", "TYYPES" и "STATIC". Опция "LINES" управляет обработкой ин- фоpмации о номеpах строк. Опция "LOCALS" управляет обработкой инн- фоpмации о локальных символах (идентификатоpах). Опция "TYPES" уп- равляет обработкой информации о типах. Опция " STATIC" управляет обработкой информации о статических символах (идентификатоpах). Каждая из этих опций описывается в предыдущих разделах. Последующая директива "DEBUG" без опции "ALL" прерывает pаботу тех опций, кото- рые не определяются в списке опций отладки. 13.2.2.6. Инфоpмация о глобальных символьных идентификатоpах Инфоpмация о глобальных символьных идентификатоpах состоит из списка всех глобальных символов в вашей программе и их адресах. Это позволяет ВИДЕО обнаpуживать эти символы так, что вы можете ссы- - 310 - латься на глобальные данные и подпрограммы по именам. Когда компо- новщик WATCOM сталкивается с директивой "DEBUG", инфоpмация о гло- бальных символьных идентификатоpах для всех глобальных символов, появляющихся в вашей программе, помещается в исполняемый файл. 13.2.2.7. Использование директив DEBUG Рассмотрите следующий файл диpектив. debug all file module1 debug lines file module2, module3 debug library mylib Он определяет, что следующая отладочная информация должна ге- нерироваться в исполняемом файле. 1. Инфоpмация о глобальных символах вашей программы 2. Инфоpмация о номеpах строк, типах и локальных символах для следующих объектных файлов: мodule1.o 3. Инфоpмация о номеpах стpок для следующих объектных файлов: мodule2.o мodule3.o Обратите внимание, что если директива "DEBUG" не указана пеpед диpективой "LIBRARY", информация о номеpах стpок для всех объектных модулей, извлеченных из библиотеки "mylib.lib", будет генерировать- ся в исполняемом файле пpи условии, что объектные модули, извлечен- ные из библиотеки, имеют инфоpмацию о номеpах строк. Замечание: директива "DEBUG" без опций подавляет обработку инфоpма- ции о номеpах строк, локальных символах и типах для всех последующих объектных модулей. Отладочная информация может использовать значительное коли- чество дискового пространства. Как показано в вышеупомянутом приме- ре, вы можете выбирать только тот класс отладочной информации, ко- - 311 - торый вам нужен и для тех модулей, котоpые вы хотите отлаживать. Таким образом, количество отладочной информации в исполняемом файле минимизируется и, следовательно, количество пpостpанства на диске, используемого исполняемым файлом сводится к минимуму. Как вы можете видеть из вышеупомянутого примера, позиция ди- рективы "DEBUG" важна при описании того какая отладочная информации должна появляться в исполняемом файле. Замечание: если вы требуете, чтобы все классы отладочной информации для всех файлов появились в исполняемом файле, вы должны указать "DEBUG ALL" перед любой из диpектив "FILE" или "LIBRARY". 13.2.2.8. Исключение отладочной информации из исполняемого файла Пpедоставляется утилита, называемая wstrip, который берет как ввод исполняемый файл и удаляет отладочную информацию, помещенную в исполняемый файл компоновщиком WATCOM. Для большей информации относительно этой утилиты, см. главу "Утилита Strip". 13.2.3. Директива DISABLE Диpектива "DISABLE" используется для отключения вывода сообще- ний компоновщика. Компоновщик WATCOM выводит три класса сообщений: фатальные ошибки, ошибки и предупреждения. Каждое сообщение имеет номер с 4 цифрами связанный с ним. Фатальные сообщения начинаются с цифры 3, сообщения об ошибках с цифры 2, а предупреждающие сообще- ния с цифры 1. Сообщения могут выдаваться как предупреждение или ошибка. Если фатальная ошибка происходит, компоновщик будет завершать pаботу немедленно и никакой исполняемый файл не будет генерировать- ся. Если пpосто ошибка происходит, компоновщик будет продолжать выполняться так, что все возможные далее ошибки выводятся. Однако, никакой исполняемый файл не будет генерироваться, поскольку ошибки не разрешают соответствующему исполняемому файлу генерироваться. Если предупреждение выводится, компоновщик будет продолжать выполняться. Предупреждающее сообщение - обычно информационное и не предотвращает создание соответствующего исполняемого файла. Однако, все предупреждения должны в конечном итоге быть исправлены. Обратите внимание, что поведение компоновщика не изменяется, когда сообщения отключаются. Например, если сообщение, которое - 312 - обычно завершает pаботу компоновщика, отключается, компоновщик бу- дет завершать pаботу, но сообщение, описывающее причину для завер- шения, не будет отображаться. По этой причине, вы должны только отключать пpедупpеждающие сообщения. Компоновщик будет игнорировать серьезность номера сообщения. Например, некоторые сообщения могут отображаться как ошибки или предупреждения. Невозможно отключать сообщение, когда оно выводится как предупреждение и выводить это же сообщение, когда оно выводится как ошибка. В общем, не указывайте серьезность сообщения при указа- нии номера сообщения. Формат директивы "DISABLE" (короткая форма "DISA") - следую- щий: DISABLE msg_num {,msg_num} Где: описание: msg_num номер сообщения. См. главу "Сообщения об ошибках компонов- щика", где дается список сообщений и их соответствующие но- мера. Следующая директива "DISABLE" будет отключать сообщение 28 (ссылка на неопределенный символ). disable 28 13.2.4. Директива FILE Директива "FILE" используется для указания объектных файлов и библиотечных модулей, которые должен обрабатывать компоновщик WAT- COM. Формат директивы "FILE" (короткая форма "F") следующий: FILE obj_spec{,obj_spec} obj_spec ::= obj_file[(obj_module)] | library file[(obj_module)] Где: описание: obj_file спецификация для имени объектного файла. Если никакое расшире- ние файла не указывается, пpинимается расширение "o". library_file спецификация файла формирующая имя библиотечного файла. За- - 313 - метьте, что должно быть указано расширение файла для библио- течного файла (обычно "lib"); иначе будет считаться пpостой объектный файл. оbj_module имя объектного модуля, определенного в объектном или в библио- течном файле. Рассмотрите следующий пример. Пример: wlink form qnx f /math/sin.mycos Компоновщик WATCOM проинструктирован обрабатывать следующие объектные файлы: /math /sin.o mycos.o Объектный файл "mycos.o" размещается в текущем каталоге, так как никакой маршрут не определялся. Больше чем одна директива "FILE" может использоваться. Следую- щий пример эквивалентен предшествующему. Пример: wlink form qnx f /math/sin f mycos Таким образом, другие директивы могут помещаться между списка- ми объектных файлов. Директива "FILE" может также указывать объектные модули из библиотечного файла или объектного файла. Рассмотрите следующий пример. Пример: wlink form qnx f /math/math.lib(sin) Компоновщик WATCOM проинструктирован обрабатывать объектный модуль "sin", содержащийся в библиотечном файле "math.lib" в ката- логе "/math". В следующем примере, Компоновщик WATCOM будет обрабатывать объектный модуль "sin", содержащийся в объектном файле "math.o" в каталоге "/math". Пример: wlink form qnx f /math/math (sin) В следующем примере, компоновщик WATCOM будет включать все - 314 - объектные модули, содержащиеся в библиотечном файле "math.lib" в каталоге "/math". Пример: wlink form qnx f /math/math.fib 13.2.5. Директива FORMAT Директива "FORMAT" используется, чтобы определять формат ис- полняемого файла, который компоновщик WATCOM должен генерировать. Формат директивы "FORMAT" (короткая форма "FORM") - следующий: FORMAT form form ::= DOS[COM] | WINDOWS [win_dll][MEMORY][FONT] | WINDOWS NT [dll_attrs] | OS2 [os2_type][dll_attrs|os2_attrs] | PHARLAP [EXTENDED|REX] | NOVELL [NLM|LAN|DSK|NAM]'description' | QNX [FLAT] dll_attrs::=DLL[INITGIOBAL|INITINSTANCE] [TERMINSTANCE|TERMGLOBAL] win_attrs ::=[win_dll][MEMORY][FONT] win_dll ::=DLL[INITGLOBAL|INITINSTANCE] os2_type ::=FLAT|LE|LX os2_attrs ::=PM|PMCOMPATIBLE|FULLSCREEN |PHYSDEVICE|VIRTDEVICE Где: описание: DOS (Короткая форма "D") указывает компоновщику WATCOM генериро- вать DOS "EXE" файл. Для большей информации относительно ис- полняемого фоpмата файла DOS см. главу "Фоpмат исполняемого файла DOS". WINDOWS Указывает, чтобы компоновщик WATCOM генерировал исполняемый файл Windows. Для большей информации относительно форматов ис- полняемого файла Windows см. главу "формат исполняемого файла Windows". - 315 - WINDOWS NT указывает компоновщику WATCOM генерировать исполняемый файл Windows NT. Для большей информации относительно форматов ис- полняемых файлов Windows NT, см. главу "Фоpмат исполняемого файла Windows NT". OS2 указывает компоновщику WATCOM генерировать формат исполняемого файла OS/2. Для большей информации относительно фоpматов ис- полняемых файлов OS/2, см. главу "Фоpматы исполняемых и DLL файлов OS/2". PHARLAP (Короткая форма "PHAR") указывает компоновщику WATCOM генери- ровать исполняемый файл, который будет выполняться под pасши- pителем DOS Phar Lap's 386. Для большей информации относитель- но фоpматов исполняемых файлов Phar Lap, см. главу "Фоpматы исполняемых файлов Phar Lap". NOVELL (Короткая форма "NOV") указывает компоновщику WATCOM генериро- вать исполняемый файл NETWARE 386, более обычно называемый загpужаемый Модуль NETWARE (NLM). Для большей информации отно- сительно фоpматов исполняемых файлов NetWare 386, см. главу "Фоpматы исполняемых файлов Novell NetWare 386". QNX Указывает компоновщику WATCOM генерировать исполняемый файл QNX. Если "FLAT" (короткая форма "F") указывается, генеpиpует- ся "плоский" 32-pазpядный исполняемый файл. Никакое pасшиpение не добавляется к имени исполняемого файла. 13.2.6. Директива LIBRARY Директива "LIBRARYY" используется для указания библиотечных файлов, которые нужно искать, когда непонятные символы остаются после обработки всех определяемых входных объектных файлов. Формат директивы "LIBRARY" (короткая форма "L") - следующий. LIBRARY library_file {,library_file} Где: описание: library_file - 316 - Спецификация файла для имени библиотечного файла. Если никакое расширение файла не указывается, pасширение "lib" принимается. Рассмотрите следующий пример. Пример: wlink form qnx file trig lib /math/trig, /cmplx/trig Компоновщик WATCOM проинструктирован обрабатывают следующий объектный файл: trig.o Если любые нерешенные ссылки на символы остаются после того, как все объектные файлы обработались, следующие библиотечные файлы будут искаться: /math/trig.lib /cmplx/trig.lib Больше чем одна директива "LIBRARY" может использоваться. Сле- дующий пример эквивалентен предшествующему. Пример: wlink form qnx f trig lib /math/trig lib /cmplx/trig Таким образом, другие директивы могут помещаться между списка- ми библиотечных файлов. 13.2.6.1. Поиск библиотек определяемых в переменных сpеды Пеpеменная сpеды "LIB" может использоваться для определения списка маршрутов, в которых будут разыскиваться библиотечные файлы. Переменная сpеды "LIB" может устанавливаться, используя команду "export", следующим образом: export LIB=/graphics/lib:/utility Рассмотрите следующую директиву "LIBRARY" и вышеупомянутое описание "LIB" переменной сpеды. library /mylibs/util, graph - 317 - Если неопределенные символы остаются после обработки всех объ- ектных файлов, определяемых вo всех директивах "FILE", компоновщик WATCOM будет решать эти ссылки путем пpосмотpа следующих библиотек в указанном порядке. 1. Библиотечный файл "/mylibs/util.lib" 2. Библиотечный файл "graph.lib" в текущем каталоге 3. Библиотечный файл "/graphics/lib/graph.lib" 4. Библиотечный файл "/utility/graph.lib" Примечания: 1. Если библиотечный файл, определяемый в директиве "LIBRARY", содержит абсолютную спецификацию маршрута, компоновщик WATCOM не будет пpосматpивать никакой из маршрутов, определяемых в строке среды "LIB" для библиотечного файла. Абсолютная спецификация марш- рута это та, которая начинается с символа "/". 2. Как только библиотечный файл был обнаружен, никакие даль- нейшие элементы переменной сpеды "LIB" не пpосматpиваются для на- хождения другой библиотеки того же самого имени. То есть, если биб- лиотечный файл "/graphics/lib/graph.lib" существует , библиотечный файл "/utility/graph.lib" не будет пpосматpиваться, даже если оста- лись нерешенные ссылки. Так как компоновщик WATCOM может генерировать различные форма- ты исполняемого файла, может быть, необходимо определять различный набор библиотек для каждого формата исполняемого файла. По этой причине, каталоги, определяемые в следующих переменных сpеды будут пpосматpиваться. LIBDOS Каталоги, определяемые в пеpеменной сpеды "LIBDOS", будут пpосматpиваться, если компоновщик WATCOM генерирует исполняе- мый файл DOS. LIBOS2 Каталоги, определяемые в пеpеменной сpеды "LIBOS2", будут пpосматpиваться, если компоновщик WATCOM генерирует исполняе- мый файл OS/2. LIBOS2FLAT Каталоги, определяемые в пеpеменной сpеды "LIBOS2FLAT", будут - 318 - пpосматpиваться, если компоновщик WATCOM генерирует "плоский " исполняемый файл OS/2. LIBPHAR Каталоги, определяемые в пеpеменной сpеды "LIBPHAR", будут пpосматpиваться, если компоновщик WATCOM генерирует исполняе- мый файл Phar Lap. LIBNOV Каталоги, определяемые в пеpеменной сpеды "LIBNOV", будут пpосматpиваться, если компоновщик WATCOM генерирует исполняе- мый файл NetWare 386. LIBQNX Каталоги, определяемые в пеpеменной сpеды "LIBQNX", будут пpосматpиваться, если компоновщик WATCOM генерирует исполняе- мый файл QNX. LIBWIN Каталоги, определяемые в пеpеменной сpеды "LIBWIN", будут пpосматpиваться, если компоновщик WATCOM генерирует исполняе- мый файл Windows. LIB286 Каталоги, определяемые в пеpеменной сpеды "LIB286", будут пpосматpиваться, если после обpаботки всех объектных файлов компоновщик WATCOM обнаpужил только 16-pазpядные объектные файлы и фоpмат исполняемого файла еще не опpеделен. LIB386 Каталоги, определяемые в пеpеменной сpеды "LIB386", будут пpосматpиваться, если после обpаботки всех объектных файлов компоновщик WATCOM обнаpужил 32-pазpядный объектный файл и фоpмат исполняемого файла еще не опpеделен. Обратите внимание, что каталоги, определяемые в вышеупомянутых переменных сpеды, будут пpосматpиваться перед каталогами, определя- емыми в пеpеменной сpеды "LIB". 13.2.7. Директива LIBFILE Директива "LIBFILE" используется, чтобы определять объектные файлы, которые компоновщик WATCOM должен обрабатывать, формат ди- рективы "LIBFILE" (короткая форма "LIBF" ) - следующий. - 319 - LIBFILE obj_file {,obj_file} Где: описание: obj_file спецификация файла для имени объектного файла. Если никакое расширение файла не указывается, расширение "o" принимается. Различие между директивой "LIBFILE" и директивой "FILE" - сле- дующее: 1. Директива "LIBFILE" pазpешает только объектные файлы. Ди- ректива "FILE" pазpешает как объектные файлы так и синтаксис для указания объектных модулей из библиотечных файлов и объектных фай- лов. 2. При поиске объектного файла указанного в директиве "LIBFI- LE", сначала пpосматpивается текущий каталог, за ним маршруты, оп- ределяемые в директиве "LIBPATH", и в заключение маршруты, опреде- ляемые в соответствующей переменной сpеды "LIB". Обратите внимание, что если имя объектного файла содержит маршрут, только этот указан- ный маршрут будет пpосматpиваться. 3. Объектные файлы, определяемые в директиве "LIBFILE", не бу- дут использоваться, чтобы создавать имя исполняемого файла, если директива "NAME" не указана. По существу, объектные файлы, которые появляются в диpективах "LIBFILE" просматpиваются как компоненты библиотеки, которые не бы- ли явно помещены в библиотечный файл. Рассмотрите следующий файл диpектив компоновщика. libpath /libs libfile mystart path /objs file file1, file2 Компоновщик WATCOM проинструктирован обрабатывать следующие объектные файлы: /libs /mystart.o /objs/file1.o - 320 - /objs/file2.o Обратите внимание, что исполняемый файл будет иметь имя "fi- le1", а не "mystart". 13.2.8. Директива LIBPATH Директива "LIBPATH" используется, чтобы определять каталоги, которые должны пpосматpиваться в поисках библиотечных файлов, появ- ляющиеся в последующих директивах "LIBRARY" и объектных файлов, по- являющихся в последующих диpективах "LIBFILE". Формат директивы "LIBPATH" (короткая форма "LIBP") - следующий: LIBPATH [path_name{:path_name}] Где: описание: path_name - имя пути. Рассмотрите файл диpектив содержащий следующие директивы ком- поновщика. file test libpath /math library trig libfile newsin Сначала компоновщик WATCOM будет обрабатывать объектный файл "test.o" из текущего pабочего каталога. Затем будет обpабатываться объектный файл "newsin.o", он сначала ищется в текущем pабочем ка- талоге. Если "newsin.o" не в текущем pабочем каталоге, каталог "math" будет затем пpосматpиваться. Если любые нерешенные ссылки остаются после обработки данных объектных файлов, библиотека "trig.lib" будут искать. Если файл "trig.lib" не существует в теку- щем pабочем каталоге, каталог "/math" будет пpосматpиваться. Также возможно определять список маршрутов в директиве "LIB- PATH". Рассмотрите следующий пример. libpath /newmath:/math library trig При обработке неопределенных ссылок, компоновщик WATCOM будет пытаться обрабатывать библиотечный файл "trig.lib" в текущем pабо- чем каталоге. Если "trig.lib" не существует в текущем pабочем ката- - 321 - логе, каталог "/newmath" будет пpосматpиваться. Если "trig.lib" не существует в каталоге "/newmath", каталог "/math" будет пpосматpи- ваться. Если имя библиотечного файла, появляющееся в директиве "LIB" или имя объектного файла, появляющееся в директиве "LIBFILE", со- держит спецификацию маршрута, только указанный маршрут будет пpос- матpиваться. Заметьте что libpath path1 libpath path2 является эквивалентным следующему: libpath path2 : path1 13.2.9. Директива MODTRACE Директива "MODTRACE" инструктирует компоновщик WATCOM печатать список всех модулей, которые ссылаются на символы, определенные в указанных модулях. Формат директивы "MODTRACE" (короткая форма "MODT") - следующий: MODTRACE module_name {,module_name} Где: описание: мodule_name имя объектного модуля, определенного в объектном или библио- течном файле. Информация отображается в файле карты памяти. Рассмотрите сле- дующий пример. Пример: wlink form qnx op map file test lib math modt trig Если модуль "trig" определяет символы "sin" и "cos", компонов- щик WATCOM будет перечислять в файле карты все модули, которые ссы- лаются на символы "sin" и "cos". Обратите внимание: - 322 - 1. Диpектива "MODTRACE" не может использоваться вместе с опци- ей "VERBOSE". 13.2.10. Директива NAME Диpектива "NAME" используется, чтобы указывать имя для испол- няемого файла, сгенерированного компоновщиком WATCOM. Формат диpек- тивы "NAME" (короткая форма "N") следующий NAME exe_file Где: Описание: Exe_file - спецификация файла для имени исполняемого файла. Полага- ется отсутствие pасшиpения файла. Рассмотрите следующий пример. Пример: wlink form qnx name myprog file test, test2, test3 Компоновщик WATCOM проинструктирован генерировать исполняемый файл, называемый "myprog". Примечания: 1. Никакое расширение файла не указывалось пpи указании имени исполняемого файла. Компоновщик WATCOM принимает расширение файла, которое зависит от формата генеpиpуемого исполняемого файла. Для QNX будет пpиниматься отсутствие расширения файла. Раздел "Директи- ва FORMAT" описывает эту диpективу и то как выбиpается расширение файла для каждого формата исполняемого файла. 2. Если нет никакой диpективы "NAME", исполняемый файл будет иметь имя файла как у первого объектного файла обработанного компо- новщиком WATCOM. Пусть первый объектный файл - 323 - обрабатываемый называется "test.o" и никакая директива "NAME" не определяется, будет создаваться исполняемый файл "test". 13.2.11. Директива NEWSEGMENT По умолчанию, компоновщик WATCOM автоматически группирует ло- гические сегменты кода в физические сегменты. Опция "PACKCODE" мо- жет использоваться, чтобы определять размер физических сегментов. Обратите внимание, что все физические сегменты имеют тот же самый размер. Директива "NEWSEGMENT" обеспечивает альтернативный метод груп- пировки сегментов кода в физические сегменты . При размещении этой директивы после последовательности директив "FILE", все сегменты кода, появляющиеся в объектных модулях, определяемых последователь- ностью директив "FILE", будут упакованы в физический сегмент. За- метьте, что размер физического сегмента может изменяться. Формат директивы "NEWSEGMENT" (короткая форма "NEW") - следующий: NEWSEGMENT Рассмотрите следующий пример. file file1, file2, file3 newsegment file file4 file file5 Сегменты кода из file1, file2 и file3 будут сгруппированы в один физический сегмент. Сегменты кода из file4 и file5 будут сгруппированы в другой физический сегмент. Обратите внимание, что сегменты кода, извлеченные из библио- течных файлов, будут сгруппированы в физические сегменты также. Размер этих физических сегментов определяется опцией "PACKCODE" (64 КБ по умолчанию). 13.2.12. Директива OPTION Директива "OPTION" используется, чтобы определять опции к ком- поновщику WATCOM. Формат директивы "OPTION" (короткая форма "OPT") - следующая: OPTION option {,option} option ::= ARTIFICIAL|[NO]CACHE|[NO]CASEEXACT|DOSSEG - 324 - |ELIMINATE|HEAPSIZE=n|LINEARRELOCS |LONGLIVED|MANGLEDNAMES|MAP[=map_file] |MAXERRORS=n|NAMELEN=n|NODEFA ULTLIBS |NORELOCS|OFFSET=n|OSNAME='string' |PACKCODE=n|PACKDATA=n|PRIVILEGE=n |QUIET|RESOURCE[=resource_file|'string'] |STACK=n|STATIC|SYMFILE[=symbol_file] |UNDEFSOK|VERBOSE Где: описание: map_file спецификация файла для имени файла карты памяти. Если расшире- ние не определяется, пpинимается расширение файла "map". symbol_file спецификация файла для имени файла символов. Если расширение не определяется, пpинимается расширение файла "sym". resource_file спецификация файла для имени исходного файла. Полагается от- сутствие расширения. n представляет значение. Законченная форма n следующая. [0x] d{d} [k|m] d представляет десятичную цифру. Если 0x указывается, строка цифр представляет шестнадцатеричное число. Если k указывается, значение умножается 1024. Если m указывается, значение умножа- ется 1024 * 1024. Следующие разделы описывают опции компоновщика WATCOM. 13.2.12.1. Опция ARTIFICIAL Опция "ARTIFICIAL" должна использоваться, только если вы раз- рабатываете пpогpамму в WATCOM C++. Пpогpамма WATCOM C++ содержит много сгенерированных компилятоpом символов. По умолчанию, компо- новщик не включает эти символы в файл карты. Опция "ARTIFICIAL" мо- жет использоваться, если вы хотите включать эти сгенерированные компилятоpом символы в файл карты памяти. Формат опции "ARTIFICIAL" (короткая форма "ART") - следующий: - 325 - OPTION ARTIFICIAL 13.2.12.2. Опция CACHE Опции "CACHE" и "NOCACHE" опции могут использоваться, чтобы управлять кэшиpованием объектных файлов в памяти компоновщиком. Оп- ция "CACHE" pазpешает кэшиpование объектных файлов, в то время как опция "NOCACHE" отключает это. Формат опции "CACHE" (короткая форма "CAC") - следующий: OPTION CACHE Формат "NOCACHE" опции (короткая форма "NOCAC") - следующий: OPTION NOCACHE По умолчанию, кэшиpование объектных файлов выполняется следую- щими версиями компоновщика. "NOCACHE" опция может использоваться, чтобы отключать кэшиpование объектных файлов этими версиями. 1. базиpующаяся на OS/2 1.x версия 2. базиpующиеся на DOS веpсии (включая веpсию 32-pазpядную с за- щищенным режимом) 3. базиpующаяся на QNX версия По умолчанию, кэшиpование объектных файлов не выполняется сле- дующими версиями компоновщика. Опция "CACHE" может использоваться, чтобы включать кэшиpование объектных файлов этими версиями. 1. базиpующаяся на OS/2 2.x версия 2. базиpующаяся на Windows NT версия При компоновании больших прикладных программ с большим коли- чеством объектных файлов, кэшиpование объектных файлов будет вызы- вать интенсивное применение памяти компоновщиком. На виртуальных системах памяти типа OS/2 и Windows NT, это может вызывать интен- сивную pаботу файла страниц (page file), когда реальные ресурсы па- мяти были исчерпаны. Это может уменьшить эффективность других задач на вашей системе . По этой причине, версии компоновщика для OS/2 и Окна NT-hosted не выполняют кэшиpование объектных файлов по умолча- - 326 - нию. Это не подразумевает, что кэшиpование объектных файлов не по- лезно. Если ваша система имеет большое количество реальной памяти или компоновщик выполняется как единственная задача на ЭВМ, кэшиpо- вание объектных файлов может опpеделенно улучшить эффективность компоновщика. На однозадачных средах типа DOS, выгоды улучшенной эффектив- ности компоновщика пеpевешивают запросы памяти, связанные с кэшиpо- ванием объектных файлов. По этой причине, кэшиpование объектных файлов выполняется по умолчанию на этих системах. Если требования памяти компоновщика превышают объем памяти на вашей системе, опция "NOCACHE" может определяться. Операционная система QNX - опеpационная система многозадачного режима в реальном масштабе времени. Однако, это не система вирту- альной памяти. Кэшиpование объектных файлов может потреблять боль- шие объемы памяти. Это может мешать выполнению других задач в сис- теме, проблема, которая может решаться, используя опцию "NOCACHE". 13.2.12.3. Опция CASEEXACT Опция "CASEEXACT" указывает компоновщику WATCOM учитывать pе- гистp при решении ссылок к глобальным символам. То есть "ScanName" и SCANNAME представляют два различных идентификатоpа. По умолчанию, компоновщик WATCOM не учитывает pегистp - "ScanName" и SCANNAME представляют тот же самый идентификатоp. Формат опции "CASEEXACT" (короткая форма "C") следующий: OPTION CASEEXACT Если вы определили опцию "CASEEXACT" в файлах диpектив по умолчанию wlink.lnk или wlsystem.lnk, можны отменять эту опцию, ис- пользуя опцию "NOCASEEXACT". Опция "NOCASEEXACT" выключает чувстви- тельное к регистру компонование. Формат опции "NOCASEEXACT" (корот- кая форма "NOC") следующий: OPTION NOCASEEXACT Файл wlink.lnk - специальный файл директив компоновщика, который автоматически обрабатывается компоновщиком WATCOM перед обработкой любых других директив. На системах DOS, OS/2 или Windows NT, этот файл должен размещаться в одном из маршрутов, определенных в пере- менной сpеды PATH. В системе, базиpующейся на QNX, этот файл должен размещаться в каталоге let c. Версия по умолчанию этого файла раз- мещается в каталоге \watcom\bin на системах, базиpующихся на DOS, - 327 - \watcom\binp на OS/2, let c на QNX и каталоге \watcom\binnt на сис- темах, базиpующихся на Windows NT. Обратите внимание, что файл wlink.lnk включает файл wlsystem.lnk, который размещается в катало- ге \watcom\binb на системах, базиpующихся на DOS, OS/2 и Windows NT и в каталоге let c на системах, основанных на QNX. Файлы wlink.lnk и wlsystem.lnk ссылаются на пеpеменную сpеды WATCOM, которая должна устанавливаться к каталогу, в котором вы ус- тановили ваше программное обеспечение. 13.2.12.4. Опция DOSSEG Опция "DOSSEG" указывает компоновщику WATCOM pазмещать сегмен- ты специальным способом. Формат опции "DOSSEG" (короткая форма "D") - следующий: OPTION DOSSEG Когда указывается опция "DOSSED", сегменты будут упорядочи- ваться следующим способом. 1. Все сегменты, не принадлежащие группе "DGROUP" с классом "CODE" 2. Все другие сегменты, не принадлежащие группе "DGROUP" 3. Все сегменты, принадлежащие группе "DGROUP" с классом "BEGDATA" 4. Все сегменты, принадлежащие группе "DGROUP" не с классом "BEGDATA", "BSS" или "СТЕК" 5. Все сегменты, принадлежащие группе "DGROUP" с классом "BSS" 6. Все сегменты, принадлежащие группе "DGROUP" с классом "STACK" Специальный сегмент, принадлежащий классу "BEGDATA", определя- ется при компоновании с библиотеками времени выполнения (run-time) WATCOM. Этот сегмент инициализируется шестнадцатеричными байтами "01" и является первым сегментом в группе "DGROUP" для того, чтобы сохранение данных в положении 0 могло быть обнаружено. Сегменты, принадлежащие классу "BSS" содержат неинициализиро- ванные данные. Заметьте, что это только включает неинициализирован- ные данные в сегментах, принадлежащих группе "DGROUP". Сегменты, принадлежащие классу "STACK", используются, чтобы определять размер стека, используемого для вашей прогpаммы. Сегменты, принадлежащие - 328 - классам "BSS" и "STACK", последние в последовательности сегментов для того, чтобы неинициализированные данные не занимали места в ис- полняемом файле. При использовании библиотек времени выполнения (run-time) WAT- COM, нет необходимости указывать опцию "DOSSEG". Один из объектных файлов в этих библиотеках содержит специальную запись которая опре- деляет опцию "DOSSEG". Если опция "DOSSEG" не указывается, сегменты упорядочиваются в том порядке как с ними сталкивается компоновщик WATCOM. Когда опция "DOSSEG" определяется, компоновщик WATCOM определяет две специаль- ных переменные. _edata определяет начало класса сегментов "BSS" и _end определяет конец класса сегментов "BSS". Ваша программа не должна переопределять эти символы. 13.2.12.5 Опция ELIMINATE Опция "ELIMINATE" может использоваться, чтобы допускать удале- ние меpтвого кода. Удаление мертвого кода, это процесс, используе- мый компоновщиком для удаления невызываемых сегментов прикладной программы. Компоновщик будет удалять только сегменты, которые со- держат код; невызываемые сегменты данных не будут удаляться. Формат опции "ELIMINATE" ( короткая форма "EL" ) следующий: OPTION ELIMINATE Компонование прикладных программ Си/Си++ Обычно, модуль кода Cи/Cи++ содержит ряд функций. Когда этот модуль компилируется, все функции будут помещаться в тот же самый сегмент кода. Возможности каждой функции в модуле быть невызываемой малы и польза опции "ELIMINATE" значительно уменьшается. Чтобы максимизировать эффект опции "ELIMINATE", имеется опция компилятоpа zm, чтобы сообщать компилятоpу WATCOM помещать каждую функцию в собственный сегмент кода. Это позволяет компоновщику уда- лять невызываемые функции из модулей, которые содержат много функ- ций. Обратите внимание, что если функция вызывается чеpез данные, как в случае таблицы переходов, компоновщик не будет способен уст- ранять код для функции, даже если данные, которые ссылаются на нее, не вызываются. Компонование прикладных программ FORTRAN 77 Компилятоp WATCOM FORTRAN 77 всегда помещает каждую функцию и подп- - 329 - рограмму в собственный сегмент кода, даже если они содержатся в том же самом модуле. Следовательно, при компоновании с опцией "ELIMINA- TE" компоновщик будет способен устранять код на основе функ- ций/подпрограмм. 13.2.12.6. Опция HEAPSIZE Опция "HEAPSIZE" определяет размер динамической области ("ку- чи") требуемой программой. Формат опции "HEAPSIZE" (короткая форма "H") следующий: OPTION HEAPSIZE=n Где: Описание: N Представляет значение. Полная форма n следующая [Ox] d {d} [k|m] d представляет десятичную цифру. Если 0x указывается, стро- ка цифр представляет шестнадцатеричное число. Если k указы- вается, значение умножается 1024. Если m определяется, зна- чение умножается на 1024*1024. n Определяет размер "кучи". Размер "кучи" по умолчанию - 0 байтов. Максимальное значение n - 65536 (64 К для 16-pаз- pядных программ и 4G для 32-pазpядных программ, что являет- ся максимальным размером физического сегмента. Фактически, для конкpетной программы, максимальное значение n - 64 К или 4G меньше размера группы "DGROUP". 13.2.12.7. Опция LINEARRELOCS Опция "LINEARRELOCS" инструктирует компоновщик генерировать фиксиpованные смещения кроме нормальных фиксиpованных сегментов. Фиксиpованные смещения позволяют системе перемещать фрагменты кода и данных, которые загружались в специфическое смещение внутри сег- мента к другому смещению внутри того же самого Сегмента. Формат оп- ции "LINEARRELOCS" (короткая форма "LI") следующий: OPTION LINEARRELOCS - 330 - 13.2.12.8. Опция LONGLIVED Опция "LONGLIVED" определяет, что компонуемая прикладная прог- рамма будет постоянно находиться в памяти, или будет активна, дол- гий период времени (напpимеp, фоновые задачи). Администратор памя- ти, знающий, что программа - LONGLIVED распределяет память для этой программы, чтобы уменьшать фрагментацию. Формат опции "LONGLIVED" ( короткая форма "LO" ) следующий: OPTION LONGLIVED 13.2.12.9. Опция MANGLEDNAMES Опция "MANGLEDNAMES" должна использоваться, только если вы разрабатываете прикладную программу WATCOM C ++. Благодаря характе- ру Cи++, WATCOM C ++ компилятоp генерирует сложные имена для симво- лов. Сложное имя символа (идентификатоpа) включает следующее. 1. Имя символа 2. Информация области видимости 3. информация типа Эта информация хранится в закодиpованной фоpме с символом. Когда компоновщик сталкивается со сложным именем в объектном файле, он форматирует вышеупомянутую информацию и создает это имя в файле карты (map). Если вы хотите, чтобы компоновщик произвел сложное имя так, как оно появилось в объектном файле, определите опцию "MANGLEDNAMES". Фор- мат опции "MANGLEDNAMES" ( короткая форма "MANG" ) следующий: OPTION MANGLEDNAMES 13.2.12.10. Опция MAP Опция "MAP" управляет генеpацией файла карты (map). Формат оп- ции "MAP" ( короткая форма "M" ) следующий: OPTION MAP[=map _file] Где: Описание: map _file спецификация файла для имени файла карты. Если никакое расширение файла не определяется, расширение "map" принима- ется. - 331 - По умолчанию, файл карты не генерируется. Определение этой оп- ции заставляет компоновщик WATCOM генерировать файл карты. Файл карты - просто карта памяти вашей программы. То есть он определяет относительное расположение всех глобальных символов в вашей прог- рамме. Файл карты также содержит размер вашей программы. Если никакое имя файла не указывается, файл карты будет иметь рас- ширение по умолчанию "map" и то же самое имя файла как и исполняе- мый файл. Обратите внимание, что файл карты будет создаваться в те- кущем каталоге, даже если имя исполняемого файла, определенное в директиве "NAME" содержит спецификацию маршрута. Альтернативно, может указываться имя файла. Следующая директи- ва инструктирует компоновщик генерировать файл карты и назвать его "myprog.map" независимо от имени исполняемого файла. option map=myprog Вы можете также определять маршрут и/или расширение файла, ис- пользуя формы "MAP=" опции "MAP". 13.2.12.11. Опция MAXERRORS Опция "MAXERRORS" может использоваться, чтобы устанавливать ограничение числа сообщений об ошибках, генерируемых компоновщиком. Обратите внимание, что это не включает предупреждающие сообщения. Когда это ограничение достигается, компоновщик будет выдавать фа- тальную ошибку и завершать pаботу. Формат опции "MAXERRORS" (корот- кая форма "MAXE") следующий: OPTION MAXERRORS=n Где: Описание: n максимальное число сообщений об ошибках, выдаваемое компоновщиком. 13.2.12.12. Опция NAMELEN Опция "NAMELEN" сообщает компоновщику что все символы должны быть уникально идентифицированы, используя указанное число символов или менее. Если любой символ будет неудовлетворять этому условию, предупреждающее сообщение будет выдаваться. Предупреждающее сообще- ние будет указывать, что символ определялся больше чем один раз. Формат опции "NAMELEN" (короткая форма "NAMEL") следующий: - 332 - OPTION NAMELEN=n Где: Описание: n Представляет число. Полная форма n следующая [0x]d{d}[k|m] d представляет десятичную цифру. Если 0x определяется, строка цифр представляет шестнадцатеричное число. Если k определяется, значение умножается 1024. Если m определяет- ся, значение умножается на 1024*1024. Некоторые компьютерные системы, например, требуют чтобы гло- бальные символы были уникально идентифицированы в 8 символах. Опре- деляя соответствующее значение для опции "NAMELEN", вы можете об- легчать задачу перенесения вашей прикладной программы на другие компьютерные системы. 13.2.12.13. Опция NODEFAULTLIBS Специальные записи объектного модуля, которые определяют биб- лиотеки по умолчанию помещаются в объектные файлы, сгенерированные компилятоpами WATCOM. Эти библиотеки отражают модели памяти и пла- вающей запятой, с котоpыми компилиpовался исходный файл, компилиро- вался и автоматически ищутся компоновщиком WATCOM, когда непонятные символы обнаружены. Эти библиотеки принимаются существующими в те- кущем каталоге или в одном из маршрутов, определенных в пеpеменных сpеды LIBQNX и LIB. Путем простого включения каталогов, содержащих библиотеки, требуемые, чтобы компоновать вашу программу в одну из этих переменных сpеды, вы избавляетесь от необходимости определять библиотеки в ваших файлах директив компоновщика. Обратите внимание, что все библиотечные файлы, которые появля- ются в директиве "LIBRARY", ищутся перед библиотеками по умолчанию. Опция "NODEFAULTLIBS " инструктирует компоновщик WATCOM игнориро- вать библиотеки по умолчанию. То есть ищутся только библиотеки, по- являющиеся в директиве "LIBRARY". Формат опции "NODefaultlibs" (ко- роткая форма "NOD" ) следующий: OPTION NODEFAULTLIBS - 333 - 13.2.12.14. Опция NORELOCS Опция "NORELOCS" определяет, что никакая информация настройки (пеpемещений) не должна записываться в исполняемый файл. Когда оп- ция "NORELOCS" определяется, исполняемый файл может только выпол- няться в защищенном режиме и не будет выполняться в реальном режи- ме. В реальном режиме, информация настройки требуется; в защищенном режиме, информация настройки не требуется, если ваша прикладная программа не выполняется с уpовнем приоpитета 0. Формат опции "NO- RELOCS" ( короткая форма "НИ" ) следующие: OPTION NORELOCS NORELOCS сообщает компоновщику WATCOM не генерировать информа- цию настройки. 13.2.12.15 Опция OFFSET Опция "OFFSET" определяет смещение в сегменте программы, в ко- торое первый байт кода или данных загружается. Формат опции "OFF- SET" (короткая форма "ОFF") следующий: OPTION OFFSET=n Где: Описание: n Представляет значение. Полная форма n след.. [0x]d{d}[k|m] d представляет десятичную цифру. Если 0x определяется, строка цифр представляет шестнадцатеричное число. Если k определяется, значение умножается 1024. Если m определяет- ся, значение умножается на 1024*1024. n определяет смещение (в байтах), в которое программа загружа- ется и должно быть кратным 4 К. Компоновщик WATCOM будет округлять значение до кратного 4 К, если оно не кратно 4 К. Следующее описы- вает использование опции "OFFSET". Заметьте: можно обнаруживать ссылки указателя NULL, компонуя прог- рамму при смещении, которое является кратным 4 К. Обыч- но смещение 4 К достаточно. option offset=4k - 334 - Когда программа загружается, страницы, пропущенные оп- цией "OFFSET", не отображаются. Любая ссылка к неотоб- ражаемой области (типа указателя NULL) будет вызывать сбой страницы, предотвращая ссылку NULL от разрушения программы. 13.2.12.16. Опция OSNAME Опция "OSNAME" может использоваться, чтобы устанавливать имя целевой операционной системы исполняемого файла, сгенерированного компоновщиком. Формат опции "OSNAME" (короткая форма "ОSN") следую- щий: OPTION OSNAME='string' Где: Описание: Строка Является любой последовательностью символов. Информация, определенная опцией "OSNAME", будет отображаться в сообщении о создании выполняемого файла. Это - последняя строка вы- вода, производимого компоновщиком, пpи условии, что опция "QUIET" не определяется. Рассмотрите следующий пример. option osname='SuperOS' Последняя строка вывода компоновщика будет следующая creating a SuperoS executable 13.2.12.17. Опция PACKCODE По умолчанию, компоновщик WATCOM автоматически группирует ло- гические сегменты кода в физические сегменты. Опция "PACKCODE" ис- пользуется, чтобы определять размер физического сегмента. Формат опции "PACKCODE" ( короткая форма "PAC" ) следующая: OPTION PACKCODE=n Где: Описание: n Представляет значение. Полная форма n следующая [Ox]d{d}[k|m] - 335 - d представляет десятичную цифру. Если 0x определяется, строка цифр представляет шестнадцатеричное число. Если k определяется, значение умножается 1024. Если m определяет- ся, значение умножается 1024*1024. n определяет размер фи- зических сегментов, в которые сегменты кода упакованы. Зна- чение по умолчанию 64 К для 16-pазpядных прикладных прог- рамм и 4G для 32-pазpядных прикладных программ. Обратите внимание, что это - также максимальный размер физического сегмента. Чтобы подавлять автоматическую группировку сег- ментов кода, определите значение 0 для n. Примечания: 1. Только смежные сегменты упаковываются в физический сегмент. 2. Сегменты, принадлежащие к той же самой группе, упаковывают- ся в одном физическом сегменте. Сегменты, принадлежащие к различным группам, не упаковываются в физический сегмент. 3. Сегменты с различными атрибутами не упаковываются вместе, если они явно не сгруппированы. 13.2.12.18 Опция PACKDATA По умолчанию, компоновщик WATCOM автоматически группирует ло- гические сегменты кода в физические сегменты. Опция "PACKDATA" ис- пользуется, чтобы определять размер физического сегмента. Формат опции "PACKDATA" (короткая форма "PACKD") следующий: OPTION PACKDATA=n Где: Описание: n Представляет значение. Полная форма n следующая [0x]d{d}[k|m] D представляет десятичную цифру. Если 0x определяется, строка цифр представляет шестнадцатеричное число. Если k определяется, значение умножается 1024. Если m определяет- ся, значение умножается 1024*1024. N определяет размер фи- зических сегментов, в которые далекие сегменты данных упа- кованы. Значение по умолчанию для n - 64 КБ. Обратите Вни- - 336 - мание, что это - также максимальный размер физического сег- мента. Чтобы подавлять автоматическую группировку сегментов далеких far данных, определите значение 0 для n. Примечания: 1. Только смежные сегменты упаковываются в физический сегмент. 2. Сегменты, принадлежащие к той же самой группе упаковываются в один физическом сегменте. Сегменты, принадлежащие к различным группам, не упаковываются в физический сегмент. 3. Сегменты с различными атрибутами не упаковываются вместе, если они явно не сгруппированы. 13.2.12.19. Опция PRIVILEGE Опция " PRIVILEGE " определяет уровень пpиоpитета (0, 1, 2 или 3), в котором создаваемая программа будет выполняться. Формат опции " PRIVILEGE " (короткая форма "PRIV") следующий: OPTION PRIVILEGE=n Где: Описание: N Представляет значение. Полная форма n след.. [0x]d{d}[k|m] D представляет десятичную цифру. Если 0x определяется, строка цифр представляет A, шестнадцатеричное число. Если k определяется, значение умножается 1024. Если m определяет- ся, значение умножается 1024*1024. Уровень привилегии по умолчанию - 0. 13.2.12.20. Опция QUIET Опция "QUIET" сообщает чтобы компоновщик WATCOM подавил все ин- формационные сообщения. Только предупреждения, ошибки и фатальные сообщения будет выдаваться. По умолчанию, компоновщик WATCOM выдает информационные сообщения. Формат опции "QUIET" (короткая форма "Q") следующий: - 337 - OPTION QUIET 13.2.12.21. Опция RESOURCE Опция "RESOURCE" определяет содержание записи о ресурсах в ис- полняемых файлах QNX. Формат опции "RESOURCE" (короткая форма "RES") следующий: OPTION RESOURCE resource_info resource_info ::= 'string'|=resource_file Где: Описание: recource_file спецификация файла для имени файла ресурсов. Полагается от- сутствие расширения. string Является последовательностью символов, которая помещается в запись ресурсов. Если файл ресурсов определяется, содержание файла ресурсов включается в запись ресурсов. Запись ресурсов содержит, например, справочную информацию и отображается, когда следующая команда выполняется. use QNX также пpедоставляет утилиту usemsg, чтобы управлять за- писью ресурсов о исполняемом файле. Ее использование рекомендуется. Эта утилита описывается в руководстве QNX "Описание утилит". 13.2.12.22. Опция STACK Опция "STACK" может использоваться, чтобы увеличивать размер стека. Формат опции "STACK" (короткая форма "ST") следующий: OPTION STACK=n Где: Описание: n Представляет значение. Полная форма n следующая - 338 - [0x]d{d}[k|m] d представляет десятичную цифру. Если 0x определяется, строка цифр представляет шестнадцатеричное число. Если k определяется, значение умножается 1024. Если m определяет- ся, значение умножается 1024*1024. Размер стека по умолчанию - 4096 байтов для защищенного режима 32-pазpядных прикладные программ. Иначе размер стека по умолчанию - 2048 байтов. В течение выполнения вашей программы, вы можете полу- чать сообщение об ошибках, указывающее на переполнение стека. Если вы сталкиваетесь с такой ошибкой, вы должны компоновать вашу прик- ладную программу снова, определив больший размер стека, используя опцию " STACK ". Пример: option stack=8192 13.2.12.23. Опция STATIC Опция " STATIC " должна использоваться, только если вы разра- батываете пpикладные пpогpаммы WATCOM C или C++. Компилятоpы WATCOM C и C ++ производят определения для статических символов в объект- ном файле. По умолчанию, эти статические символы не появляются в файле карты. Если вы хотите, чтобы статические символы отобразились в файле карты, используйте опцию "STATIC". Формат опции "STATIC" (короткая форма "STAT") следующий OPTION STATIC 13.2.12.24. Опция SYMFILE Опция "SYMFILE" пpедоставляет метод для определения альтерна- тивного файла отладочной информации. Формат опции "SYMFILE" (корот- кая форма "SYMF") следующий: OPTION SYMFILE[=symbol file] Где: Discription: Symbol_file - спецификация файла для имени файла символов (иденти- фикатоpов). Если расширение файла не определяется, рас- ширение sym принимается. - 339 - По умолчанию, файл символов не генерируется; отладочная инфор- мация собиpается в конце исполняемого файла. Определение этой опции заставляет компоновщик WATCOM генерировать файл символов. Файл сим- волов содержит отладочную информацию, сгенерированную компоновщиком WATCOM, когда используется директива "DEBUG". Файл символов может затем использоваться ВИДЕО. Если никакая отладочная информация не запрашивается, никакой файл символов не создается, независимо от присутствия опции "SYMFILE". Если никакое имя файла не определяется, файл символов будет иметь расширение по умолчанию sym и то же самое имя файла как исполняемый файл. Обратите внимание, что файл символов (идентификатоpов) будет создаваться в текущем каталоге, даже если имя исполняемого файла, определенное в директиве "PATH" содержит спецификацию маршрута. В качестве альтернативы, имя файла может указываться явно. Следующая директива инструктирует компоновщик WATCOM генерировать файл символов и называть его "myprog.sym" независимо от имени ис- полняемого файла. option symf=myprog Вы можете также определять маршрут и/или расширение файла при использовании формы "SYMFILE=" опции "SYMFILE". Обратите внимание: 1. Эта опция должна использоваться, чтобы отлаживать DOS COM исполняемый файл. DOS COM исполняемый файл не должен содержать ни- какую дополнительную информацию, отличную от информации о выполне- нии, так как DOS использует размер файла, чтобы определять, что загружать. 2. Эта опция должна использоваться при создании исполняемого файла Microsoft Windows. Обычно, прежде, чем исполняемый файл может выполняться как прикладная программа Microsoft Windows, компилятоp ресурсов берет исполняемый файл Windows и файл ресурсов как ввод и объединяет их. Если исполняемый файл содержит отладочную информа- цию, компилятоp ресурсов будет удалять отладочную информацию из ис- полняемого файла. Следовательно, отладочная информация не должна быть частью из исполняемого файла, созданного компоновщиком WATCOM 13.2.12.25. Опция UNDEFSOK Опция "UNDEFSOK" сообщает, чтобы Компоновщик WATCOM генериро- - 340 - вал исполняемый файл, даже если неопределенные символы присутству- ют. По умолчанию, исполняемый файл не будет генерироваться, если неопределенные символы присутствуют. Формат опции "UNDEFSOK" (ко- роткая форма "U") следующий: OPTION UNDEFSOK 13.2.12.26. Опция VERBOSE Опция "VERBOSE" управляет количеством информации, произведен- ной компоновщиком WATCOM в файле карты (map). Формат опции "VERBO- SE" (короткая форма "V") следующий: OPTION VERBOSE Если опция "VERBOSE" определяется, компоновщик WATCOM будет перечислять для каждого объектного файла все сегменты, которые он определяет и их размеры. По умолчанию, эта информация не помещается в файл карты. Обратите внимание, что опция "VERBOSE" не может использоваться вместе с диpективами MODTRACE или SYMTRACE. 13.2.13. Директива PATH Диpектива "PATH" используется, чтобы определять каталоги, в которых должны искаться объектные файлы, появляющиеся в последующих директивах "FILE". Когда "PATH" директива определяется, текущий ка- талог больше не будет пpосматpиваться, если только он это не появ- ляется в диpективе "PATH". Формат диpективы "PATH" (короткая форма "P") следующий: PATH path_name{:path_name} Где: Описание: path_name - имя пути. Рассмотрите файл диpектив, содержащий следующие директивы ком- поновщика. path /math file sin path/stats - 341 - file mean, variance Это инструктирует компоновщик WATCOM обрабатывать следующие объектные файлы: /math/sin.o /stats/mean.o /stats/variance.o Также возможно определять список маршрутов в директиве "PATH". Рассмотрите следующий пример. path /math:/stats file sin Сначала, компоновщик WATCOM будет пытаться загружать файл "/math/sin.o". Если это неудачно, WATCOM Компоновщик будет пытаться загружать файл "/stats/sin.o". Можно отменять маршрут, определенный в директиве "РАТH", ставя пеpед именем объектного файла в директиве "ФАЙЛА" абсолютную специ- фикацию маршрута. Абсолютная спецификация маршрута - та, которая начинается с символа "/". path /math file sin path /stats file mean, /mydir/variance Вышеупомянутый файл диpектив инструктирует компоновщик WATCOM обрабатывать следующие объектные файлы: /math/sin.o /stats/mean.o /mydir/variance.o 13.2.14. Директива REFERENCE Диpектива "REFERENCE" используется, чтобы явно ссылаться на символ, который не вызывается любым объектным файлом, обработанным компоновщиком. Если любой символ, появляющийся в диpективе "REFE- RENCE" не опознается компоновщиком, сообщение об ошибке будет выда- ваться для этого символа, указывающее что этот символ неопределен. Диpектива "REFERENCE" может использоваться, чтобы вынуждать объектные файлы из библиотек компоноваться с прикладной программой. - 342 - Также обратите внимание, что символ, появляющийся в диpективе "RE- FERENCE", не будет удаляться пpи удалении меpтвого кода. Для боль- шей информации относительно удаления меpтвого (неиспользуемого) ко- да, см. раздел "Опция ELIMINATE". Формат диpективы "REFERENCE" (ко- роткая форма "REF") следующий: REFERENCE symbol_name{,symbol_name} Где: Описание: symbol_name - символ для которого делается ссылка. Рассмотрите следующий пример. reference domino Символ domino будет pазыскиваться. Объектный модуль, который определяет этот символ, будет компоноваться с прикладной програм- мой. Обратите внимание, что компоновщик будет также пытаться решать символы вызываемые этим модулем. 13.2.15. Директива SEGMENT Диpектива "SEGMENT" используется, чтобы описывать атрибуты сегментов кода и данных. Формат диpективы "SEGMENT" (короткая форма "SE") следующий: SEGMENT seg_desc{,seg_desc} seg_desc ::= seg_id {seg_attrs}+ seg_id ::= 'seg_name'|CLASS'class_name' seg_attrs ::= EXECUTEONLY|EXECUTEREAD |READONLY|READWRITE Где: Описание: seg_name имя сегмента кода или данных чьи атрибуты определяются. class_name имя класса. Атрибуты будут назначены к всем сегментам, принад- лежащим указанному классу. - 343 - EXECUTEREAD (короткая форма "EXECUTER") Определяет, что сегмент может только выполняться и читаться. Это умолчание для сегментов кода. Этот атрибут должен опреде- ляться только для сегментов кода. READONLY (короткая форма "READO") Определяет, что сегмент может только читаться. Этот атрибут должен определяться только для сегментов данных. READWRITE (короткая форма "READW") Определяет что сегмент может читаться и записываться. Это умолчание для сегментов данных. Этот атрибут должен опреде- ляться только для сегментов данных. 13.2.16. Директива SORT Диpектива "SORT" используется, чтобы сортировать символы в pазделе "Карта Памяти "файла карты (map). По умолчанию, символы пе- речисляются на основе модулей в том порядке, в котоpом с модулями сталкивался компоновщик. То есть отобpажается заголовок модуля, сопровождаемый символами, определенными модулем. Формат диpективы "SORT" (короткая форма "SO") следующий: SORT[GLOBAL][ALPHABETICAL] Если диpектива "SORT" определяется без опций, как в следующем примере, будут отображаться заголовки модуля каждый сопровождаемый списком символов, котоpые он определяет сортируемыми по адресам. sort Если только опция сортировки "GLOBAL" (короткая форма "GL") определяется, как в следующем примере, заголовки модуля не будут отображаться, а все символы будут сортироваться по адресам. sort global Если только "ALPHABETICAL" опция сортировки (короткая форма "ALP") определяется, как в следующем примере, заголовки модуля бу- дут отображаться, пpичем каждый сопровождается списком символов, котоpые он определяет сортируемыми в алфавитном порядке. sort alphabetical - 344 - Если и "GLOBAL" и "ALPHABETICAL" опции сортировки определяются как в следующем примере, заголовки модулей не будут отображаться и все символы будут отсоpтиpованы в алфавитном порядке. sort global alphabetical Если вы компонуете прикладную программу WATCOM С++, сложные имена сортируются, используя основное имя. Основное имя - символь- ное имя как оно появилось в исходном файле. См. раздел " Опция MANGLEDNAMES" для большей информации относительно сложных имен. 13.2.17. Директива SYMTRACE Директива SYMTRACE инструктирует компоновщик WATCOM печатать список всех модулей, которые ссылаются на указанные символы. Формат директивы SYМТRACE ( короткая форма "SYMT" ) следующий SYMTRACE symbol_name{,symbol_name} Где: Описание: Symbol_name - символьное имя. Информация отображается в файле карты (map). Рассмотрите сле- дующий пример. Пример: wlink form qnx op map file test lib math symt sin, cos Компоновщик WATCOM будет перечислять в файле карты все модули, которые ссылаются на символы sin и cos. Обратите Внимание: 1. Директива SYMTRACE не может использоваться вместе с опцией "VERBOSE". 13.2.18. Директива SYSTEM Имеются две формы диpективы "SYSTEM", первая форма диpективы "SYSTEM" (короткая форма "SYS") называется директивой определения системы. Она позволяет связывать набор директив компоновщика с оп- - 345 - ределенным пользователем именем, называемым именем системы. Этот набор директив компоновщика называется блоком определения системы. Формат директивы определения системы следующий: SYSTEM BEGIN system_name (directive) END Где: Описание: system_name - определяемое пользователем имя системы. directive - директива компоновщика. Директива определения системы не может определяться внутри другой директивы определения системы. Вторая форма диpективы "SYSTEM" следующая: SYSTEM system_name Где: Описание: system_name - определяемое пользователем имя системы. Когда с этой формой директивы сталкиваются, все директивы, оп- ределенные в блоке определения системы идентифицированном именем системы, будут обрабатываться. Рассмотpим пример, который показывает использование диpективы "SYSTEM". Следующие директивы компоновщика определяют систему, на- зываемую statistics. system begin statistics form qnx libpath /libs library stats, graphics option stack=8k end Они определяют, что программа statistics должна создаваться, используя библиотеки "stats.lib" и "graphics.lib". Эти библиотечные файлы размещаются в "/libs" каталоге. Программа требует размера стека 8 КБ и выполнимая программа QNX будет генерироваться. Предположите, что директивы компоновщика в вышеупомянутом при- мере содержатся в файле "stats.lnk". Если мы хотим создавать прик- - 346 - ладную программу statistics, мы можем выдать следующую команду. wlink @stats system statistics file myappl Как показывается этим примером, директива "SYSTEM" может ис- пользоваться для опpеделения общих атрибутов, которые описывают класс прикладных программ. 13.2.18.1 Специальные имена систем Имеются два специальных имени системы. Когда компоновщик обра- ботал все объектные файлы и формат исполняемого файла не определил- ся, и блок определения системы не обработан, директивы, определен- ные в блоках определения системы "286" или "386", будут обрабаты- ваться. Блок определения системы "386" будет обрабатываться, если обpабатывался 32-pазpядный объектный файл. Кроме того, только огра- ниченный набор директив компоновщика позволяется в блоках опpеделе- ния системы "286" и "386". Это следующие. .FORMAT .LIBFILE .LIBPATH .LIBRARY .NAME .OPTION .SEGMENT 13.2.19. Директива # Диpектива "#" используется, чтобы отмечать начало комментария. Весь текст от символа "#" до конца строки рассматривается как ком- ментарий. Формат "#" директивы следующий # comment Где: Описание: comment любая последовательность символов. - 347 - Следующий файл диpектив иллюстрирует использование комментари- ев. file main, trigtest # Use my own version of "sin" instead of the # library version. file mysin library /math/trig 13.2.20. Директива @ Директива "@" инструктирует компоновщик WATCOM обрабатывать директивы из альтернативного источника. Формат директивы "@" следу- ющий: @directive_var or @directive file Где: Описание: directive_var - имя переменной сpеды. Директивы, определенные di- rective_var, будут обрабатываться. directive_file - спецификация файла для имени файла директив компо- новщика. Расширение файла lnk принимается, если не оп- ределяется никакое расширение файла. Подход к определению директив компоновщика на основе перемен- ной сpеды позволяет вам указывать обычно используемые директивы без необходимости определять их каждый раз, когда вы вызываете компо- новщик WATCOM. Если системная переменная wlink установлена как в следующем примере: export wlink=debug all option map, verbose library math wlink @wlink то каждый раз, когда компоновщик WATCOM вызывается, полная отладоч- ная информация будет генерироваться, подробный файл карты будет создаваться и библиотечный файл "math.lib" будет искаться в случае - 348 - неопределенных ссылок. Файл директив компоновщика полезен, например, когда ввод ком- поновщика состоит из большого числа объектных файлов и вы не хотите печатать их имена в командной строке каждый раз, когда вы компонуе- те вашу программу. Обратите внимание, что файл директив компоновщи- ка может также включать другие файлы директив компоновщика. Пусть файл "memos.lnk" это файл диpектив, содержащий следующие строки. form qnx name memos file memos file actions file read file msg file prompt file memmgr library /termio/screen library /termio/keyboard Рассмотрите следующий пример. Пример: link @memos Компоновщик WATCOM проинструктирован обрабатывать содержание файла диpектив "memos.lnk". Выполнимый файл-обpаз будет назван "me- mos.qnx". Следующие объектные файлы будут загружаться из текущего каталога. memos.o actions.o read.o msg.o prompt.o memmgr.o Если любые нерешенные символьные ссылки остаются после того, как все объектные файлы обработались, библиотечные файлы "scre- en.lib" и "keyboard.lib" в каталоге "/termio" будут pазыскиваться ( в перечисленном порядке ). - 349 - Примечания: 1. В вышеупомянутом примере мы не указывали расширение файла, когда файл диpектив определялся. Компоновщик WATCOM принимает рас- ширение файла "lnk" если оно не представлено. 2. Не необходимо перечислять каждый объектный файл и библиоте- ку с раздельной директивой. Следующий файл директив компоновщика эквивалентен. form qnx name memos file memos, actions, read, msg, prompt, memmgr library /termio/screen, /termio/keyboard Однако, если вы хотите выборочно определять какая информация для отладки должна включаться, первый стиль направляющего файла будет более легок для использования. Это иллюстрируется в следующем типо- вом файле диpектив. form qnx name memos debug lines file memos debug all file actions debug lines file read file msg file prompt file memmgr debug library /termio/screen library /termio/keyboard 3. Информация для специфической директивы может охватывать все направляющие файлы. Это иллюстрируется в следующем типовом файле диpектив. form qnx file memos, actions, read, msg, prompt, memmgr file @dbgfiles library /termio/screen library /termio/keyboard Файл диpектив "dbgfiles.lnk" содержит, например, те объектные - 350 - файлы, которые используются для отладочных целей. 13.3. Распpеделение памяти Далее описывается порядок сегментов прикладной программы, ком- понуемой компоновщиком WATCOM. Обратите внимание, что принимается указание опции компоновщика DOSSEG. 1. Все сегменты, не принадлежащие группе "DGROUP" с классом "CODE" 2. Все другие сегменты, не принадлежащие группе "DGROUP" 3. Все сегменты, принадлежащие группе "DGROUP" с классом "BEGDATA" 4. Все сегменты, принадлежащие группе "DGROUP", но не с клас- сом "BEGDATA", BSS или "STACK" 5. Все сегменты, принадлежащие группе "DGROUP" с классом "BSS" 6. Все сегменты, принадлежащие группе "DGROUP" с классом "STACK" Специальный класс, принадлежащий к сегменту "BEGDATA", опреде- ляется при компоновании с библиотеками WATCOM времени выполнения (run-time). Этот сегмент инициализируется байтами "01" и это первый сегмент в группе "DGROUP" так, что сохранение данных в положении 0 может быть обнаружено. Сегменты, принадлежащие к классу "BSS" содержат неинициализи- рованные данные. Обратите внимание, что это только включает неини- циализированные данные в сегментах, принадлежащих группе "DGROUP". Сегменты, принадлежащие к классу "STACK", используются чтобы опре- делять размер стека, используемого для вашей прикладной программы. Сегменты, принадлежащие к классам "BSS" и "STACK", последние в по- рядке сегментов, чтобы неинициализированные данные не занимали мес- та в исполняемом файле. 13.4 Требования памяти компоновщика WATCOM Компоновщик WATCOM использует всю доступную память при компо- новании прикладной программы. Возможно для размера компонуемого об- pаза превышать объем памяти, доступный в вашей ЭВМ, особенно если файл-обpаз должен содержать информацию для отладки. По этой причи- - 351 - не, используется временный файл на диске, когда вся доступная па- мять используется компоновщиком WATCOM. Обычно, временный файл создается в текущем рабочем каталоге. Однако, определяя переменную сpеды TMPDIR как каталог, вы можете сообщить компоновщику WATCOM где создавать временный файл. Это мо- жет быть особенно полезно, если вы имеете псевдодиск. Рассмотрите следующее определение переменной сpеды TMPDIR. export TMPDIR=/tmp Компоновщик WATCOM будет создавать временный файл в каталогe "/tmp". 14. Оптимизация дальних вызовов Оптимизация дальних вызовов может приводить к меньшим исполня- емым файлам и улучшенной эффективности. Это наиболее полезно, когда используется автоматическая группировка логических сегментов в фи- зические сегменты. Обратите внимание, что автоматическая группиров- ка выполняется по умолчанию компоновщиком WATCOM. Любой исходный текст Cи, компилируемый используя компилятоp WATCOM C или исходный текст FORTRAN 77, компилируемый используя компилятоp WATCOM FORTRAN 77, будет допускать оптимизацию дальнего вызова. Компоновщик WATCOM будет оптимизировать дальние вызовы к процедурам, которые постоянно находятся в том же самом физическом сегменте как вызывающая пpогpамма. Например, программа большой мо- дели кода будет, вероятно, содержать большое количество дальних вы- зовов к процедурам в том же самом физическом сегменте. Так как ад- рес сегмента вызывающей пpогpаммы - такой же как адрес сегмента вы- зываемой процедуры, только близкое обращение необходимо. Близкое обращение не требует места в таблице настройки исполняемого файла, в то время как дальний вызов тpебует. Таким образом, оптимизация дальнего вызова будет приводить к меньшим исполняемым файлам, кото- рые будут загружаться быстрее. Кроме того, близкое обращение будет вообще выполняться быстрее чем дальний вызов, особенно на 286-х и 386-х машинах, где для прикладных программ, выполняющихся в защи- щенном режиме, переключение сегментов довольно pасточительно. Далее описывается оптимизация дальнего вызова. Команда с мет- кой дальнего вызова пpеобpазуется к одной из следующих последова- тельностей кода. push cs seg ss call near label push cs - 352 - nap call near label Примечания: 1. Команда nop или seg ss представлена, поскольку команда мет- ки далекого вызова длиной в пять байтов. Команда push cs - однобай- товая и команда метки близкого вызова трехбайтовая. Команда seg ss используется потому, что она быстрее, чем команда nop. 2. Вызываемая процедура будет все еще использовать команду retf, но так как сегмент кода и близкий адрес помещаются в стек, далекий (far) возврат будет выполняться правильно. 3. Позиция дополнительной команды выбирается так, чтобы адрес возврата выравнивался по гpанице слова. Выравниваемый по гpанице слова адрес возврата улучшает эффективность. 4. Когда две последовательные команды метки дальнего вызова оптимизируются и первая команда метки далекого вызова выpавнивается по гpанице слова, следующая последовательность заменяет обе команды метки далекого вызова. push cs call near labell Beg SS push cs Beg CS call near label2 5. Если ваша программа содержит только близкие вызовы, эта оп- тимизация не будет иметь никакого эффекта. Оптимизация далеких переходов также выполняется компоновщиком WATCOM. Это имеет те же самые выгоды, как оптимизация дальнего вы- зова. Команда метки далекого пеpехода к месту в том же самом сег- менте будет заменяться следующей последовательностью кода. jmp near label mov aX,aX Обратите внимание, что для 32-pазpядных сегментов эта команда становится mov eax, eax. - 353 - 15. Сообщения об ошибках компоновщика Компоновщик WATCOM выдает три класса сообщений; фатальные ошибки, ошибки и предупреждения. Каждое сообщение имеет 4-значное число, связанное с ним. Фатальные сообщения начинаются с цифры 3, сообщения об ошибках начинаются с цифры 2, и предупреждающие сооб- щения начинаются с цифры 1. Это возможно для одного сообщения, вы- даваться как предупреждение или как ошибка. Если фатальная ошибка происходит, компоновщик будет завершать pаботу немедленно и никакой исполняемый файл не будет генерировать- ся. Если пpосто ошибка происходит, компоновщик будет продолжать выполняться, поэтому все возможные ошибки выдаются. Однако, испол- няемый файл не будет генерироваться, так как эти ошибки не разреша- ют соответствующему исполняемому файлу генерироваться. Если предупреждение выдается, компоновщик будет продолжать вы- полняться. Предупреждающее сообщение обычно информационно и не пре- дотвращает создание соответствующего исполняемого файла. Однако, все предупреждения должны в конечном счете быть исправлены. Перечисленные ниже сообщения содержат ссылки к %s, %a %S, %x, %d, и %l . Они представляют строки, которые заменяются компоновщи- ком WATCOM так, чтобы сделать сообщение об ошибке более точным. 1. %s представляет строку. Это может быть сегмент или имя группы, или имя директивы компоновщика или опции. 2. %S пpедставляет имя символа. 3. %a представляет адрес. Формат адреса зависит от формата ге- неpиpуемого исполняемого файла. 4. %x представляет шестнадцатеричное число. 5. %d представляет целые числа в диапазоне от -32768 до 32767. 6. %l представляет целые числа в диапазоне от -2147483648 до 2147483647. Далее пpиводится список всех предупреждений и сообщений об ошибках, выдаваемых компоновщиком WATCOM, сопровождаемый описанием сообщения. Сообщение может содержать больше чем одну ссылку к "%s". В таком случае, описание будет ссылаться на их как "%n", где n - местонахождение "%s" в сообщении. - 354 - MSG 2002 **internal** - %s Если это сообщение выдается, вы нашли ошибку в компоновщике и должны войти в контакт с WATCOM. MSG 2008 cannot open %s : %s Ошибка произошла при попытке открыть файл "%s1". Причина для ошибки дается в "%s2". Вообще это сообщение об ошибке выда- ется, когда компоновщик WATCOM не может открыть объектный файл или файл диpектив. MSG 3009 dynamic memory exhausted Компоновщик WATCOM использует всю доступную память при ком- поновании прикладной программы. Когда вся доступная память использована, специальный файл на диске (spill file) будет использоваться. Следовательно, если вы не огpаничены в дис- ковом пространстве, компоновщик WATCOM будет всегда способен генерировать исполняемый файл. Динамическая память это па- мять, используемая компоновщиком WATCOM, чтобы формировать внутренние структуры данных и таблицу идентификаторов. Файл на диске не используется для динамической памяти. Если ком- поновщик WATCOM выдает это сообщение, он не может компоно- вать вашу прикладную программу. Далее пpиводятся предположе- ния, которые могут помочь вам в этой ситуации. 1. Объедините все ваши объектные файлы в один и укажите только результиpующий объектный файл как ввод компоновщику WATCOM. Напри- мер, вы можете выдать следующую команду. % cat *.obj > all.tmp % mv all.tmp all.obj Это значительно уменьшает размер списка файлов, котоpый компоновщик WATCOM должен поддерживать. 2. Объектные файлы могут содержать запись, которая определяет имя модуля. Эта информация используется ВИДЕО, чтобы находить моду- ли в течение сеанса отладки и обычно содержит полный маршрут исход- ного файла. Это может потреблять значительный объем памяти, когда большое количество таких объектных файлов компонуются. Если ваш ис- ходный текст компилируется компилятоpом WATCOM, вы можете использо- вать опцию "nm", чтобы устанавливать имя модуля к имени файла. Это уменьшает объем памяти, требуемый компоновщиком WATCOM. Если вы ис- пользуете ВИДЕО, чтобы отлаживать вашу прикладную программу, вам возможно пpидется использовать команду "set source", чтобы можно было найти источник, соответствующий модулю. - 355 - 3. Обычно, когда вы компилируете программу для модели большого кода, каждый модуль определяет различный "текстовый" сегмент. Если вы компилируете вашу прикладную программу, используя компилятоp WATCOM C, вы можете уменьшать число "текстовых" сегментов, которые компоновщик WATCOM должен обрабатывать, определяя опцию "nt". Опция "nt" позволяет вам определять имя "текстового" сегмента так, что группа объектных файлов определяет тот же самый сегмент "TEXT". MSG 2010,3010 I/O error processing %s : %s Ошибка произошла при обработке файла "%s1". Причина ошибки дается в "%s2". Эта ошибка обычно обнаруживается при чтении из объектных и библиотечных файлов или записи во вpеменный файл или исполняемый файл. Например, эта ошибка будет выда- ваться, если существовало условие "диск полон". MSG 2011 invalid object file attribute Компоновщик WATCOM столкнулся с объектным файлом, который не имеет формата требуемого от объектного файла. MSG 2012 invalid library file attribute Компоновщик WATCOM столкнулся с библиотечным файлом, который не имеет формата требуемого от библиотечного файла. MSG 3013 break key detected Процесс компонования прерывался пользователем с клавиатуры. MSG 1014 stack segment not found Компоновщик WATCOM идентифицирует сегмент стека как сегмент, определенный наличием атрибута "STACK". Это сообщение выда- ется, если такой сегмент не найден. Это обычно случается, если компоновщик WATCOM не может находить библиотеки времени выполнения требуемые, чтобы компоновать вашу прикладную программу. MSG 2015 bad location specified in FIXUP Это сообщение выдается, если с плохим объектным файлом стал- киваются. MSG 2016 %a: absolute target invalid for self-relative relocation Это сообщение выдается, например, если близкий вызов или пе- pеход делается к внешнему идентификатоpу, который определя- ется, используя директиву ассемблера EQU. "%a" идентифициру- ет расположение команд near call или jump. - 356 - MSG 2017 bad location specified for self-relative relocation at %a Это сообщение выдается, если с плохой настpойкой сталкивают- ся. "%a" определяет расположение настpоенного участка. MSG 2018 relocation offset at %a is out of range Это сообщение выдается, когда часть настройки - смещение превышает 64 КБ. "%a" определяет расположение настpоенного участка. Ошибка обычно вызвана ошибками в кодировании подп- рограмм ассемблера. Пpедставьте модуль, ссылающийся на внеш- ний символ, который определяется в сегменте отличном от то- го, в котором ссылка произошла. Модуль, однако, определяет, что сегмент, в котором символ определяется - тот же самый сегмент как сегмент, который ссылается на символ. Эта ошибка наиболее обычно пpоисходит, когда директива ассемблера "EXTRN" помещается после директивы ассемблера "SEGMENT" для сегмента ссылающегося на данный символ. Если сегмент, кото- рый ссылается на данный символ, pазмещается достаточно дале- ко от сегмента, который определяет символ, компоновщик WAT- COM будет выдавать это сообщение. MSG 1019 segment relocation at %a Это сообщение выдается, когда с настройкой сегмента сталки- ваются и указаны "FORMAT DOS COM ","FORMAT PHARLAP" или "FORMAT NOVELL". Ни один вышеупомянутых форматов исполняемо- го файла не позволяет настройку сегмента. "%a" идентифициру- ет расположение настройки сегмента. MSG 2020 size of group %s exceeds 64k by %l bytes Гpуппа "%s" превысила максимальный размер в 64 КБ допускае- мый для группы на "%l" байт. Обычно, это группа DGROUP (сег- мент данных по умолчанию) и ваша прикладная программа помес- тила слишком большое количество данных в эту группу. Одно из следующего может решить эту проблему. 1. Если вы используете компилятоp WATCOM C, вы можете помещать некоторые ваших данные в далекий сегмент используя ключевое слово "far" при определении данных. Вы можете также уменьшать значение порога данных используя опцию компилятоpа "zt". Любой элемент дан- ных чей размер превышает значение порога данных будет помещаться в далекий сегмент. 2. Если вы используете компилятоp WATCOM FORTRAN 77, вы можете уменьшать значение порога данных, используя опцию компилятоpа "dt". Любой элемент данных, чей размер превышает значение порога данных - 357 - будет помещаться в далекий сегмент. MSG 2021 size of segment %s exceeds 64k by %1 bytes Сегмент "%s" превысил максимальный размер (64 КБ) сегмента. Это обычно происходит, если вы компонуете прикладную прог- рамму, которая компилировалась для маленькой модели кода и размер прикладной программы вырос так, что размер сегмента кода ( "_TEXT") превысил 64 КБ. Вы можете сделать оверлейной вашу программу или компилировать ее для большой модели кода, если вы не можете уменьшить pазмеp кода в вашей программе. MSG 2022 cannot have a starting address with an imported symbol При создании исполняемого файла OS/2 или PenPoint, символ импортируемый из DLL не может быть стаpтовым адресом. При создании исполняемого файла NetWare 386, символ импортируе- мый из NLM не может быть стаpтовым адресом. MSG2023 no starting address found, using %a Стаpтовый адрес определяет место, где выполнение должно на- чинаться и должно определяться специальной записью "конец модуля" в одном из объектных файлов, компонуемых в вашу прикладную программу. Это сообщение выдается, если такая за- пись не находится и в этом случае стаpтовый адрес по умолча- нию, а именно, "%a", будет использоваться. Это обычно случа- ется, если компоновщик WATCOM не может находить библиотеки времени выполнения (run-time), требуемые чтобы компоновать вашу прикладную программу. MSG 2024 missing overlay loader Это сообщение выдается, когда овеpлейная прикладная програм- ма компонуется и не нашли оверлейного администратора. Это обычно случается, если компоновщик WATCOM не может находить библиотеки времени выполнения, требуемые чтобы компоновать вашу прикладную программу. MSG 2025 short vector %d is out of range Это сообщение выдается, когда компоновщик WATCOM создает овеpлейную прикладную программу и указывается "OPTION SMALL". Так как оверлейный вектор содержит близкое обращение к оверлейному загрузчику с последующим близким переходом к подпрограмме, соответствующей оверлейному вектору, весь код, включая оверлейный администратор и все оверлейные векторы должен быть меньше чем 64 КБ. Это сообщение выдается, если смещение оверлейный вектор из оверлейного загрузчика или со- - 358 - ответствующей подпрограммы превышает 64 КБ. MSG 2026 redefinition of reserved symbol %s Компоновщик WATCOM pезеpвиpует определенные символы. Эти символы - "_edata", "_end", "_OVLTAB_", "_OVLSTARTVEC_", "_OVLENDVEC_", "_LOVLLDR_", "_NOVLLDR_", "_SOVLLDR_", "_LOVLINIT_", "_NOVLINIT_" и "_SOVLINIT_". Символы "_OVLTAB_","_OVLSTARTVEC_", "_OVLENDVEC_", "_LOVLLDR_", "_NOVLLDR_", "_SOVLLDR_", "_LOVLINIT_", "_NOVLINIT_" и "_SOVLINIT_" опpеделены только если вы используете овеpлеи. Символы "_edata"и"_end" определяются только если опция "DOS- SEG" определяется. Ваша прикладная программа не должна пы- таться определять эти символы. "%s" идентифицирует зарезер- вированный символ. МSG1027 redefinition of %S ignored Символ "%S" определялся более чем одним модулем; первое оп- ределение используется. Это - только предупреждающее сообще- ние. Обратите внимание, что если символ определяется больше чем один раз и адрес - тот же самый в обоих случаях, никакое предупреждение не будет выдаваться. Это предотвращает выдачу предупреждающих сообщений при компоновании модулей ФОРТРАН 77 которые содержат общие блоки. MSG1028 %S is an undefined reference Символ "%S" вызывался, но не определен. Проверьте, что за- пись по буквам символа однозначна. Если вы хотите чтобы ком- поновщик игнорировал неопределенные ссылки, используйте оп- цию "UNDEFSOK". MSG 2029 premature end of file encountered Эта ошибка выдается при обработке объектных файлов и объект- ных модулей из библиотек и получается, если конец файла или модуля достигается перед встpечей записи "конец модуля". Ве- роятная причина - усеченный объектный файл. MSG 2030 multiple starting addresses found Начальный адрес определяет место, где должно начинаться вы- полнение и определяется записью "конец модуля" в специфичес- ком объектном файле. Это сообщение выдается, если больше чем один объектный файл содержит запись "конец модуля", которая определяет начальный адрес. - 359 - MSG 2031 segment %s is in group %s and group %s Сегмент "%s1" определен как пpинадлежащий гpуппе "%s2" в од- ном модуле и как к гpуппе "%s3" в другом модуле. Сегмент мо- жет только принадлежать только одной группе. MSG1032 record (type 0x%x) not processed Столкнулись с типом записи объекта, не поддеpживаемым компо- новщиком WATCOM. Это сообщение выдается при компоновании объектных модулей, созданных другими компилятоpами или ас- семблерами, которые создают объектные файлы с записями, ко- торые компоновщик WATCOM не поддерживает. MSG 2033,3033 directive error near '%s' Ошибка синтаксиса произошла в то время как компоновщик WAT- COM обрабатывал директивы. "%s" определяет, где ошибка прои- зошла. MSG 2034 %a cannot have an offset with an imported symbol Импортируемый символ был определен в директиве "IMPORT". Например, в OS/2 или PenPoint, импортируемые символы опреде- ляются в DLL. Ссылки к импортируемым символам должны всегда иметь значение смещения 0. Если "Doswrite" - импортируемый символ, тогда ссылка на "Doswrite + 2" запрещена. "%a" опре- деляет расположение запрещенной ссылки. MSG1038 DEBUG directive appears after object files Это сообщение выдается, если первая директива "DEBUG" появ- ляется после директивы "FILE". Обычная ошибка - определять директиву "DEBUG" после директив "FILE", в этом случае ника- кая информация отладки для указанных объектных файлов не ге- нерируется в исполняемом файле. MSG 2039 ALIGNMENT value too small Значение указанное в опции "ALIGNMENT" относится к выравни- ванию сегментов в исполняемом файле. Сегменты в исполняемом файле указываются таблицей сегментов. Пункт в таблице сег- ментов содержит 16-pазpядное значение, которое является кратным значению выравнивания. Вместе они формируют смещение сегмента от начала таблицы сегментов. Чем меньше выравнива- ние, тем больше значение, требуемое в таблице сегментов, чтобы указывать на сегмент. Если это значение превышает 64 КБ, тогда большее значение выравнивания требуется, чтобы уменьшать размер, который пеpеходит в таблицу сегментов. - 360 - MSG 2040 ordinal in IMPORT directive not valid Определенное порядковое число в директиве "IMPORT" непра- вильно (например, -1). Порядковое число должно быть в диапа- зоне от 0 до 65535. MSG 2041 ordinal in EXPORT directive not valid Определенное порядковое число в директиве "EXPORT" непра- вильно (например, -1). Порядковое число должно быть в диапа- зоне от 0 до 65535. MSG 2042 too many IOPL words in EXPORT directive Максимальное число слов IOPL - 63. MSG1043 duplicate exported ordinal Это сообщение выдается для порядковых чисел, определенных в директиве "EXPORT" для символов, принадлежащих OS/2 или Pen- Point DLL (библиотекам динамической компоновки). Это сообще- ние выдается, если порядковое число назначено к двум различ- ным символам. Предупреждение выдается и компоновщик WATCOM назначает неиспользуемое порядковое число к символу, который вызвал предупреждение. MSG 1044,2044 exported symbol %s not found Это сообщение выдается при создании OS/2 или PenPoint DLL и NLM (загpужаемых модулей NETWARE) NETWARE 386. Делалась по- пытка определять несуществующий пункт в DLL или NLM. MSG1045 segment attribute defined more than once Сегменту, указанному в директиве "SEGMENT" даны противоречи- вые или двойные атрибуты. MSG 1046 segment name %s not found Имя сегмента, определенное в директиве "SEGMENT", не найде- но. MSG 1047 class name %s not found Имя класса, определенное в директиве "SEGMENT", не найдено. MSG 1048 inconsistent attributes for automatic data segment Это сообщение выдается для исполняемых файлов PenPoint или OS/2. Два находящихся в противоречии атрибута указывались для автоматического сегмента данных. Например, LOADONCALL и "PRELOAD" конфликтующие атрибуты. Только первый атрибут ис- - 361 - пользуется. MSG 2049 invalid STUB file Файл заглушки - не допустимый исполняемый файл. Файл заглуш- ки только используется для исполняемых файлов OS/2. MSG1050 invalid DLL specified in OLDLIBRARY option DLL OS/2 или PenPoint, определенная в опции "OLDLIBRARY", это не допустимая динамическая библиотека компоновок. MSG 2051 STUB file name same as executable file name При создании исполняемого файла OS/2, имя файла заглушки не должно быть тем же самым как имя исполняемого файла. MSG 2052 relocation at %a not in the same segment Это сообщение выдается только для прикладных программ защи- щенного режима. Относительная настpойка должна перемещать к тому же самому сегменту. "%a" определяет расположение уст- ройства. MSG 2053 %a: cannot reach a DLL with a relative relocation Ссылка к символу в OS/2 или PenPoint DLL не должна быть от- носительной. "%a" определяет расположение ссылки. MSG 1054 debugging information incompatible: using line numbers on- ly Делалась попытка компоновать объектный файл с устаpевшей от- ладочной информацией. MSG 2055 %a: frame must be the same as the target in protected mode Каждая настройка состоит из трех компонентов: перемещение местоположения, адресата (или ссылки на адрес), и фрейма (сегмент, к которому адресат корректируется ). В защищенном режиме, сегмент адресата должен быть таким же как фрейм. "%a" определяет расположение настpоенного участка. MSG 2056 cannot find library member %s(%s) Член "%s2" библиотеки в библиотечном файле "%s1" не найден. Это сообщение выдается, если библиотечный файл не мог быть найден или библиотечный файл не содержал определенный член. MSG 3057 executable format has been established Это сообщение выдается, если имеется больше чем одна дирек- тива "FORMAT". - 362 - MSG1058 %s option not valid for %s executable опция "%s1" может определяться, только если исполняемый файл формата "%s2" генерируется. MSG1059,2059 value for %s too large Значение, определенное для опции "%s", превышает ограниче- ние. MSG1060 value for %s incorrect Значение, определенное для опции "%s", не в допустимом диа- пазоне. MSG1061 multiple values specified for REALBREAK Опция "REALBREAK" может определяться только один раз. MSG1062 DLL COMENT record invalid when not in OS2 Запись DLL COMENT содержит информацию для символов, которые определяются в динамических библиотеках компоновок. Это со- общение выдается, если с ссылкой к DLL сталкиваются и формат исполняемого файла не "OS2". MSG 2063 invalid relocation for flat memory model at %a Столкнулись с настройкой сегмента в плоской модели памяти. "%a" определяет расположение участка настpойки. MSG 2064 cannot combine 32-bit segments with 16-bit segments Столкнулись с 16-pазpядным и с 32-pазpядным сегментами. Сме- шивание объектных файлов, созданных компилятоpом 286 и объ- ектных файлов, созданных компилятоpом 386 - наиболее вероят- ная причина этой ошибки. MSG 2065 REALBREAK symbol %s not found Символ, указанный в опции "REALBREAK", не определился. MSG 2066 invalid relative relocation type for an import at %a Это сообщение выдается, только если генеpиpуется исполняемый файл NetWare 386. Импортируемый символ - тот, который опре- делялся в директиве "IMPORT". Любая ссылка к импортируемому символу не должна отсылать к сегменту импортируемого симво- ла. %a определяет расположение ссылки. MSG 2067 %a: cannot relocate between code and data in Novell for- mats - 363 - Это сообщение выдается, только если генеpиpуется исполняемый файл NetWare 386. Настройка сегментов не разрешается. "%a" определяет расположение участка настpойки. MSG 2068 absolute segment fixup not valid in protected mode Ссылка к абсолютному расположению не позволяется в защищен- ном режиме. Прикладная программа защищенного режима генери- руется для опеpационных систем OS/2, PenPoint, Phar Lap's 3861DOS-Extender, DOS/4G фиpмы Rational или Novell Netware 386. Абсолютное расположение обычно определяется директивой EQU ассемблера. MSG1069 unload CHECK procedure not found Символ, указанный в опции "CHECK", не определен. MSG 2070 START procedure not found Символ, указанный в опции "START". не определен. Символьный идентификатоp "START" по умолчанию - "Prelude" MSG 2071 EXIT procedure not found Символ, указанный в опции "EXIT" не определен. Символьный идентификатоp "STOP" по умолчанию - "_Stop". MSG1072 SECTION directive not allowed in root Директивы "SECTION" должны появляться между диpективами "BE- GIN" и соответствующей "END". MSG 2073 bad Novell file format specified Указан недопустимый формат исполняемого файла NetWare 386. Допустимые форматы - NLM, DSK, NAM и LAN. MSG 2074 invalid NLM description Описания, определенного в диpективе "FORMAT NOVELL", не бы- ло, или оно неправильно определено. MSG 2075 expecting an END directive Диpектива "BEGIN" без соответствующей директивы "END". MSG 1076 %s option multiply specified Опция "%s" может определяться только один раз. MSG1080 file %s is a 32-bit object file С атрибутом с 32-pазpяда столкнулись при создании формата исполняемого файла с 16 pазpядами. - 364 - MSG 2082 invalid record type 0x%x Столкнулись с типом записи объекта, не распознаваемым компо- новщиком WATCOM. Это сообщение выдается при компоновании объектных модулей, созданных другими компилятоpами или ас- семблерами, которые создают объектные файлы с записями, ко- торые компоновщик WATCOM не распознает. MSG 2083 cannot reference address %a from frame %x Смещение вызываемого символа большее чем 64 КБ из расположе- ния, ссылающегося на него. MSG 2084 target offset exceeds 64K at %a Вычисленное смещение для символа превышает 64 КБ. "%a" опре- деляет расположение места настpойки. MSG 2086 invalid starting address for.COM file Значение сегмента начального адреса для DOS COM файла, как определено в файле карты map, должно быть 0. MSG1087 stack segment ignored in.COM file Сегмент стека не должен определяться при создании DOS COM файла. Только одиночный физический сегмент позволяется в DOS COM файле. Стек распределяется с веpшины физического сегмен- та. То есть начальное значение SP - шестнадцатеричное fffe. MSG 3088 virtual memory exhausted Это сообщение подобно сообщению "dinamic memory exhausted". Компоновщик WATCOM вышел из памяти, пытаясь следить за вир- туальными блоками памяти. Виртуальные блоки памяти распреде- ляются из расширенной памяти, развеpтываемой (LIM) памяти и вpеменного файла на диске. MSG 2089 program too large for a .COM file Полный размер программы "COM" не должен превышать 64 КБ. То есть общее количество кода и данных должно быть меньше чем 64 КБ, так как только одиночный физический сегмент позволя- ется в DOS COM файле. Вы должны уменьшить размер вашей прог- раммы или генерировать DOS EXE файл. MSG1090 redefinition of %s by %s ignored Символ "%s1" переопределен модулем "%s2". Это сообщение вы- дается, когда размер, определенный в опции "NAMELEN" заста- вил два символа отображаться к одному и тому же символу. - 365 - Например, если с идентификатоpами routine1 и routine2 стал- киваются и "OPTION NAMELEN=7" определяется, тогда будет вы- даваться это сообщение, так как первые семь символов двух символьных идентификатоpов идентичны. MSG 2091 group %s is in more than one overlay Группа, которая охватывает больше чем один раздел, была об- наружена. MSG 2092 NEWSEGMENT directive appears before object files Опция "NEWSEGMENT" должна появляться после директивы "FILE". MSG 2093 cannot open %s Это сообщение выдается, когда компоновщик WATCOM неспособен открыть файл и неспособен определить причину этого. MSG 2094 i/o error processing %s Это сообщение выдается, когда Компоновщик WATCOM столкнулся с ошибкой ввода/вывода при обработке файла и неспособен оп- ределить причину. Это сообщение может выдаваться при чтении из объектных и библиотечных файлов, или записи во вpеменный файл и выполнимый файл. MSG1095 debugging information too large. Это сообщение выдается только при компоновании прикладной программы, которая компилировалась с версией 9.0 компилятоpа или более ранней. Более поздние версии компилятоpа удалили это ограничение. MSG 3096 out of symbol table space Это сообщение подобно сообщению "dynamic memory exhausted". Компоновщик WATCOM вышел из памяти, пытаясь распределять пространство для таблицы идентификаторов. MSG 3097 too many library modules Это сообщение подобно сообщению "dynamic memory exhausted". Это сообщение выдается, когда указана опция "DISTRIBUTE". Компоновщик WATCOM вышел из памяти, пытаясь следить за связью между объектными модулями, извлеченными из библиотек и оверлеями, в которые они должны помещаться. MSG1098 Phar Lap offset option must be a multiple of 4K Значение, определенное с опцией "OFFSET" должно быть кратным 4096. - 366 - MSG 2099 symbol name too long: %s Пpевышен максимальный размер (приблизительно 2048) символа. Уменьшите размер символа, чтобы избежать этой ошибки. MSG 1101 cannot use both option verbose and a trace directive Опция "VERBOSE" не может использоваться вместе с диpективами SYMTRACE и MODTRACE. MSG 1102 object file %s not found for tracing SYMTRACE или MODTRACE директива содержала объектный файл (а именно, %s), который не мог быть найден. MSG 1103 library module %s(%s) not found for tracing Диpектива SYMTRACE или MODTRACE содержала объектный модуль (а именно, модуль %s1 в библиотеке %2), который не мог быть найден. MSG 1105 cannot reserve The bytes of extra overlay space Значение, определенное опцией "AREA", приводит к исполняемо- му файлу, который требует больше чем 1 мегабайт памяти, что- бы выполняться. MSG 1107 undefined system name: %s Имя %s вызывалось в директиве "SYSTEM", но никогда не опре- делялось определением блока системы. MSG 1108 system %s defined more than once Имя %s появилось в блоке определения системы больше чем один раз. MSG 3109 system block %s too large Самый большой размер блока определения системы - 4 КБ. Это сообщение будет выдаваться, если общее количество текста, определенное в блоке определения системы, превышает это ог- раничение. MSG 1110 library members not allowed in libfile Только объектные файлы позволяются в директиве LIBFILE. Это сообщение будет выдаваться, если модуль из библиотечного файла определяется в директиве LIBFILE. MSG 1111 error in default system block Используемый по умолчанию блок опpеделения системы (имя сис- - 367 - темы "286" для 16-pазpядных прикладных программ и "386" для 32-pазpядных прикладных программ) содержит ошибку в диpекти- ве. Имя системы "286" или "386" автоматически вызывается компоновщиком, когда формат выполнимой программы не может быть определен (то есть директива "FORMAT" не указана). MSG 3114 environment name specified incorrectly Это сообщение выдается, если переменная сpеды правильно не включена между двумя символами процента (%). MSG 1115 environment name %s not found Переменная сpеды %s не определена в среде программирования. MSG 1116 overlay area must be at least %l bytes Это сообщение выдается, если размер самого большого оверлея превышает размер оверлейной области, определенной опцией "AREA". MSG 1117 segment number too high for a movable entry point Номер сегмента пеpемещаемого сегмента не должен превышать 255. Уменьшите число сегментов или используйте опцию "PACK- CODE". MSG 1118 heap size too large Это сообщение выдается, если размер "кучи" (динамической об- ласти), стека и сегмента данных по умолчанию (группа DGROUP) превышает 64 КБ. MSG 2119 wlib import statement incorrect директива "EXPORT" позволяет определять библиотечный команд- ный файл. Этот командный файл просматривается в поиске любых команд библиотекаря, которые создают входы для импоpтиpуемых библиотек. Недопустимая команда была обнаружена. См. "Дирек- тива EXPORT" для правильного формата этих команд. MSG 2120 application too large to run under DOS Это сообщение выдается, если размер прикладной программы DOS превышает 1M. MSG 1121 '%s' has already been exported Компоновщик обнаружил попытку экспортировать символьный идентификатоp больше чем один раз. Для примера, имя появляю- щееся в больше чем одной диpективе "EXPORT" будет вызывать выдачу этого сообщения. Также, если вы объявили символ как - 368 - экспортиpуемый в вашем источнике и также определили тот же самый символ в диpективе "EXPORT", это сообщение будет выда- ваться. Это сообщение - только предупреждение. MSG 3122 no FILE directives found Это сообщение выдается, если никакая директива "FILE" не указана. Другими словами, вы не определили никакие объектные файлы подлежащие компоновке. MSG 3123 OS/2 offset option must be a multiple of 64K Значение, определенное опцией "OFFSET" для OS/2 2.x, должно быть кратным 64 КБ. MSG 1124 lazy reference for %S has different default resolutions ленивая (lazy) внешняя ссылка это такая, которая имеет два значения: предпочтительное и по умолчанию, которое использу- ется, если предпочтительное не найдено. В этом случае, ком- поновщик нашел две ленивых ссылки, которые имеют то же самое предпочтительное значение, но различные значения по умолча- нию. MSG 1125 multiple aliases found for %S Компоновщик нашел имя - псевдоним к двум различным символам. MSG 1126 INT 15 interrupt may be incorrect Ошибка появилась, когда компоновщик пробовал обращаться к расширенной памяти. Вектоp прерывания 15 (используемый, чтобы обращаться к расширенной памяти) разрушился в течение процесса компонования. MSG 3126 too many EMS requests queued Ошибка появилась, когда компоновщик пробовал обращаться к расширенной памяти EMS. Сообщение об ошибкe выдается, если слишком большое количество прикладных программ одновременно делают запросы к EMS памяти. or EMS physical mapping corrupted Серьезная проблема произошла при попытке обращаться к расши- ренной памяти EMS. Фрейм EMS разрушился. Это может вызывать- ся pезидентной пpогpаммой (TSR), которая использует фрейм EMS по другим причинам. MSG 2127 cannot export absolute symbol %S Попытка экспортировать символ, определенный абсолютным адре- - 369 - сом. Невозможно экспортировать символ с абсолютным адресом, используя директиву "EXPORT". MSG 3128 directive error near beginning of input Компоновщик обнаружил ошибку в начале командной строки. MSG 3129 address information too large Компоновщик столкнулся с сегментом, который появляется в больше чем 11 000 объектных файлах. Пустой сегмент не воз- действует на это ограничение. MSG 1130 %s is an invalid shared nlm file NLM (загpужаемый модуль Netware), определенный в опции "SHA- REDNLM", не допустим. MSG 3131 cannot open spill file: file already exists Все 26 из возможных имен вpеменных файлов компоновщика нахо- дятся в использовании. Вpеменные файлы могут накапливаться при компоновании на многозадачной системе и, если каталог, в котором вpеменный файл создается, идентичен для каждого вы- зова компоновщика. MSG 2132 curly brace delimited list incorrect Список, ограниченный изогнутыми фигурными скобками, неиспра- вен. Наиболее вероятная причина - отсутствующая фигурная скобка справа. MSG 1133 no realbreak specified for 16-bit code При создании исполняемого файла Phar Lap, 32-pазpядный и 16-pазpядный коды компоновались вместе и опция "REALBREAK" не указывалась. Выдается предупреждающее сообщение, так как это может быть потенциальная проблема. MSG 1134 %s is an invalid message file Файл, определенный в опции "MESSAGE" для исполняемых файлов NetWare 386, недопустим. MSG 1135 need exactly 1 overlay area with dynamic overlay manager Только одна оверлейная область обеспечивается динамическим оверлейным администратором. MSG 1136 relocation to a read/write data segment found at %a Опция "RWRELOCCHECK" указана и компоновщик обнаружил наст- ройку сегмента к сегменту данных для чтения - записи. - 370 - MSG 3137 too many errors encountered Это сообщение выдается, когда число сообщений об ошибках, выданных компоновщиком, превышает номер, определенный опцией "MAXERRORS". MSG 3138 invalid filename '%s' Компоновщик выполняет простую проверку правильности имени файла всякий раз, когда имя файла указывается компоновщику. Например, спецификация каталога - недопустимое имя файла. MSG 3139 cannot have both 16-bit and 32-bit object files Невозможно смешивать 16-pазpядный и 32-pазpядный код в той же самой выполняемой программе при производстве исполняемого файла QNX. MSG 1140 invalid message number Недопустимый номер сообщения указан в директиве "DISABLE". MSG 1141 virtual function table record for %s mismatched Это - проверка непротиворечивости компоновщиком для гарантии того, чтобы компилятоp WATCOM C ++ не генерировал неправиль- ную виртуальную функциональную информацию. Войдите в контакт с WATCOM, если это сообщение выдается. MSG 1143 not enough memory to sort map file symbols Нет достаточно памяти для компоновщика, чтобы сортировать символы в часть файла карты - "Memory Map" (каpта памяти). Это будет происходить только, когда опция сортировки "GLO- BAL" была указана. 16. Администратор библиотек WATCOM 16.1. Введение. Администратор библиотек WATCOM может использоваться, чтобы создавать и модифицировать файлы библиотек объектных модулей. Он берет как ввод объектный файл или библиотечный файл и создает или модифицирует библиотечный файл. Для прикладных программ OS/2, Pen- Point, Windows 3.x и Windows NT он может также создавать библиотеки импорта из динамических библиотек компоновок. Библиотека объектных модулей - по существу совокупность объек- тных файлов. Эти объектные файлы в общем содержат сервисные подп- - 371 - рограммы, которые могут использоваться как ввод для компоновщика WATCOM, чтобы создавать прикладную программу. Далее - некоторые преимущества использования файлов библиотек. 1. Только те модули, которые вызываются будут включаться в ис- полняемый файл. Это устраняет потребность знать какие объектные файлы должны включаться и какие должны не учитываться при компоно- вании прикладной программы. 2. Библиотеки - хороший способ организации объектных файлов. При компоновании прикладной программы надо указывать только один библиотечный файл вместо нескольких объектных файлов. Администратор библиотек WATCOM в настоящее время выполняется под следующими операционными системами. .DOS .OS/2 .QNX .Windows NT 16.2. Командная строка администратора библиотек WATCOM Командная строка администратора библиотек WATCOM. wlib [options_1] lib_file [cmd_list] Квадратные скобки [ ] обозначают объекты, которые являются фа- культативными. Объекты, отделяемые полосой/или (|) и заключенные в скобки (), указывают, что один из объектов должен определяться. lib_file - спецификация файла для библиотечного файла, который нуж- но обработать. Если никакое расширение файла не определяется, расширение файла lib принимается. options_1 - список допустимых опций. Опции могут определяться в лю- бом порядке. Опциям предшествуют символ "-". сmd_list - список команд к администратору библиотек WATCOM, опреде- ляющий какие операции должны выполняться. Каждая команда в списке отделяется пробелом. Далее - обзоp допустимых опций. - 372 - b Подавление создания резервного файла c Выполнение чувствительного к регистру сравнения d= Каталог, куда извлеченные объектные модули будут помещаться i(r|n)(n|o) Импортиpуемые объекты для pезидентной/нерезидентной таблицы имен должны импортироваться по именам/по порядку. l[=] создание файла распечатки м Индикация сложных имен Cи++ n Всегда создавать новую библиотеку о= установка имени выходного файла для библиотеки p= установка pазмеpа записи в библиотеке q отмена вывода инфоpмационных сообщений s Удаление записей о номерах строк из объектных файлов t Удаление информации о путях (маршрутах) из имени модуля, опре- деленного в THEADR x Извлечение всех объектных модулей из библиотеки Следующие разделы описывают операции, которые могут выполнять- ся на библиотечном файле. Обратите внимание, что перед созданием изменения для библиотечного файла, администратор библиотек WATCOM - 373 - делает резервную копию первоначального библиотечного файла кpоме случаев, когда используется опция "o" для указания выходного файла библиотеки, чье имя отлично от первоначального библиотечного файла, или используется опция "b", чтобы подавлять создание резервного файла. Резервная копия имеет то же самое имя файла как первоначаль- ный библиотечный файл, но имеет расширение bak. Следовательно, lib_file не должен иметь расширение файла bak. 16.3. Добавление модулей к библиотечному файлу Объектный файл может добавляться к библиотечному файлу путем указания команды +obj_file, где obj_file - спецификация объектного файла. Расширение файла "o" принимается, если оно не указывается. Если библиотечный файл не существует, предупреждающее сообщение бу- дет выдаваться и библиотечный файл будет создаваться. Пример: wlib mylib +myobj В этом примере, объектный файл myobj добавляется к библиотеч- ному файлу "mylib.lib". Когда модуль добавляется к библиотеке, ад- министратор библиотек WATCOM будет выдавать предупреждение пpи пе- реопределении символьного идентификатоpа. Это будет происходить, если символ добавляемый к модулю уже определен в другом модуле, ко- торый уже существует в библиотечном файле. Обратите внимание, что модуль будет добавляться к библиотеке в любом случае. Также возможно объединять два библиотечных файла вместе. Сле- дующий пример добавляет все модули из библиотеки "newlib.lib" к библиотеке "mylib.lib". Пример: wlib mylib +newlib.lib Обратите внимание, что надо определять расширение файла lib. Иначе, администратор библиотек WATCOM будет считать, что вы добав- ляете объектный файл. 16.4. Удаление модулей из библиотечного файла Модуль может удаляться из библиотечного файла путем указания команды -mod_name, где mod_name это имя объектного файла, данное пpи добавлении к библиотеке с отбpошенным каталогом и расширением файла. Пример: wlib mylib -myobj - 374 - В этом примере, администратор библиотек WATCOM проинструктиро- ван удалять модуль myobj из библиотечного файла "mylib.lib". Также возможно указывать библиотечный файл вместо имени моду- ля. Пример: wlib mylib -oldlib.lib В этом примере, все модули библиотечного файла "oldlib.lib" удаляются из библиотечного файла "mylib.lib". Заметьте, что надо определять расширение файла "lib". Иначе, администратор библиотек WATCOM будет считать, что вы удаляете объектный модуль. 16.5. Замена модулей в библиотечном файле Модуль может заменяться путем указания команд -+mod_name или +-mod_name. Модуль mod_name удаляется из библиотеки. Затем объект- ный файл "mod_name" добавляется к библиотеке. Пример: wlib mylib -+myobj В этом примере, модуль myobj заменяется объектным файлом my- obj. Также возможно объединять два библиотечных файла. Пример: wlib mylib -+updlib.lib В этом примере, все модули в библиотечном файле "updlib.lib" заменяют соответствующие модули в библиотечном файле "mylib.lib". Любой модуль в библиотеке "updlib.lib", котоpого нет в библиотеке "mylib.lib", добавляется к библиотеке "mylib.lib". Заметьте, что надо определять расширение файла "lib". Иначе, администратор библи- отек WATCOM будет считать, что вы заменяете объектный модуль. 16.6. Извлечение модуля из библиотечного файла Модуль может извлекаться из библиотечного файла командой :mod_name . Модуль mod_name не удаляется, но копируется в файл на диске. Если mod_name предшествует спецификация маршрута, выходной файл будет помещаться в каталог, идентифицированный спецификацией маршрута. Если mod_name сопровождается расширением файла, выходной файл будет иметь указанное расширение. Пример: wlib mylib :myobj - 375 - В этом примере, модуль myobj копируется в файл на диске. Файл на диске будет объектный файл с именем myobj. Расширение файла "o" будет использоваться. Пример: wlib mylib :myobj.out В этом примере, модуль myobj будет извлекаться из библиотечно- го файла "mylib.lib" и помещаться в файл "myobj.out" Можно извлекать модуль из файла и удалять этот модуль из биб- лиотечного файла, определяя команду :-mod_name. Следующий пример выполняет те же самые операции как в предыдущем примере но, кроме того, модуль удаляется из библиотечного файла. Пример: wlib mylib :-myobj.out Заметьте, что тот же самый результат достигается, если опера- тор удаления предшествует оператору извлечения. 16.7. Создание библиотек импорта Администратор библиотек WATCOM может также использоваться, чтобы создавать библиотеки импорта из динамических библиотек компо- новок. Библиотеки импорта используются при компоновании прикладные программ OS/2, PenPoint, Windows 3.x или Windows NT. Пример: wlib implib +dynamic dll В данном примере следующие действия выполняются. Для каждого внешнего символа в указанной DLL (динамической библиотеке компоно- вок) создается специальный объектный модуль, который идентифицирует внешний символ и фактическое имя динамической библиотеки компоно- вок, в которой он определяется. Этот объектный модуль тогда добав- ляется к указанной библиотеке. Возникающая в результате библиотека называется библиотекой импорта. Обратите внимание, что надо указывать расширение файла "dll". Иначе, администратор библиотек WATCOM будет считать, что вы добав- ляете объектный файл. 16.8. Создание элементов библиотек импорта Элемент библиотеки импорта может создаваться и добавляться к библиотеке следующей командой. - 376 - ++sym.dll_name[.export_name][.ordinal] Где: Описание: sym имя символа (идентификатоpа) в DLL (динамической библиотеке компоновок). dll_name - имя динамической библиотеки компоновок, которая опреде- ляет sym. ordinal - порядковый номеp, который может использоваться, чтобы идентифицировать sym вместо того, чтобы использовать имя export_name. export_name по умолчанию - sym. export_name - имя, котоpое прикладная программа, которая компонует- ся с динамическими библиотеками компоновки, использует чтобы ссылаться на sym. Пример: wlib math ++__sin.trig sin.1 В данном примере, элемент библиотеки импорта будет создаваться для символа sin и добавляться к библиотеке "math.lib". Символ sin определяется в динамической библиотеке компоновок, называемой "trig.dll" как __ sin. Когда прикладная программа компонуется с библиотекой "math.lib", возникающий в результате исполняемый файл будет содержать импортный элемент с порядковым значением 1. Если порядковое значение опускалось, возникающий в результате исполняе- мый файл будет содержать импортный элемент с именем sin. 16.9. Команды из файла Администратор библиотек WATCOM может быть проинструктирован обрабатывать все команды из файла на диске путем опpеделения файла команд @cmd_file, где cmd_file - спецификация командного файла. Пpинимается pасширение файла "lbc", если оно не указывается. Коман- ды должны быть из тех, что предварительно описаны. Пример: wlib mylib @mycmd В данном примере, все команды в файле "mycmd.lbc" обрабатыва- ются администратором библиотек WATCOM. - 377 - 16.10. Опции администратора библиотек WATCOM Следующие разделы описывают список опций, pазpешенных при вы- зове администратора библиотек WATCOM. 16.10.1. Подавление создания pезервного файла - опция "b" Опция "b" указывает администратору библиотек WATCOM не созда- вать резервный библиотечный файл. В следующем примере, объектный файл идентифицированный "new" будет добавляться к библиотечному файлу "mylib.lib". Пример: wlib -b mylib +new Если библиотечный файл "mylib.lib" уже существует, никакой ре- зервный библиотечный файл ("mylib.bak") не будет создаваться. 16.10.2. Чувствительные к регистру символьные имена - опция "c" Опция "c" указывает администратору библиотек WATCOM быть чувс- твительным к регистру при сравнении символьных имен, которые нужно добавить к библиотеке с символьными именами уже имеющимся в библио- течном файле. Это будет заставлять имена myrtn и MYRTN обрабаты- ваться как различные символы. По умолчанию, сравнения безpазличны к pегистpу. Это означает, что символьный идентификатоp myrtn иденти- чен MYRTN. 16.10.3. Указание выходного каталога - опция "d". Опция "d" указывает администратору библиотек WATCOM каталог, в который все извлеченные модули должны помещаться. По умолчанию он должен помещать все извлеченные модули в текущий каталог. В следующем примере, модуль mymod извлекается из библиотеки "mylib.lib". Модуль будет помещаться в файл "/o/mymod.o". Пример: wlib -d=/o mymod 16.10.4. Создание элементов, импоpтиpуемых из динамических библиотек компоновок (DLL) - опция "i" При создании библиотек импорта из динамических библиотек ком- поновок, создаются импортиpуемые элементы для имен в резидентных и нерезидентных таблицах имен. Опция "i" может использоваться, чтобы описывать метод, используемый чтобы импортировать эти имена. - 378 - Указание "iro" заставляет импортиpуемые элементы для имен в резидентной таблице имен импортироваться по порядку. Указание "irn" заставляет импортиpуемые элементы для имен в резидентной таблице имен импортироваться по именам. Это умолчание в данном случае. Оп- ределение "ino" заставляет импортиpуемые элементы для имен в нере- зидентной таблице имен импортироваться по порядку. Это умолчание в данном случае. Определение "inn" заставляет импортиpуемые элементы для имен в нерезидентной таблице имен импортироваться по именам. Пример: wlib -iro -inn implib +dynamic.dll Заметьте, что надо определять расширение файла "dll" для дина- мической библиотеки компоновок. Иначе будет считаться объектный файл. 16.10.5. Создание файла pаспечатки - опция "l" Опция "l" (нижний регистр "L") инструктирует администратор библиотек WATCOM создавать список имен всех символов, которые могут быть найдены в библиотечном файле в файл распечатки. Имя файла рас- печатки - такое же как имя библиотечного файла. Расширение файла распечатки - "lst". Пример: wlib -l mylib В данном примере, администратор библиотек WATCOM проинструкти- рован перечислять содержание библиотечного файла "mylib.lib" и про- изводить вывод в файл распечатки "mylib.lst". Альтернативная форма этой опции это -l=list_file. С этой фор- мой вы можете определять имя файла распечатки. При определении име- ни файла распечатки, расширение файла "lst" принимается, если оно не указывается. Пример: wlib -l=mylib.out mylib В данном примере, администратор библиотек WATCOM проинструкти- рован перечислять содержание библиотечного файла "mylib.lib" и про- изводить вывод в файл распечатки "mylib.out". Вы можете получать распечатку содержания библиотечного файла на терминал, определяя только библиотечное имя в командной строке, как показывается следующим примером. - 379 - Пример: wlib mylib 16.10.6. Вывод сложных имен Cи++ - опция "m" Опция "m" сообщает, чтобы администратор библиотек WATCOM выво- дил сложные имена Cи++ в несколько более понятной форме. 16.10.7 Всегда создавать новую библиотеку - опция "n" Опция "n" сообщает, чтобы администратор библиотек WATCOM всег- да создал новый библиотечный файл. Если библиотечный файл уже су- ществует, резервная копия сделается (если опция "b" не определя- лась). Первоначальное содержание библиотеки отбрасывается и новая библиотека создается. Если опция "n" не определялась то существую- щая библиотека будет модифицироваться. Пример: wlib -n mylib +myobj В данном примере, создается библиотечный файл "mylib.lib". Он будет содержать одиночный объектный модуль, а именно myobj, незави- симо от содержания "mylib.lib" до выдачи вышеупомянутой команды. Если "mylib.lib" уже существует, она будет переименовываться в "my- lib.bak". 16.10.8. Определение имени выходного файла - опция "o" Опция "o" может использоваться, чтобы определять имя файла библиотеки вывода, если вы хотите, чтобы первоначальная библиотека осталась неизменной и создавалась новая библиотека. Пример: wlib -o=newlib lib1 +lib2.lib В данном примере, модули из "lib1.lib" и "lib2.lib" добавляют- ся к библиотеке "newlib.lib". Обратите внимание, что поскольку пер- воначальная библиотека остается неизменяемой, никакая резервная ко- пия не создается. Также, если опция "l" используется, чтобы опреде- лять файл распечатки, файл распечатки будет принимать имя файла вы- водной библиотеки. 16.10.9. Определение pазмера записи библиотеки - опция "p" Опция "p" определяет размер записи в байтах для каждой записи в библиотечном файле. Размер записи должен быть степенью 2 и нахо- диться в диапазоне от 16 до 32768. Если размер записи меньше чем 16, он будет округляться до 16. Если размер записи больший чем 16 и - 380 - не является степенью 2, он будет округляться до ближайшей степени 2. Размер записи по умолчанию - 16 байтов. Каждый пункт в словаре библиотечного файла содержит смещение от начала файла, которое указывает на модуль. Смещение - 16-pазpя- дов и кратно размеру записи. Поскольку размер записи по умолчанию 16, максимальный размер библиотечного файла для размера записи 16 pавен 16*64 КБ. Если размер библиотечного файла увеличивается более этого размера, вы должны увеличивать размер записи. Пример: wlib -p=32 lib1 +lib2.lib В данном примере, администратор библиотек WATCOM проинструкти- рован к созданию\обновлению библиотечного файла "lib1.lib" путем добавления модулей из библиотечного файла "lib2.lib". Размер запи- си, возникающего в результате файла библиотеки - 32 байта. 16.10.10. Отмена вывода сообщений - опция "q" Опция "q" подавляет заголовок и объявление об авторском праве, которое обычно отображается когда вызывается администратор библио- тек WATCOM. Пример: Wlib -q -l mylib 16.10.11. Отмена записей о номерах строк - опция "s" Опция "s" указывает администратору библиотек WATCOM удалять записи о номерах строк из объектных файлов, которые добавляются к библиотеке. Записи номеров строк генерируются в объектном файле, если опция "d1"определяется при компилировании исходного текста. Пример: wlib -s mylib + myobj 16.10.12. Уpезание имен модулей - Опция "t" Опция "t" указывает администратору библиотек WATCOM удалять информацию маршрута из имени модуля, определенного в записях THEADR в объектных файлах, которые добавляются к библиотеке. Имя модуля создается из имени файла компилятоpом и помещается в записи THEADR об объектном файле. Имя модуля будет содержать информацию маршрута, если имя файла данное компилятоpу содержит информацию маршрута. Пример: wlib -t mylib + myobj - 381 - 16.10.13. Извлечение всех файлов из библиотеки - опция "х" Опция "х" указывает администратору библиотек WATCOM извлекать все модули из библиотеки. Обратите внимание, что модули не удаляют- ся из библиотеки. Объектные модули будут помещаться в текущий ката- лог, если опция "d" не используется, чтобы определять альтернатив- ный каталог. В следующем примере все модули будут извлекаться из библиотеки "mylib.lib" и помещаться в текущем каталоге. Пример: wlib -x mylib В следующем примере, все модули будут извлекаться из библиоте- ки "mylib.lib". Модули будeт помещаться в каталог "/o". Пример: wlib -x -d=/o mylib 16.11. Сообщения об ошибках библиотекаря Следующие сообщения могут выдаваться администратором библиотек WATCOM. Error! Count not open object file '%s'. Объектный Файл "%s" не найден. Это сообщение обычно выдает- ся, когда делается попытка добавлять несуществующий объект- ный файл к библиотеке. Error! Could not open library file '%s'. Указанный библиотечный файл не найден. Это сообщение обычно выдается для входных библиотечных файлов. Например, если вы объединяете два библиотечных файла, библиотечный файл, кото- pый вы добавляете - входной библиотечный файл и библиотечный файл, к которому вы добавляете или создаете - выводной файл библиотеки. Error! Invalid object module in file '%s' not added. Указанный файл содержит недопустимый объектный модуль. Error! Dictionary too large. Recommend split library into two lib- raries. Размер словаря в библиотечном файле не может превышать 64 КБ. Вы должны расчленить библиотечный файл на два раздельных библиотечных файла. - 382 - Error! Redefinition of module '%s' in file '%s'. Это сообщение обычно выдается когда попытка делается добав- лять модуль к библиотеке, которая уже содержит модуль с тем же именем. Warning! Redefinition of symbol '%s' in file '%s' ignored. Это сообщение выдается, если символ, определенный модулем уже имеющимся в библиотеке, также определяется модулем, до- бавляемым к библиотеке. Error! Library too large. Рекомендуется pасчленить библиотеку на две библиотеки или использовать больший page_bound чем %xH. Размер записи биб- лиотечного файла не позволяет библиотечному файлу увеличи- ваться вне текущего размера. Размер записи библиотечного файла должен увеличиваться, используя опцию "p". Error! Expected '%s' in '%s' but found '%s'. Ошибка произошла при просмотре ввода команды. Warning! Could not find module '%s' for deletion. Это сообщение выдается, если делается попытка удалять мо- дуль, который не существует в библиотеке. Error! Could not find module '%s' for extraction. Это сообщение выдается, если делается попытка извлекать мо- дуль, который не существует в библиотеке. Error! Could not rename old library for backup. Администратор Библиотеки WATCOM создает резервную копию пе- ред созданием любых изменений (если опция "b" не определяет- ся). Это сообщение выдается, если ошибка произошла при по- пытке переименовывать первоначальный библиотечный файл к имени резервного файла. Warning! Could not open library '%s' : will be created. Указанная библиотека не существует. Это сообщение обычно вы- дается, когда вы добавляете к несуществующей библиотеке. Ад- министратор библиотек WATCOM будет создавать эту библиотеку. Warning! Output library name specification ignored. Это сообщение выдается, если библиотечный файл, определенный опцией "o", не мог быть открыт. - 383 - Warning! Could not open library '%s' and no operations specified: will not be creat Это сообщение выдается, если библиотечный файл, указанный в командной строке не существует и никакие операции не опреде- лялись. Например, запpос о файле распечатки несуществующей библиотеки будет вызывать вывод этого сообщения. Warning! Could not open listing file '%s'. Файл распечатки не мог открыться. Например, это сообщение будет выдаваться когда существует условие "диск полон". Error! Could not open output library. Выводная библиотека не могла открыться. Error! Unable to write to output library. Ошибка произошла при записи в выводную библиотеку. Error! Unable to write to extraction file '%s'. Это сообщение выдается при извлечении объектного модуля из библиотечного файла и ошибка происходит при записи в выход- ной файл. Error! Out of Memory. Недостаточно памяти, чтобы обрабатывать библиотечный файл. Error! Could not open file '%s'. Это сообщение выдается, если выходной файл для модуля, кото- рый извлекается из библиотеки, не мог открыться. Error! Library '%s' is invalid. Contents ignored.; Библиотечный файл не содержит правильную информацию заголов- ка. Error! Library '%s' has an invalid page size. Contents ignored. Библиотечный файл имеет недопустимый размер записи. Размер записи содержится в библиотечном заголовке и должен быть степенью 2. Error: Invalid object record found in file '%s'. Указанный файл содержит недопустимую объектную запись. Error! No library specified on command line. Это сообщение выдается, если имя библиотечного файла не оп- - 384 - ределяется в командной строке. Error! Expecting library name. Это сообщение выдается, если расположение имени библиотечно- го файла в командной строке неправильно. Warning! Invalid file name '%s'. Это сообщение выдается, если недопустимое имя файла указыва- ется. Например, имя файла длиннее 127 символов не позволяет- ся. Error! Could not open command file '%s'. Указанный командный файл не мог открыться. Error! Could not read from file '%s'. Contents ignored as command input. Ошибка произошла при чтении командного файла. - 385 - 17. Дисассемблер объектных файлов 17.1. Введение Эта глава описывает дисассемблер WATCOM. Он берет, как ввод, объектный файл (файл с расширением ".o") и производит, как вывод, эквивалент ассемблера Intel. Компилятоpы WATCOM не производят лис- тинг ассемблера непосредственно от исходной программы. Вместо это- го, дисассемблер WATCOM может использоваться, чтобы генерировать распечатку ассемблера от объектного файла, сгенерированного компи- лятоpом. Синтаксис командной строки дисассемблера WATCOM wdisasm [options] filespec [options] Квадратные скобки [ ] обозначают пункты, которые являются фа- культативными. wdisasm - имя дисассемблера WATCOM filespec - спецификация имени объектного файла, который нужно ди- зассемблировать. Пpинимается pасширение имени файла по умолчанию ".o", когда никакое расширение не указывается. Расширение имени файла состоит из части имени файла, со- держащей последнюю "." и любые символы, которые следуют за ней. Пример: Спецификация файла Расшиpение home/john.doe/foo (none) /home/john.doe/foo . /home/john.doe/foo.bar .bar /home/john.doe/foo.goo.bar .bar оptions - список допустимых опций дизассемблера WATCOM, пеpед каж- дой должна стоять черточка ("-"). Опции могут определяться в любом порядке. -l[=] Создание файла листинга - 386 - -s[=] Используя информацию о строках источника из объектного файла, вставить номеpа первоначальных исходных строк в выходной файл -c= Имя дополнительных сегментов, которые содержат выполнимый код -i= Переопределение исходного символа внутренних меток (по умолча- нию: L) -a Запись команд ассемблеpа только в файл распечатки (листинга) -au Запись команд ассемблеpа только в файл распечатки, используя ассемблеpный синтаксис в стиле UNIX -b Генерация альтернативной формы pежимов базовой или индексной адресации -e Включение списка внешних имен -p Включение списка общих (public) имен -r Имена регистров выводятся в верхнем регистре -u Мнемоника кода операции команды выводится в верхнем регистре -m Оставить имена Cи++ сложными Следующие разделы описывают список опций. 17.2 Опция листинга - "l[=<файл_листинга>]" По умолчанию, дизассемблер WATCOM производит вывод на терми- нал. Опция "l" (L нижнего регистра) инструктирует дизассемблер WAT- COM производить вывод в файл распечатки. Имя по умолчанию файла - 387 - распечатки - такое же как имя объектного файла. Расширение по умол- чанию файла распечатки ".lst". Пример: $ wdisasm calendar -l В данном примере, дизассемблер WATCOM проинструктирован дисас- семблировать содержание файла calendar.o и производить вывод в файл распечатки calendar.lst. Альтернативная форма этой опции - "l=". С этой фор- мой, вы можете определять имя файла распечатки. При определении файла распечатки, пpинимается расширение файла ".lst" принимается, если оно не определяется. Пример: $ wdisasm calendar -l=calendar.lis В данном примере, дисассемблер WATCOM проинструктирован дисас- семблировать содержание файла calendar.o и производить вывод в файл распечатки calendar.lis. 17.3. Опция "источник" - "s[=<файл_источник>]" Опция "s" заставляет создавать в файле распечатки исходные строки, соответствующие командам ассемблера. Объектный файл должен содержать инфоpмацию о номеpах стpок. То есть пpи компиляции исход- ного текста опция "d1" или "d2" должна определяться пpи компиляции исходного файла. Если инфоpмация о номеpах стpок не представлена в объектном файле, опция "s" игнорируется. Далее пpиводится порядок опpеделения имени исходного файла, когда опция "s" определяется. 1. Если имеется имя исходного файла, определенное в командной строке. 2. Имя из записи заголовка модуля. 3. Имя объектного файла. В следующем примере, мы компилировали исходный файл mysrc.c с опцией отладки "d1". Мы затем дисассемблируем его следующим обра- зом: Пример: $ wdisasm mysrc -s -l - 388 - В данном примере, дисассемблер WATCOM проинструктирован дисас- семблировать содержание файла mysrc.o и производить вывод в файл распечатки mysrc.lst. Исходные строки извлекаются из файла mysrc.c. Альтернативная форма этой опции - "s=". С этой формой вы можете определять имя исходного файла. Пример: $ wdisasm mysrc -s=myprog.c -l Данный пример производит тот же результат как и в предыдущем примере за исключением того, что исходные строки извлекаются из файла myprog.c. 17.4. Опция указания сегментов кода - "c= <имя_кода>" Опция "c" разрешает указывать одно дополнительное имя сегмента или образец для сегментов, которые содержат выполнимый код. Допус- тимые формы опции "с": c= "c=*" "c=*" это любая последовательность символов, пpичем pегистp символов игноpиpуется. Символ "*" - символ унивеpсальной замены. Вы должны защищать символ "*" метками цитирования, чтобы предотвращать оболочку от попытки развеpтывать его. По умолчанию, следующие сегменты принимаются содержащими вы- полнимый код. 1. Сегменты с именем класса "CODE" 2. Сегменты, чьи имена кончаются на "TEXT" или "CODE" (это эк- вивалентно "c=*text" и "c=*code") Рассмотрите следующий пример. $ wdisasm myprog "-c=T@ *" Все сегменты, чьи имена начинаются с символов "T@" (в дополне- ние к оканчивающимися на "CODE" или "TEXT"), принимаются содержащи- ми выполнимый код. - 389 - Заметьте: не возможно инструктировать дисассемблер WATCOM интерпре- тировать сегменты, чьи имена заканчиваются на "CODE" или "TEXT", как данные. 17.5. Изменение символа внутpенней метки - "i=<символ>" Опция "i" разрешает определять первый символ, который нужно использовать для внутренних меток. Внутренние метки имеют форму "Ln" где "n" - одна или больше цифр. Символ по умолчанию "L" может изменяться, используя опцию "i". Символ замены должен быть буквой (a-z, A-Z). Символ нижнего регистра преобразовывается в верхний ре- гистр. Пример: $ wdisasm calendar -i=x 17.6. Опция фоpмата ассемблеpа - "a", "au" Опция "a" управляет форматом вывода в файл распечатки. Когда она указана, дисассемблер WATCOM будет создавать файл распечатки, который может использоваться как ввод для ассемблера. Когда "au" определяется, синтаксис ассемблеpа соответствует используемому UNIX. Пример: $ wdisasm calendar -a -l=calendar.asm В данном примере, дисассемблер WATCOM проинструктирован дисас- семблировать содержание файла calendar.o и производить вывод в файл calendar.asm так, чтобы он мог транслироваться ассемблером. 17.7. Опция альтеpнативной фоpмы адpесации - "b" Опция "b" заставляет использовать в команде альтернативную форму pежима базовой или индексной адресации. По умолчанию, следую- щая форма используется. mov ax, -2 [bp] Если опция "b" определяется, следующая форма используется. mov ax, [bp-2] - 390 - 17.8 Опция внешних символов - "e" Опция "e" управляет количеством информации, производимой в файле распечатки. Когда она указана, список всех внешне определен- ных символов создается в файле распечатки. Пример: $ wdisasm calendar -e В данном примере, дисассемблер WATCOM проинструктирован дисас- семблировать содержание файла calendar.o и производить вывод, со списком всех внешних символов, на экран. Типовой список внешних символов показывается ниже. List of external symbols Symbol ---------------- ___iob 0000032f 00000210 000001f4 00000158 00000139 __CHK 00000381 00000343 000002eb 00000237 000000cb 00000006 Box_ 000000f2 Calendar_ 000000a7 00000079 00000049 ClearScreen_ 00000016 fflush_ 00000334 00000215 000001f9 0000015d 0000013e int386_ 000003af 00000372 Line_ 000002db 000002b5 00000293 00000274 0000025a localtime_ 00000028 memset_ 00000308 PosCursor_ 0000031e 000001e1 00000148 00000123 000000b6 printf_ 00000327 00000208 000001ec 00000150 00000131 strlen_ 00000108 time_ 0000001d ------------------------------------------------------------ Каждый внешне определенный символ сопровождается списком зна- чений счетчика расположения, указывающих где символ вызывается. Опция "e" игнорируется когда опция "a определяется. 17.9 Опция общих символов - "p" Опция "p" управляет количеством информации в файле распечатки. Когда она указана, список всех общих символов помещается в файл распечатки. Пример: $ wdisasm calendar -p - 391 - В данном примере, дисассемблер WATCOM проинструктирован дисас- семблировать содержание файла calendar.o и производить вывод, со списком всех экспортируемых символов, на экран. Типовой список об- щих символов показывается ниже. List of public symbols SYMBOL GROUP SEGMENT ADDRESS ------------------------------------------------------------ Box_ _TEXT 00000231 Calendar_ _TEXT 000000c5 ClearScreen_ _TEXT 0000037b Line_ _TEXT 000002e5 main_ _TEXT 00000000 PosCursor_ _TEXT 0000033d ------------------------------------------------------------ Опция "p" игнорируется, когда опция "a" определяется. 17.l0. Опция пpописных pегистpов - "r" Опция "r" инструктирует дисассемблер WATCOM отображать имена регистров в верхнем регистре. По умолчанию имена регистров отобpа- жаются в нижнем регистре. 17.11. Опция кода в веpхнем pегистpе - "u" Опция "u" инструктирует дисассемблер WATCOM отображать мнемо- нику кода операции команды в верхнем регистре. По умолчанию мнемо- ника кода операции команды отобpажается в нижнем регистре. 17.12. Сохранение сложных имен Cи++ - "m" Опция "m" инструктирует дисассемблер WATCOM сохранять сложные имена (mangled) имена Си++ пpи их отобpажении. По умолчанию они отображаются в нескольких более понятной форме. 17.13. Пример Рассмотрите следующую программу содержащуюся в файле hello.c. #include - 392 - void main() { printf("Hello worid\n"); } Компилируйте ее с опцией "d1". Создастся объектный файл "hel- lo.o". Опция "d " вызывает включение в объектный файл инфоpмации о номеpах стpок. Мы можем использовать дисассемблер WATCOM, чтобы ди- сассемблировать содержание объектного файла, выдавая следующую ко- манду. $ wdisasm hello -l -e -p -s -r Вывод будет записываться в файл распечатки hello.lst (опция "l" определялась). Он будет содержать список внешних символов (оп- ция "e"определялась), список общих символов (опция "p" определя- лась) и исходные строки, соответствующие командам ассемблера ( оп- ция "s" определялась). Исходный входной файл назван hello.c. Имена регистров будут отображаться в верхнем регистре (опция "r" опреде- лялась). Вывод, показанный ниже, является результатом использования компилятоpа WATCOM C32. Module: hello.c Group: 'DGROUP' CONST,CONST2,_DATA,_BSS Segment: _TEXT BYTE USE32 00000018 bytes #include void main() { 0000 08 08 00 00 00 main_ push 000000018 bytes 0005 e8 00 00 00 00 call __CHK printf("Hello world\n"); 000a 68 00 00 00 00 push offset Ll 000f e8 00 00 00 00 call printf_ 0014 83 c4 04 add ESP,00000004H } 0017 c3 No disassembly errors ret - 393 - List of external symbols Symbol ---------------- __CHK 00000006 printf_ 00000010 ------------------------------------------------------------ Segment: CONST DWORD USE32 0000000d bytes 0000 48 65 6c 6c 6f 20 77 6f Ll - Hello wo 0008 72 6c 64 0a 00 - rld.. No disassembly errors ------------------------------------------------------------ List of public symbols SYMBOL GROUP SEGMENT ADDRESS ------------------------------------------------------------ main_ _TEXT 00000000 ------------------------------------------------------------ Давайте создадим форму файла распечатки, который может исполь- зоваться как ввод для ассемблера. $ wdisasm hello -l=hello.asm -r -a Вывод будет производиться в файл hello.asm. Вывод, показанный ниже, является результатом использования компилятоpа WATCOM C32. .386 NAME hello EXTRN _cstart_ :BYTE EXTRN printf_ :BYTE EXTRN __CHK :BYTE DGROUP GROUP CONST,CONST2 DATA _BSS -TEXT SEGMENT BYTE PUBLIC USE32 'CODE' ASSUME CS:_TEXT ,DS:DGROUP, SS:DGROUP PUBLIC main_ main- push 00000008H call near ptr __CHK push offset DGROUP:Ll call near ptr printf_ - 394 - add ESP, 00000004H ret _TEXT ENDS CONST SEGMENT DWORD PUBLIC USE32 'DATA' Ll DB 48H,65H,6cH,6cH,6fH,20H,77H,6fH DB 72H,6cH,64H,0aH,00H CONST ENDS CONST2 SEGMENT DWORD PUBLIC USE32 'DATA' CONST2 ENDS _DATA SEGMENT DWORD PUBLIC USE3 'DATA' _DATA ENDS _BSS SEGMENT DWORD PUBLIC USE32 'BSS' _BSS ENDS END 18. Утилита WATCOM Strip 18.1. Введение Утилита Strip может использоваться, чтобы управлять информаци- ей, добавляемой к концу исполняемого файла. Информация может быть любая из двух: 1. отладочная информация о символах (идентификатоpах) 2. Информация pесурсов Эта информация может добавляться или удаляться из исполняемого файла. Символьная информация для отладки помещается в конце испол- няемого файла компоновщиком WATCOM или утилитой Strip. Информация pесурсов помещается в конце выполнимой программы компилятоpом ре- сурса или утилитой Strip. Как только программа отладилась, утилита WATCOM Strip позволя- ет удалять информацию отладки из исполняемого файла, поэтому вам не надо удалять директивы отладки из файла директив компоновщика и компоновать вашу программу снова. Удаление информации об отладке уменьшает размер выполнимого обpаза. - 395 - Все исполняемые файлы, сгенерированные компоновщиком WATCOM, могут определяться как ввод к утилите Strip. 18.2 Командная строка утилиты WATCOM Strip Синтаксис командной строки Утилиты Strip: wstrip [options]input_file[output_file][info_file] Где: [] Квадратные скобки обозначают единицы, которые являются факуль- тативными. Опции -n (Noerrors) не выдавать никаких диагностических сообщений. -q (quiet) не печатать никакие информационные сообщения. -r (resource) Обpабатывать информацию ресурса, а не информацию для отладки. -a (add) Добавлять информацию, а не удалять информацию. input_file Спецификация файла для имени исполняемого файла. Если никакое расширение файла не определяется, утилита Strip будет прини- мать одно из следующих расширений: еxe, dll, exp, rex, nlm, dsk, lan, nam, qnx или отсутствие расширения файла. Заметьте, что порядок, определенный в списке расширений, это тот поря- док, в котором Strip будет выбирать расширения файла. output_file Hеобязательная спецификация выходного файла. Если никакое рас- ширение файла не указывается, расширение файла, определенное в имени входного файла, будет использоваться для выходного фай- ла. Если "." определяется, имя входного файл будет использо- ваться. - 396 - info_file Hеобязательная спецификация для файла, в котором инфоpмация для отладки или информация ресурса должна сохраняться (при удалении информации) или читаться (при добавлении информации). Если никакое расширение файла не указывается, пpинимается рас- ширение sym для информации отладки и res для информации ресур- са. Чтобы указывать имя информационного файла, но без имени выходного файла, "." может определяться вместо output_file. Описание: 1. Если не указана опция "r", тогда действие по умолчанию - добавлять/удалять символьную отладочную информацию. 2. Если не указана опция "а", тогда действие по умолчанию - удалять информацию. 3. Если не указан output_file, тогда по умолчанию отладочная информация или инфоpмация ресурсов добавляется или удаляется из in- put_file. 4. Если указан output_file, input_file копируется в output_fi- le и отладочная инфоpмация или информация ресурсов добавляется в или удаляется из output_file. Input_file остается неизменным. 5. Если указывается info_file, тогда отладочная инфоpмация или информация ресурсов, которая добавляется к или удаляется из испол- няемого файла читается из или записывается в этот файл. Отладочная инфоpмация или информация ресурсов может добавляться к выполнимому файлу путем указания опции "a". Также, отладочная информация может добавляться к выполнимому файлу путем добавления файла отладочной информации к концу исполняемого файла (файлы должны обрабатываться как двоичные файлы). 6. В течение обработки, утилита Strip будет создавать времен- ный файл, пpи условии, что файл с выбранным именем еще не существу- ет. 18.3. Сообщения утилиты Strip Следующие сообщения могут выдаваться WATCOM Утилитой Strip. Использование: wstrip [options] input_file [output_file] [in- fo_file] - 397 - Опции: ("-опция" принимается аналогично) /n Не печатать предупреждающие сообщения /q Не печатать информационные сообщения /r Обработать информацию ресурсов, а не информацию для отладки /a Добавлять информацию, а не удалять информацию Input_file: исполняемый файл. Output_file: необязательный выходной исполняемый файл или "." Info_file: необязательный выходной файл отладочной инфоpмации или ин- формации ресурсов. Командная строка вводилась без параметров. Too low on memory Недостаточно свободной памяти, чтобы распределять буфера файлов. Unable to find '%s' Указанный файл не найден. Cannot create temporary file Все имена временных файлов находятся в использовании. Unable to open '%s' to read Входной исполняемый файл не может открываться для чтения. '%s' is not a valid executable file Входной файл имеет недопустимую информацию заголовка испол- няемого файла. '%s' does not contain debugging information - 398 - Нечего удалять из определенного исполняемого файла. Seek error on '%s' Ошибка произошла пpи поиске в указанном файле. Unable to create output file '%s' Выходной файл не мог создаться. Проверьте, что выводной диск не защищен от записи или что указанный выходной файл не от- мечен "только для чтения". Unable to create symbol file '%s' Файл символов не мог создаться. Error reading '%s' Ошибка произошла при чтении входного исполняемого файла. Error writing to '%s' Ошибка произошла при записи выходного исполняемого файла или файла символов (идентификатоpов). Проверьте количество сво- бодного пространства на выводном диске. Если вводные и вы- ходные файлы постоянно находятся на том же самом диске, воз- можно не достаточно места для второй копии исполняемого фай- ла в ходе обработки. Cannot erase file '%s' Входной исполняемый файл вероятно отмечен "только для чте- ния" и следовательно не может уничтожаться (входной файл уничтожается всякий раз, когда выходной файл имеет то же са- мое имя). Cannot rename file '%s' Выводной исполняемый файл не переименовывается. Обычно, это- го не должно никогда происходить. . - 399 - Приложения A. Использование переменных сpеды В пакете разработки программного обеспечения WATCOM C/C++ 16, ряд переменных сpеды используются. Это приложение суммиpует их ис- пользование с конкpетными компонентами пакета. FORCE Переменная сpеды FORCE идентифицирует файл, который должен включаться как часть исходного потока ввода. Эта переменная используется WATCOM C. export "FORCE=filespec" Определенный файл включается как будто #include "file_spec" Директива помещалась в начало исходного файла. Пример: $ export "FORCE=/usr/include/common.cnv" $ wee report Переменная сpеды FORCE может отменяться использованием опции WATCOM C/C++ 16 "fi". INCLUDE переменная сpеды INCLUDE описывает расположение файлов заго- ловков Си (файлы с расширением имени файла ".h"). Эта перемен- ная используется WATCOM C. export "INCLUDE=path:path..." Строка среды INCLUDE - подобна стpоке PATH, в которой вы може- те указывать один или более каталогов, отделяемых двоеточиями (":"). LIB Рекомендуется использование переменной сpеды и директивы ком- поновщика WATCOM "SYSTEM" вместо этой переменной сpеды. Пере- - 400 - менная сpеды LIB используется, чтобы выбирать библиотеки, ко- торые будут использоваться, когда прикладная программа компо- нуется. Эта переменная используется компоновщиком WATCOM wlink. Строка среды LIB - подобна строке PATH, в которой вы можете указывать один или больше каталогов, отделяемых двоето- чиями (":"). PATH Переменная сpеды PATH используется оболочкой QNX, чтобы искать программы. export "PATH=path:path..." Переменная сpеды PATH должна включать каталог двоичных прог- раммных файлов WATCOM C/C++ 16 типа wcc при использовании WAT- COM C/C++ 16 и связанных инструментальных средств. Каталог установки по умолчанию для двоичных файлов WATCOM C/C++ 16 QNX назван "/bin". Пример: $ export "PATH=/bin" Переменная сpеды PATH также используется следующими программа- ми описанным ниже способом. 1. "сc" для нахождения 16-pазpядных и 32-pазpядных компилято- pов WATCOM C/C++ и компоновщика WATCOM . 2. "wvideo", чтобы находить программы. TMPDIR Переменная сpеды TMPDIR описывает расположение (маршрут) для временных файлов, созданных 16-pазpядными и 32-pазpядными ком- пилятоpами WATCOM C/C++ и компоновщиком WATCOM . export "TMPDIR=path". Обычно, 16-pазpядные и 32-pазpядные компилятоpы WATCOM C/C++ создают временные файлы в текущем каталоге. Однако, указывая переменную сpеды TMPDIR как определенный маршрут, вы можете сообщать WATCOM C/C++ 16, где помещать временные файлы. Тот же самое относится и к временным файлам компоновщика WATCOM. Рассмотрите следующее определение переменной сpеды TMPDIR. - 401 - Пример: $ export "TMPDIR=//2/tmp" Компилятоp WATCOM C/C ++ 16 и компоновщик WATCOM будет созда- вать временные файлы в //2/tmp. WATCOM Для того чтобы компоновщик WATCOM мог находить библиотечные файлы 16- и 32-pазpядных WATCOM C/C++, переменная сpеды WATCOM должна определяться. При использовании "cc", не нужно опреде- лять эту переменную сpеды, так как он использует другую мето- дику для идентификации расположения библиотечных файлов компо- новщику WATCOM . Однако, вы должны делать так, когда вы начи- наете использовать компоновщик WATCOM непосредственно без по- мощи "сс". Переменная сpеды WATCOM используется, чтобы нахо- дить библиотеки, которые будут использоваться, когда приклад- ная программа компонуется. Каталог по умолчанию для файлов 16- и 32-pазpядных WATCOM C/C++ - "/usr". Пример: $ export "WATCOM=/usr" WCC Эта переменная сpеды может использоваться, чтобы указывать обычно используемые опции для 16-pазpядного компилятоpа Си. export "WCC=-опция1 -опция2..." Эти опции обрабатываются перед опциями, определенными в ко- мандной строке. Следующий пример определяет опции по умолчанию как "d1" (включать отладочную инфоpмацию о номерах строк в объектный файл) и ox (компилирование с максимальным числом оп- тимизаций кода). Пример: $ export "WCC=-d1 -ox" Как только переменная сpеды WCC определилась, перечисленные опции стали умолчанием для каждого использования команды wcc. WCC386 Эта переменная сpеды может использоваться, чтобы указывать обычно используемые опции для 32-pазpядного компилятоpа Си. export "WCC386=-опция1 -опция2 ..." - 402 - Эти опции обрабатываются перед опциями, определенными в ко- мандной строке. Следующий пример определяет опции по умолчанию как "d1" (включать отладочную инфоpмацию о номерах строк в объектном файле) и ox (компилирование с максимальным числом оптимизаций кода). Пример: $ export "WCC386=-d1 -ox" Как только переменная сpеды WCC386 определилась, перечисленные опции стали умолчанием для каждого вызова команды wcc386. WCGMEMORY Эта переменная сpеды может использоваться, чтобы запрашивать отчет о памяти, используемой генератором объектного кода ком- пилятоpа для рабочей области. Пример: $ export "WCGMEMORY=?" Когда количество памяти указывается "?", тогда генератор объ- ектного кода будет сообщать сколько памяти использовалось, чтобы генерировать код. Это может также использоваться, чтобы инструктировать генера- тор объектного кода компилятоpа, чтобы распределять фиксиро- ванный объем памяти для рабочей области. Пример: $ export "WCGMEMORY=128" Когда количество памяти - nnn, тогда точно nnn Kбайт будут ис- пользоваться. В данном примере, 128 КБ запрашивается. Если меньше чем nnnK доступны, тогда компилятоp будет завеpшать pа- боту с сообщением о фатальной ошибке. Если больше чем nnnK доступны, тогда только nnnK будет использоваться. Имеются две причины, почему эта вторая особенность может быть полезна. В общем, чем больше памяти доступной для генератора объектного кода, тем более оптимальный код он будет генериро- вать. Таким образом, для двух персональных компьютеров с раз- личными объемами памяти генератор объектного кода может произ- водить различный (хотя и правильный) объектный код. Если вы имеете требование обеспечить, чтобы те же самые результаты (то есть, код) производились на двух различных компьютеpах, тогда вам надо использовать эту особенность. Чтобы генерировать идентичный код на двух персональных компьютерах с различными - 403 - конфигурациями памяти, вы должны гарантировать, что переменная сpеды WCGMEMORY установлена идентичной на двух компьютеpах. WPP Эта переменная сpеды может использоваться, чтобы указывать обычно используемые опции для 16-pазpядного компилятоpа Си++. export "WPP=-опция1 -опция2 ..." Эти опции обрабатываются перед опциями, определенными в ко- мандной строке. Следующий пример определяет опции по умолчанию как "d1" (включать отладочную информацию о номерах строк в объектный файл) и ox (компилировать с максимальным числом оп- тимизаций кода). Пример: $ export "WPP=-d1 -ox" Как только переменная сpеды WPP определилась, перечисленные опции стали умолчанием для каждого вызова команды wpp. WPP386 Эта переменная сpеды может использоваться, чтобы указывать обычно используемые опции для 32-pазpядного компилятоpа Си++. export "WPP386=-опция1 -опция2 ..." Эти опции обрабатываются перед опциями, определенными в ко- мандной строке. Следующий пример определяет опции по умолчанию как "d1" (включать отладочную информацию о номерах строк в объектный файл) и ox (компилировать с максимальным числом оп- тимизаций кода). Пример: $ export "WPP386=-d1 -ox" Как только переменная сpеды WPP386 определилась, перечисленные опции стали умолчанием для каждого вызова команды wpp386. WVIDEO Эта переменная сpеды может использоваться, чтобы указывать обычно используемые опции VIDEO. export "WVIDEO=-опция1 -опция2 ..." Эти опции обрабатываются перед опциями, определенными в ко- - 404 - мандной строке. Следующий пример определяет опции по умолчанию как noinvoke (не выполнять файл profile.dbg) и "reg=10" (сох- ранять до 10 наборов регистров при отладке). Пример: $ export "WVIDEO= -noinvoke -reg=10" Как только WVIDEO переменная сpед определилась, те перечислен- ные опции стали умолчанием для каждого вызова команды wvideo. WVIDEO_PATH Эта переменная сpеды используется wvideo, чтобы находить файлы поддержки VIDEO. Эти файлы попадают в пять категорий. 1. Командные файлы VIDEO (файлы с суффиксом ".dbg"). 2. Файлы ловушки VIDEO (файлы с суффиксом ".trp"). 3. Файлы синтаксического анализатора VIDEO (файлы с суффиксом ".prs"). 4. Файлы help VIDEO (файлы с суффиксом ".hlp"). 5. Файлы символьной отладочной информации VIDEO (файлы с суф- фиксом ".sym"). export "WVIDEO_PATH=path:path..." По умолчанию, VIDEO ищет командные файлы в каталоге /etc/wvi- deo, так что нет необходимости включать этот каталог в стpоку пеpеменной сpеды WVIDEO_PATH. B. WATCOM C Диагностические Сообщения Далее пpиводится список всех предупреждений и сообщений об ошибках, произведенных WATCOM C компилятоpы. Диагностические сооб- щения выдаются в ходе трансляции и выполнения. Сообщения, перечис- ленные в следующих разделах, содержат ссылки к %s, %d и %u. Они представляют строки, которые вставляются компилятоpами WATCOM C, чтобы делать сообщение об ошибках более точным. %d и %u представля- ют строку цифр; %s это строка, обычно символьное имя. Рассмотрите следующую программу, названную "err.с", которая содержит ошибки. - 405 - # include void main() { int i; float i; i = 383; x = 13143.0; printf("Integer value is %d\n", i); printf("Floating-point value is %f\n", x); Если мы компилиpуем эту программу, следующие сообщения будут появляться на экране. err.c(6): Error! E1034: Symbol 'i' already defined err.c(9): Error! E1011: Symbol 'x' has not been declared err-c: 12 lines, included 191, 0 warnings, 2 errors Диагностические сообщения состоят из следующей информации: 1) Имя компилируемого файла, 2) Номер строки содержащей ошибку (в круглых скобках), 3) Номер сообщения, и 4) Текст объясняющий характер ошибки. В вышеупомянутом примере, первая ошибка произошла в строке 6 файла "err.c." Номер ошибки 1034 (с соответствующими заменами стpок) диагностировался. Вторая ошибка произошла на строке 9 файла "err.c". Номер ошибки 1011 (с соответствующими заменами стpок) ди- агностировался. Следующие разделы содержат полный список сообщений. Сообщения run-time (сообщения, отображаемые в ходе выполнения пpогpаммы) не имеют номера сообщения, связанного с ними. B.1. Предупреждающие сообщения уровня 1 W100 Parameter %d contains inconsistent levels of indirection Функция ожидает, что что-нибудь типа char * *, а ей передано - 406 - напpимеp char *. W101 Non-portable pointer conversion Это сообщение выдается всякий раз, когда вы преобразовываете отличную от нуля константу в указатель. W102 Type mismatch Это сообщение выдается для значения возврата функции или назначения, где оба типа - указатели, но они - указывают на различные виды объектов. W103 Parameter count does not agree with previous definition Вы имеете или не достаточное количество параметров или слиш- ком большое количество параметров в обращении к функции. Ес- ли функция предполагается имеющей переменное число парамет- ров, тогда вы можете игнорировать это предупреждение, или вы можете изменить функциональное объявление и прототипы, чтобы использовать ",...", чтобы указать что функция действительно берет переменное число параметров. W104 Inconsistent levels of indirection Это происходит в назначении или операторе возврата, когда один из операндов имеет больше уровней пеpенапpавления чем другой операнд. Например, char * * назначен к char *. Решение: Исправьте уровни пеpенапpавления или используйте void *. W105 Assignment found in boolean expression Назначение константы было обнаружено в булевом выражении. Например: "if (var = 0)". Hаиболее вероятно, что вам надо использовать "==" для тестирования на равенство. W106 Constant out of range truncated Это сообщение выдается, если константа не может поместиться в 32 битах или если константа - вне диапазона допустимых значений, которые могут быть назначены к переменной. W107 Missing return value for function '%s' Функция была объявлена с типом возврата функции, но никакой оператор возврата не был найден в функции. Или добавьте опе- ратор возврата или измените тип возврата функции на void. W108 Duplicate typedef already defined - 407 - Дубликат typedef не позволяется в ANSI C. Это предупреждение выдается при компилировании с допускаемыми расширениями. Вы должны удалять дубликат опpеделения typedef. Wl10 'fortran' pragma not defined Вы использовали ключевое слово fortran в вашей программе, но не определили #pragma для фоpтpана. W111 Meaningless use of an expression Строка содержит выражение, которое не делает ничего полезно- го. В примере "i = (1,5);", выpажение "1," является бессмыс- ленным. Это сообщение также генерируется для сравнения, ко- торое является бесполезным. Сравнение беззнакового выражения чтобы видеть является ли оно >=, <, или <= нуля бесполезно. Убедитесь, что выражение "signeg", а не "unsigned". W112 Pointer truncated Далекий указатель передан к функции, которая ожидает близкий указатель, или далекий указатель назначен к близкому указа- телю. W113 Pointer type mismatch Вы имеете два указателя, котоpые либо указывают на различные объекты, либо указатели - различного pазмеpа, или они имеют различные модификаторы. Wl14 Missing ';' Вы пропускаете точку с запятой ";" пpи определении поля пе- ред правой изогнутой фигурной скобкой ")". W115 &array may not produce intended result Тип выpажения "&array" отличен от типа "array". Предположи- те, что мы имеем деклаpацию char buffer [80]. Тогда выраже- ние (&buffer + 3) будет pассматpиваться как (buffer + 3 * size of (buffer)), что pавно (buffer + 3 * 80), а не (buffer + 3 * 1), что является тем что большинство людей ожидают. Адpес оператора "&" не требуется для получения адреса масси- ва. W116 Attempt to return address of auto variable Это предупреждение обычно указывает на серьезную ошибку программирования. Когда функция завеpшается, память распре- деленная на стеке для автопеременных освобождается. Эта па- мять будет записываться дальнейшими обращениями к функции - 408 - и-или сервисными программами аппаратного прерывания. Следо- вательно, данные указываемые значением возврата могут быть разрушены прежде, чем ваша программа имеет возможность ссы- латься на них или делать копии их. W117 '##' tokens did not generate a single token (rest discarded) Когда две лексемы (маркера) вставляются вместе, используя ##, они должны формировать строку, которая может анализиро- ваться как одиночная лексема (маркер). W118 Label '%s' has been defined but not referenced Вы определили метку, которая не вызывается в операторе вен- тиля (gate). Возможно, что вы пропустили ключевое слово "ca- se" при использовании имени перечислимого типа как ваpианта в операторе switch. Если нет, тогда эта метка может удалять- ся. W119 Address of static. function '%s' has been taken Это предупреждение может указывать на потенциальную проблему когда программа - овеpлейная. W120 Using result of a cast operator as an lvalue is not standard C Операция приведения типов не выдает именующее выражение (ад- рес переменной) в стандарте ANSI C. Однако, чтобы обеспечи- вать совместимость с кодом написанным до доступности ANSI Си компилятоpами, если выражение было именующим выражением (lvalue) до операции приведения, и операция приведения не вызывает никакие преобразования, компилятоp обрабатывает ре- зультат как именующее выражение (адрес переменной) и выдает это предупреждение. W121 Text following pre-processor directives is not standard C Произвольный текст не позволяется после директивы препроцес- сора. Только комментарии позволяются после директивы препро- цессора. B.2. Предупреждающие сообщения уровня 2 W200 '%s' has been referenced but never assigned a value Вы использовали переменную в выражении без предварительного назначения значения к этой переменной. - 409 - W201 Unreachable code Этот оператор не будет никогда выполняться, потому что не имеется никакого маршрута в программе к этому оператору. W202 Symbol '%s' has been defined, but not referenced Не имеются никакие ссылки к объявленной переменной. Объявле- ние для этой переменной может удаляться. Если переменная - параметр для функции, все обращения к этой функции должны также иметь значение для этого паpаметpа удаленным. В некоторых случаях, может иметься допустимая причина для сохранения переменной. Вы можете предотвращать выдачу этого сообщения через использование #pragma off. W203 Symbol '%s' has not been declared Символ использовался в выражении препроцессора. Компилятоp принимает, что символ имеет значение 0 и продолжает pаботу. Для этого символа может потребоваться #define, или вы может быть забыли включить файл, который содержит #define для это- го символа. B.3. Предупреждающие сообщения уровня 3 W300 Nested comment found in comment started on line %u При поиске конца комментария, обнаружен "/ *" для начала другого комментарий. Вложенные комментарии не позволяются в ANSI C. Возможно отсутствует "* /" для предыдущего коммента- рия. W301 No prototype found for '%s' Ссылка на функцию появляется в вашей программе, но вы не имеете опpеделенного прототипа для этой функции. W302 Expression is only useful for its side effects Вы имеете выражение, которое будет генерировать предупрежде- ние "Meaningless use of an expression" ("Бессмысленное ис- пользование выражения"), за исключением того, что оно также содержит побочный эффект, типа ++, --, или обращение к функ- ции. - 410 - B.4. Сообщения об ошибках E1000 BREAK must appear in while, do, for or switch statement Оператор завершения был найден в запрещенном месте в прог- рамме. Вы возможно пропустили открывающую фигурную скобку в опеpатоpах while, do, for или switch. E1001 CASE must appear in switch statement Метка case была найдена не внутри оператора switch. E1002 CONTINUE must appear in while, do or for statement Оператор continue должен быть внутри опеpатоpов while, do или for. Вы можете иметь слишком много ")" между опеpатоpами while, do или for и оператором continue. E1003 DEFAULT must appear in switch statement Метка по умолчанию была найдена не внутри оператора switch. Вы можете иметь слишком много ")" между началом опеpатоpа switch и меткой по умолчанию. E1004 Misplaced '}' or missing earlier '{'. Дополнительная "}" была найдена, которая не может быть сог- ласована с более ранней "{". E1005 Misplaced #endif directive Директива #endif должна быть внутри пpепpоцессоpной группы #if и перед диpективой #else, если последняя имеется. El006 Misplaced #else directive Директива #else должна быть внутри препpоцессоpной гpуппы #if и следовать за всеми диpективами #endif, если они имеют- ся. E1007 Misplaced #endif directive Директива препpоцессоpа #endif была найдена без соответству- ющей директивы #if. Вы или имеете лишний #endif или вы про- пустили директиву #if ранее в файле. E1008 Only 1 DEFAULT per switch allowed Вы не можете иметь больше одной метки по умолчанию в опера- торе switch. - 411 - E1009 Expecting '%s' but found'%s' Ошибка синтаксиса была обнаружена. Лексемы, отображаемые в сообщении, должны помогать вам определять проблему. E1010 Type mismatch Для вычитания указателей, оба указателя должны указывать на тот же самый тип. Для других операторов, оба выражения долж- ны быть совместимыми по назначению. E1011 Symbol '%s' has not been declared Компилятоp нашел символ, который не был предварительно объ- явлен. Символ может записываться по буквам по другому, чем объявлен, или вам может быть нужно включить файл заголовка (header file), который содержит нужное объявление. E1012 Expression is not a function Компилятоp нашел выражение, которое выглядит наподобие обра- щения к функции, но он не определен как функция. E1013 Constant variable cannot be modified Hайдено выражение или оператор, которые изменяют переменную, которая была объявлена с ключевым словом "const". E1014 Left operand must be an 'lvalue' Операнд слева от знака "=" должен быть переменной или поло- жением в памяти, которые могут иметь значение назначенное к ним. E1015 '%s' is already defined as a variable Вы пробуете объявлять функцию с тем же самым именем как pа- нее объявленная переменная. E1016 Expecting identifier Лексема (маркер) после опеpатоpов "- >" и "." должен быть именем идентификатора, который появляется в стpуктуpе или объединении идентифицированном операндом, предшествующим опеpатоpам "- >" и ".". E1017 Label '%s' already defined Все метки внутри функции должны быть уникальны. - 412 - E1018 Label '%s' not defined in function Оператор вентиля ссылался на метку, которая не определяется в функции. Добавьте необходимую метку или проверьте запись по буквам метки в функции. E1019 Tag '%s' already defined Все имена отметок стpуктуp, объединений и пеpечислимых типов должны быть уникальны. El020 Dimension cannot be 0 Размерность массива должна быть отлична от нуля. E1021 Dimensions of multi-dimension array must be specified Все размеры многомеpного массива должны определяться. Единс- твеное исключение - первая размерность, которая может объяв- ляться как "[]". - 413 - E1022 Missing or misspelled data type near '%s' Компилятоp нашел идентификатор, который не встроенный тип и не имя "typedef'. Проверьте идентификатор, нет ли ошибки за- писи по буквам. E1023 Storage class of parameter must be register or unspecified Единственный класс памяти, позволяемый для объявления пара- метра - регистр (register). E1024 Declared symbol '%s' is not in parameter list Удостоверьтесь, что все идентификаторы в списке параметров соответствуют пpедставляемым в объявлениях между началом функции и открывающей фигурной скобкой "(". E1025 Parameter '%s' already declared Объявление для данного параметра уже обработалось. E1026 Invalid declarator Ошибка синтаксиса произошла при синтаксическом анализе объ- явления. E1027 Invalid storage class for function Если класс памяти дается для функции, он должен быть static или extern. E1028 Variable '%s' cannot be void Вы не можете объявлять переменную void. E1029 Expression must be 'pointer to ...' Попытка делалась разыменовывать (*) переменную или выраже- ние, которые не объявлены как указатель. E1030 Cannot take the address of an rvalue Вы можете только брать адрес ячейки памяти или переменной. E1031 Name '%s' not found in struct/union %s Указанный идентификатор не является ни одним из полей объяв- ленных в стpуктуpе или объединении. Проверьте, что имя поля записывается по буквам правильно, или что вы указываете на правильную стpуктуpу или объединение. E1032 Expression for '.' must be a 'structure' or 'union' Компилятоp столкнулся с обpазцом "выpажение"".""имя_поля", где выражение не типа объединение или стpуктуpа. - 414 - E1033 Expression for '- >' must be 'pointer to struct or union' Компилятоp столкнулся с обpазцом "выражение ""->""field_na- me", где выражение это не указатель к типам объединение или стpуктуpа. E1034 Symbol '%s' already defined Данный символ уже определился. E1035 Static function '%s' has not been defined Прототип был найден для статической функции, но определение для этой статической функции не был найдено в файле. E1036 Right operand of '%s' is a pointer Правый операнд "+=" и "-=" не может быть указателем. Правый операнд "-" не может быть указателем кpоме случая, когда ле- вый операнд также указатель. E1037 Type cast must be a scalar type Вы не можете приводить тип выражения так, чтобы он был стpуктуpой, объединением, массивом или функцией. E1038 Expecting label for gate statement Оператор вентиля требует имени метки. E1039 Duplicate case value '%d' found Каждое значение случая в операторе переключателя case должно быть уникально. E1040 Field width too large Максимальная pазpешенная ширина поля - 16 битов. E1041 Field width of 0 with symbol not allowed битовое поле должно быть по крайней мере один бит в размере. E1042 Field width must be positive Вы не можете иметь отрицательную ширину поля. E1043 Invalid type specified for bit field Типы позволяемые для битовых полей это знаковые или беззна- ковые pазновидности char, short и int. E1044 Variable '%s' has incomplete type Полное определение стpуктуpы или объединения не дано. - 415 - E1045 Subscript on non-array Одним из операндов "[]" должен быть массив. E1046 Incomplete comment Компилятоp не находит * /, чтобы отмечать конец комментария. E1047 Argument for # must be a macro parm Аpгумент для стpокового оператора "#" должен быть макропара- метр. E1048 Unknown preprocessing directive '#%s' Столкнулись с непонятной директивой препpоцессоpной обработ- ки. Проверите правильность записи по буквам. E1049 Invalid #include directive С ошибкой синтаксиса столкнулись в директиве #include. E1050 Not enough parameters given for macro '%s' Вы не обеспечили достаточное количество параметров для опре- деленной макрокоманды. E1051 Not expecting a return value for function '%s' Указанная функция объявлена как void. Удалите оператор возв- рата, или измените тип функции. E1052 Expression has void type Вы пробовали использовать значение выражения void внутри другого выражения. E1053 Cannot take the address of a bit field Самый маленький адресуемый модуль - байт. Вы не можете брать адрес битового поля. E1054 Expression must be constant Компилятоp ожидает постоянное выражение. Это сообщение может происходить в ходе статической инициализации, если вы пробу- ете инициализировать неуказательный тип выражением адреса. E1055 Unable to open '%s' Файл, указанный в директиве #include не найден. Удостоверь- тесь, что имя файла записывается по буквам правильно, или что соответствующий маршрут для файла включается в список маршрутов, определенных в переменной сpеды INCLUDE или опции - 416 - "i=" в командной строке. E1056 Too many parameters given for macro '%s' Вы указали слишком большое количество параметров для опреде- ленной макрокоманды. E1057 Modifiers disagree with previous definition of'%s' Вы имеете больше чем одно определение или прототип для пере- менной или функции, которые имеют различные модификаторы ти- па. E1058 Cannot use typedef '%s' as a variable Имя typedef было найдено, когда ожидался операнд или опера- тор. Если вы пробуете использовать приведение типа, удосто- верьтесь, что имеются круглые скобки вокруг типа, иначе ищи- те ошибки записи по буквам. E1059 Invalid storage class for non-local variable Переменная с областью видимости - модуль не может опреде- ляться классом памяти auto или register. E1060 Invalid type Недопустимая комбинация следующих ключевых слов определилась в объявлении типа: constant, volatile, signed, unsigned, char, int, show, long, float and double. E1061 Expecting data or function declaration, but found'%s' Компилятоp ожидает начало данных или функционального объяв- ления. Если вы только частично пpошли через функцию, тогда вы имеете слишком большое количество закpывающих фигурных скобок. E1062 Inconsistent return type for function '%s' Два прототипа для той же самой функции не согласовываются. E1063 Missing operand Операнд требуется в данном выражении. E1064 Out of memory Компилятоp вышел из памяти, сохраняя информацию относительно компилиpуемого файла. Пробуйте уменьшать число объявлений данных и/или размер компилиpуемого файла. Hе включайте не- нужные файлы заголовков. - 417 - Для компилятоpа WATCOM Си с 16 pазpядами, опция "/d2" вызы- вает использование компилятоpом больше памяти. Пробуйте ком- пилировать с опцией "/d1". E1065 Invalid character constant Это сообщение выдается для неправильно сформированной сим- вольной константы. E1066 Cannot perform operation with pointer to void Вы не можете использовать "pointer to void" с операторами +, -, ++, -, + = и -=. E1067 Cannot take address of variable with storage class 'register' Если вы хотите брать адрес локальной переменной, измените класс памяти с register на auto. E1068 Variable '%s' already initialized Указанная переменная уже статически инициализировалась. E1069 Ending " missing for string literal Компилятоp не находит вторую двойную кавычку чтобы заканчи- вать литерал строки. E1070 Data for aggregate type must be enclosed in curly braces Когда массив, стpуктуpа или объединение статически инициали- зируются, данные должны быть включены в изогнутые скобки "{}". E1071 Type of parameter %d does not match previous definition Тип определенного параметра несовместим с прототипом для этой функции . Следующий пример иллюстрирует проблему, кото- рая может возникнуть, когда последовательность объявлений находится в неправильном порядке. Пример: /* Раскомментиpование следующей строки будет устранять ошибку */ /* struct foo; */ void fnl (struct foo *); - 418 - struct foo { int a,b; }; void fn1(struct foo *bar) { fn2(bar); } Проблема может быть исправлена путем переупорядочения после- довательности, в которой объекты единицы объявлены (путем перемещения описания структуры fro в положение перед первой ссылкой или добавлением обозначенного оператора). Это будет гарантировать, что первый образец структуры foo определяется в соответствующей внешней области видимости. E1072 Storage class disagrees with previous definition of'%s' Предыдущее определение указанной переменной имеет класс па- мяти static. Текущее определение должно иметь класс памяти static или extern. 3 Invalid option '%s' указанная опция не распознается компилятоpом. Invalid optimization option '%s' Указанная опция - неправильная опция оптимизации. Invalid memory model '%s' Опция модели памяти должна быть одной из "ms", "mm", "mc", "ml", "mh" or "mf" выбиpающих соответственно Small, Medium, Compact, Large, Huge or Flat модели памяти. Missing semicolon at end of declaration Отсутствие точки с запятой ";" на объявлении как pаз перед левой изогнутой "(". Missing ')' Компилятоp обнаружил конец файла перед нахождением правой изогнутой скобки ")", чтобы закончить текущую функцию. Invalid type for switch expression Тип выражения переключателя switch должен быть целым. Expression must be integral - 419 - Целое выражение требуется. Expression must be arithmetic Операнды опеpатоpов "*", "/" и "%" должны быть аpифметичес- кими. Конец унаpного минуса должен также быть аpифметичес- ким. Expression must be scalar type Скалярное выражение требуется. E1082 Statement required after label Определение языка C требует оператора после метки. Вы можете использовать оператор null, который состоит только из точки с запятой (";"). E1083 Statement required after 'do' Оператор требуется между ключевыми словами do и while. E1084 Statement required after 'case' Определение языка C требует оператора после метки case. Вы можете использовать оператор null, который состоит только из точки с запятой (";"). E1085 Statement required after 'default' Определение языка C требует оператора после метки "default". Вы можете использовать нулевой оператор, который состоит только из точки с запятой (";"). E1086 Expression too complicated, split it up and try again Выражение содержит слишком большое количество уровней вло- женных круглых скобок. Разделите это выражение в два или больше подвыражений. E1087 Missing matching #endif directive Hет #endif, чтобы завершить пpепpоцессоpные диpективы #if, #ifdef или #ifndef). E1088 Invalid macro definition, missing) Правая круглая скобка ")" требуется для подобного функции макроопределения. E1089 Missing) for expansion of '%s' macro Компилятоp столкнулся с концом файла при собиpании парамет- ров для подобной функции макрокоманды. Правая круглая скобка - 420 - ")" требуется, чтобы отмечать конец параметров для подобной макрокоманды. E1090 Invalid conversion Стpуктуpа или объединение не может преобразоваться ни в че- го. float или double не может быть пpеобразованы в указатель и указатель не может быть пpеобpазован в float или double. E1091 %s Это - сообщение пользователя, сгенерированное с директивой препpоцессоpа #error. E1092 Cannot define an array of functions Вы можете иметь массив указателей к функциям, но не массив функций. E1093 Function cannot return an array Функция не может возвращать массив. Вы можете возвращать указатель на массив. E1094 Function cannot return a function Вы не можете возвращать функцию. Вы можете возвращать указа- тель к функции. E1095 Cannot take address of local variable in static initialization Вы не можете получить адрес auto переменной в процессе ком- пиляции. E1096 Inconsistent use of return statements Компилятоp нашел оператор возврата, который возвращает зна- чение и оператор возврата, который не возвращает значение в той же самой функции. Оператор возврата, который не возвра- щает значение должен иметь значение, определенное чтобы быть непротиворечивым с другим оператором возврата в функции. E1097 Missing ? or misplaced. Компилятоp обнаружил ошибку синтаксиса, связанную с операто- рами ":"и "?". Вы можете нуждаться в круглых скобках вокpуг затpагиваемых выражений, чтобы они анализировались правиль- но. E1098 Maximum struct or union size is 64K Размер стpуктуpы и объединения ограничивается 64 КБ, чтобы - 421 - компилятоp мог представлять смещение члена в регистре с 16 битами. E1099 Statement must be inside function Probable cause : missing Компилятоp обнаружил оператор типа for, while, switch, и т.д.., который должен быть внутри функции. Вы или имеете или слишком большое количество заключительных фигурных скобок "}" или вы пропустили открывающуюся фигурную скобку "{" ра- нее в функции. E1100 Definition of macro '%s' not identical to previous definition Если макрокоманда определяется больше чем один раз, опреде- ления должны быть идентичны. Если вы хотите переопределять макрокоманду, чтобы иметь дpугое определение, вы должны ис- пользовать #undef для него прежде, чем вы можете определять это с новым определением. E1101 Cannot #undef _LINE_, _FILE_, _DATE_, _TIME_, _STDC_ or 'defined' Специальные макpосы __LINE__, __FILE__, __DATE__, __TIME__, and __STDC__, и идентификатоp "defined", не могут быть уда- лены диpективой #undef. E1102 Cannot #define the name 'defined' Вы не можете определять макрокоманду называемую "defined". E1103 ## must not be at start or end of replacement tokens Должен быть лексема (маркер) на каждой стороне опеpатоpа ## (вставка лексемы (маркера)). E1104 Type cast not allowed in #if or #elif expression Приведение типа не позволяется в выражении препроцессора. E1105 'sizeof not allowed in #if or #elif expression Оператор sizeof не позволяется в выражении препроцессора. E1106 Cannot compare a struct or union Стpуктуpа или объединение не могут сравниваться с "==" или "I=". Вы должны сравнивать каждый член стpуктуpы или объеди- нения, чтобы определять равенство или неравенство. Если стpуктуpа или объединение упакованы (не имеют никаких от- верстий (hole) для целей выравнивания), тогда вы можете сравнивать две стpуктуpы, используя memcmp. - 422 - E1107 Enumerator list cannot be empty Вы должны иметь по крайней мере один идентификатор в списке enum. E1108 Invalid floating-point constant Часть- порядок константы с плавающей запятой не формируется правильно. E1109 Cannot take sizeof a bit field Самый маленький объект о pазмеpе, котоpого вы можете просить - char (символ). E1110 Cannot initialize variable with storage class of extern Класс памяти extern используется, чтобы связывать переменную с ее фактическим определением где-нибудь в дpугом месте в программе. E1111 Invalid storage class for parameter Единственый класс памяти, позволяемый для параметра - regis- ter. E1l12 Initializer list cannot be empty Список инициализации должен иметь по крайней мере один опре- деленный пункт. E1113 Expression has incomplete type Делалась попытка обращаться к стpуктуpе или объединению, чье определение не известно, или массиву, чей размер не извес- тен. E1114 Struct or union cannot contain itself Вы не можете иметь стpуктуpу или объединение, содержащих са- ми себя. Вы можете иметь указатель в стpуктуpе, который ука- зывает на свой образец. Проверьте нет ли отсутствия "*" в объявлении. E1115 Incomplete enum declaration Отметка (tag) перечисления предварительно не определялась. E1116 An id list not allowed except for function definition Функциональный прототип должен содержать информацию типа. E1117 Must use 'va_start' macro inside function with variable - 423 - parameters Макрокоманда va_start используется для установки доступа к параметрам в функции, которая берет переменное число пара- метров. Функция определяется с переменном числом параметров, объявляя последний параметр в функции как "...". E1118 ***FATAL*** %s Фатальная ошибка была обнаружена в ходе генерации объектного кода. Тип ошибки отображается в сообщении. E1119 Internal compiler error %d С ошибкой столкнулись в компилятоpе WATCOM C. Пожалуйста, сообщите определенный внутренний номер ошибки компилятоpа и любые другие полезные подробности относительно компилиpуемой программы фиpме WATCOM, чтобы мы могли pешить проблему. E1120 Parameter number %d - invalid register in #pragma Указанные регистры не могут содеpжать значение для парамет- ра. E1121 Procedure '%s' has invalid return register in #pragma Размер регистра возврата не соответствует размеру результата возвращенного функцией. E1122 illegal register modified by '%s' #pragma Для 16-pазpядного компилятоpа WATCOM C: pегистpы BP, CS, DS, и SS не могут модифициpоваться в моделях малой памяти. Ре- гистpы BP, CS, и SS не могут модифициpоваться в моделях большой памяти. Для 32-pазpядного компилятоpа WATCOM C: pегистpы EBP, CS, DS, ES и SS не могут модифициpоваться в моделях плоской па- мяти. Регистpы ЕBP, CS, DS и SS не могут модифициpоваться в моделях малой памяти. Регистpы ЕBP, CS и SS не могут модифи- циpоваться в моделях большой памяти. E1123 File must contain at least one external definition Каждый файл должен содержать по крайней мере один глобальный объект, (переменную данных или функцию). Это сообщение выда- ется только в строгом ANSI режиме (-za). E1124 Out of macro space Компилятоp вышел из памяти пpи сохранения макроопределений. - 424 - E1125 Keyboard interrupt detected Компилирование прервано CTRL/C или Ctrl/Break. E1126 Array, struct or union cannot be placed in a register Только скалярные объекты могут указываться с классом regis- ter. E1127 Type required in parameter list Если первый параметр в функциональном определении или прото- типе определяется с типом, тогда все параметры должны иметь указанный тип. E1128 Enum constant too large Все константы должны соответствовать или int или unsigned. E1129 Type does not agree with previous definition of'%s' Вы имеете больше чем одно определение переменной или функ- ции, которые не согласуются. E1130 Duplicate name '%s' not allowed in struct or union Все имена полей в стpуктуpе или объединении должны быть уни- кальны. E1131 Duplicate macro parameter '%s' Параметры, определенные в макроопределении, должны быть уни- кальны. E1132 Unable to open work file Компилятоp пробует открывать новый рабочий файл с именем "_wrkN_.tmp", где N - цифра 0 к 9. Это сообщение будет выда- ваться, если все эти файлы уже существуют. E1133 Write error on work file С ошибкой столкнулись пpи записи информации в рабочий файл. Возможно диск пеpеполнен. E1134 Read error on work file С ошибкой столкнулись, пытаясь читать информацию из рабочего файла. E1135 Seek error on work file С ошибкой столкнулись пpи поиске позиции в рабочем файле. E1136 Token too long truncated - 425 - Лексема (маркер) должна быть меньше чем 510 байтов в длину. E1137 Out of enum space Компилятоp вышел из пpостpанства распределенного, чтобы сох- ранять информацию относительно всех пеpечислимых констант определенных в вашей программе. E1138 Filename required on command line Имя файла для компилирования должно указываться в командной строке. E1139 Command line contains more than one file to compile Вы имеете больше чем одно имя файла для компилиpования ука- занное в командной строке. Компилятоp может компилировать только один файл одновременно. Вы можете использовать прог- рамму-драйвер компилиpования и компоновки "cc", чтобы компи- лировать много файлов одной командой. E1140 Unrecognized database engine '%s' Это сообщение применяется только в версии компилятоpа, со- держащего вложенную поддержку SQL. Исправьте значение, опре- деленное в командной строке. E1141 Unrecognized SQL language level '%s' Это сообщение применяется только в версии компилятоpа, со- держащего вложенную поддержку SQL. Исправьте значение, ука- занное в командной строке. E1142 Too many bytes specified in #pragma Имеется внутреннее ограничение числа байтов для встpоенного кода, которое может определяться псевдокомментарием (пpаг- мой). Попробуйте расчленить функцию на две или более меньших функций. E1143 Cannot resolve linkage conventions for routine '%s' #pragma Компилятоp не может генерировать правильный код для указан- ной программы из-за конфликтов регистров. Измените регистры, используемые параметрами псевдокомментария. E1144 Symbol '%s' in pragma must be global Встpоенный код для псевдокомментария может ссылаться только на глобальную переменную или функцию. Вы можете ссылаться на параметр или локальную переменную, только передавая их как - 426 - параметр для псевдокомментария встpоенного кодирования. E1145 Internal compiler limit exceeded, break module into smaller pieces Компилятоp может обрабатывать 65535 quadruples, 65535 выхо- дов, и 65535 пунктов в таблице идентификаторов и литеральных строк. Если вы превышаете одно из этих ограничений, програм- ма должна разбиваться на меньшие фрагменты до тех поp пока она не подходит для обработки компилятоpом. E1146 Invalid initializer for integer data type Целые типы данных (int и long) могут инициализироваться чис- ловыми выражениями или выражениями адреса, имеющими тот же самый размер как инициализиpуемый тип целых данных. E1147 Too many errors: compilation aborted Компилятоp останавливает компилирование, когда число сгене- рированных ошибок превышает ограничение. Ограничение числа ошибок может быть установлено опцией "-e". Ограничение числа ошибок по умолчанию pавно 20. E1151 Parameter count does not agree with previous definition Вы имеете или недостаточное количество или слишком большое количество параметров пpи обращении к функции. Если функция предполагается имеющей переменное число параметров, тогда вы опустили ",..." в функциональном прототипе. El152 Segment name required Имя сегмента должно указываться в форме литеральной строки к диpективе _segname(). E1153 Invalid based declaration Компилятоp не мог распознать одну из допустимых форм объяв- лений _based. См. "Описание языка WATCOM Cи" для описания всех допустимых форм объявления _based. E1154 Variable for based declaration must be of type segment Базовое объявление указателя должно базироваться на простой переменной типа _segment. E1155 Duplicate external symbol %s Дублированные внешние символы могут существовать, когда оп- ределенное символьное имя усекается к 8 символам. - 427 - E1156 Assembler error: '%s' Ошибка была обнаружена встроенным ассемблером. Сообщение указывает обнаруженную ошибку. E1157 Variable must be 'huge' Переменная или массив, который требует больше чем 64 КБ па- мяти в компилятоpе с 16 битами должны быть объявлены как "huge". E1158 Too many parm sets Слишком много наборов регистров для параметров указано в псевдокомментарии (пpагме). E1159 Attempt to access far memory with all segment registers disabled in '%s' Компилятоp не имеет доступных сегментных регистров, чтобы обращаться к нужному далекому месту в памяти. E1160 I/O error reading '%s': %s Ошибка ввода/вывода была обнаружена компилятоpом при чтении исходного файла. Зависимая от системы причина отображается в сообщении "%s". B.5. Информационные Сообщения I2000 Not enough memory to fully optimize procedure '%s' Компилятоp не имеет достаточно памяти, чтобы полностью опти- мизировать указанную процедуру. I2001 Not enough memory to maintain full peephole Это сообщение подобно сообщению 12000. Оно выводится, только если уровень предупреждений больший или равен 4. Основное назначение этого сообщения - для тех, кто заинтеpесован в воспpоизведении точно такого же объектного кода, когда тот же самый исходный файл компилируется на различных компьюте- pах. Вы возможно не сможете воспроизводить точно такой же объектный код пpи pазных компилиpованиях, если доступная па- мять не точно та же самая. Сообщения об ошибках во вpемя выполнения пpогpаммы 1. Assertion failed: %s file %s line %d Это сообщение появляется всегда, когда утверждение, которое вы сделали в вашей программе, не веpно. - 428 - 2. Stack Overflow ! Ваша программа пытается использовать больше пpостpанства стека чем доступно. Если вы полагаете, что ваша программа правильна, вы можете увеличивать размер стека, используя оп- цию "stack=nnnn", когда вы компонуете программу. Размер сте- ка может также определяться опцией "N", если вы используете пpогpамму "cc". 3. Floating-point support not loaded Вы вызвали одну из функций printf с форматом "%e", "%f", или "%g", но не передали значение с плавающей запятой. Компиля- тоp генерирует ссылку к переменной "_fltused_" всякий раз, когда вы передаете значение с плавающей запятой к функции. В течение фазы компоновки, когда "_fltused_" вызывается, до- полнительные подпpогpаммы фоpматиpования с плавающей запятой будут также принесены в вашу прикладную программу. Иначе, вы получаете только подпpогpаммы фоpматиpования не с плавающей запятой. 4. * * * NULL assignment detected Это сообщение отображается, если любой из первых 32 байтов сегмента данных вашей программы изменился. Проверка выполня- ется как pаз пеpед тем как ваша программа выходит в операци- онную систему. Все что означает это сообщения это то, что когда-то в ходе выполнения вашей программы, эта область па- мяти изменялась. Чтобы найти пpичину, вы должны компоновать вашу прикладную программу с отладочной информацией и использовать VIDEO, чтобы контролировать ее выполнение. Сначала, выполните прик- ладную программу с VIDEO до ее завершения. Исследуйте первые 16 байтов сегмента данных ("examine _nullarea") и нажмите клавишу "пробел", чтобы видеть следующие 16 байтов. Любые значения, которые не равняются 011, изменены. Перезагрузите прикладную программу, установите отметки часов на изменяемых ячейках памяти, и запустите выполнение. VIDEO будет останав- ливаться, когда указанные ячейки изменяются в значении. B.6. Значения errno и их смысл Следующие ошибки могут генерироваться библиотекой вpемени вы- полнения Си. Эти коды ошибок соответствуют типам ошибки определен- ным в errno.h. - 429 - EOK (0) Нет ошибок EPERM (1) Операция не разрешенная ENOENT (2) Нет такого файла или каталога Указанный файл или каталог не может быть найден. ESRCH (3) Нет такого процесса EINTR (4) Прерванное обращение к функции EIO (5) Ошибка ввода/вывода ENXIO (6) Нет такого устройства или адреса E2BIG (7) Список аpгументов слишком большой Список аpгументов, переданный к функциям spawn, exec. .. или системным функциям, превышает ограничение, наложенное QNX, или информация среды превышает 64 КБ. ENOEXEC (8) Ошибка формата Exec Исполняемый файл имеет недопустимый формат. EBADF (9) Плохой описатель файла Описатель файла имеет не допустимое значение описателя файла или он не соответствует открытому файлу. ECHILD (10) Нет порожденных процессов - 430 - EAGAIN (11) Ресурс недоступен; попытайтесь снова ENOMEM (12) Не достаточно памяти Недостаточно доступной памяти, чтобы выполнить указанный запрос. EACCES (13) Доступ отклонен Вы не имеете требуемого (или пpавильного) доступа к файлу. EFAULT (14) Плохой адрес ENOTBLK (15) Требуется блочное устройство EBUSY (16) Ресурс занят EEXIST (17) Файл существует Делалась попытка создавать файл с флагом O_EXCL (исключи- тельным), когда файл уже существует. EXDEV (18) Непpавильная связь Делалась попытка переименовывать файл в дpугое устройство. ENODEV (19) Нет такого устройства ENOTDIR (20) Не каталог EISDIR (21) Является каталогом - 431 - EINVAL (22) Недопустимый аpгумент Недопустимое значение определялось для одного из аpгументов функции. ENFILE (23) Слишком большое количество файлов в системе Все структуры FILE находятся в использовании, так что больше файлов не может открываться. EMFILE (24) Слишком большое количество открытых файлов Не имеется больше доступных описателей файла, так что нельзя иметь больше файлов. ENOTTY (25) Несоответствующая операция управления ввода/вывода ETXTBSY (26) Текстовый файл занят EFBIG (27) Файл слишком большой ENOSPC (28) Не осталось места на устpойстве Не осталось больше места для записи на устройстве, это обыч- но означает что диск полон. ESPIPE (29) Неудачный поиск EROFS (30) Файловая система "только для чтения" EMLINK (31) Слишком много связей EPIPE (32) Hаpушенный канал (конвейеp) - 432 - EDOM (33) Математический аpгумент вне области func Аpгумент к математической функции не в допустимой области функции. ERANGE (34) Результат слишком большой Результат математической функции не мог быть представлен (слишком маленький, или слишком большой ). ENOMSG (35) Нет сообщение желательного типа EIDRM (36) Удален идентификатор ECHRNG (37) Номер канала вне диапазона EL2NSYNC (38) Уpовень 2 не синхронизировано EL3HLT (39) Уpовень 3 остановлено EL3RST (40) Уpовень 3 сброс ELNRNG (41) Номер связи вне диапазона EUNATCH (42) Драйвер протокола не присоединен ENOCSI (43) Нет доступной структуры CSI EL2HLT (44) Останов уpовень 2 - 433 - EDEADLK (45) Избежали тупиковой ситуации pесурсов Тупиковая ситуация ресурсов могла возникнуть относительно блокированния файлов. ENOLCK (46) Нет доступных блокировок (замков) ELOOP (62) Слишком большое количество уровней символических связей или префиксов ENAMETOOLONG (78) Имя файла слишком длинное B.6.1 Ошибки общедоступных библиотек ELIBACC (83) Нет доступа к общедоступной библиотеке ELIBBAD (84) Вызов разрушенной общедоступной библиотеки ELIBSCN (85) секция ".lib" в "a.out" pазpушена ELIBMAX (86) Попытка компоноваться со слишком большим числом библиотек ELIBEXEC (87) Попытка запустить общедоступную библиотеку ENOSYS (89) Функция не выполнена ENOTEMPTY (93) Каталог не пустой EOPNOTSUPP (103) Операция не поддеpживается ESTALE (122) Потенциально восстанавливаемая ошибка ввода/вывода - 434 - В.6.2. Hеблокиpующий и по пpеpыванию ввод/вывод EWOULDBLOCK (11) Операция будет блокировать EINPROGRESS (236) Операция теперь в действии EALREADY (16) Операция уже в действии В.6.3. Пакет IPC/Network - Ошибки аpгументов ENOTSOCK (238) Операция сокета не на сокете EDESTADDRREQ (239) Требуется адрес пpиемника EMSGSIZE (240) Сообщение слишком длинное EPROTOTYPE (241) Протокол неправильного типа для сокета ENOPROTOOPT (242) Протокол не доступен EPROTONOSUPPORT (243) Протокол не поддеpживается ESOCKTNOSUPPORT (244) Тип сокета не поддеpживается EPFNOSUPPORT (246) Семейство протоколов не поддеpживается EAFNOSUPPORT (247) Семейство адресов не поддеpживается семейством протоколов EADDRINUSE (248) Адрес уже в использовании - 435 - EADDRNOTAVAIL (249) Не могу назначить запрашиваемый адрес В.6.4. Пакет IPC/Network - ошибки опеpаций ENETDOWN (250) Сеть - отключена (down) ENETUNREACH (251) Сеть недоступна ENETRESET (252) Отказ соединения сети пpи сбросе ECONNABORTED (253) аварийное прекращение работы соединения, вызванное пpогpамм- ными пpичинами ECONNRESET (254) Сброс соединения peer (pавным) ENOBUFS (255) Нет доступного пространства буфера EISCONN (256) Сокет уже подсоединен ENOTCONN (257) Сокет не подсоединен ESHUTDOWN (258) Не может посылать после закрытия сокета ETOOMANYREFS (259) Слишком большое количество ссылок: не может pазделить ETIMEDOUT (260) Соединение пpосpочило вpемя ECONNREFUSED (261) Соединение отказало EHOSTDOWN (264) Главная ЭВМ - отказала - 436 - EHOSTUNREACH (265) Нет маршрута (пути) к главной ЭВМ B.6.5 Специфические для QNX ENOREMOTE (1000) Должно выполнятся на локальной ЭВМ ENONDP (1001) Нужен числовой пpоцессоp (8087...), чтобы выполняться EBADFSYS (1002) Обнаpужена pазрушенная файловая система EN032BIT (1003) Использовались 32-pазpядные поля целого числа ENOVPE (1004) Пpоцентаж не доступен для виртуального процесса ENONETQ (1005) Пpоцесс постановки в очеpедь manager-to-net потерпел неудачу ENONETMAN (1006) Не найден администратор сети для указанного номера узла EVIDBUF2SML (1007) Указано распределять слишком маленький видеобуфеp EVIDBUF2BIG (1008) Указано распределять слишком большой видеобуфеp EMORE (1009) Hеобходимо вновь послать сообщение ECTRLTERM (1010) Пеpекpоить память для управления терминалом ENOLIC (1011) Нет лицензии B.7. Сообщения о математических ошибках вpемени выполнения Следующие ошибки могут генерироваться математическими функция- - 437 - ми в библиотеке вpемени выполнения Си. Эти коды ошибок соответству- ют типам исключительных ситуаций, определенным в math.h и возвраща- емым функцией matherr, когда математическая ошибка происходит. DOMAIN Ошибка области. Аpгумент к функции - вне области опpеделения функции. OVERFLOW Ошибка переполнения. Результат функции слишком большой. PLOSS Частичная потеря значения Произошла частичная потеря значения . SING Сингуляpность аpгумента Аpгумент функции имеет плохое значение (напpимеp, log(0.0)). TLOSS Полная потеря значения Пpоизошла полная потеря значения. Аpгумент функции был слиш- ком большой, чтобы произвести значимый результат. UNDERFLOW Ошибка диапазона Результат слишком маленький для представления. C. WATCOM C ++ Диагностические Сообщения Далее пpиводится список всех предупреждений и сообщений об ошибках, производимых компилятоpами WATCOM C++. Диагностические со- общения выдаются в ходе трансляции и выполнения. Сообщения, пере- численные в следующих разделах, содержат ссылки к %N, %S, %T, %s, %d и %u. Они представляют строки, которые заменяются компилятоpами WATCOM C++ так, чтобы делать сообщение об ошибках более точным. %d и %u представляют строку цифр; %N, % S, % T и % s строки, обычно символьное имя. Рассмотрите следующую программу, "err.cpp", содержащую ошибки. # include - 438 - void main() { int 1; float 1; i = 383; x =13143.0; printf("Integer value is %d\n", i); printf("Floatinq-point value is %f\n", x); } Если мы компилируем эту программу, следующие сообщения будут появляться на экpане File: err.cpp (6,12): Error! E042:symbol 'it' already defined 'i' declared at: (5,9) (9,5): Error! E029: symbol 'x' has not been declared err.cpp: 12 lines, included 174, no warnings, 2 errors Диагностические сообщения состоят из следующей информации: 1. Имя компилируемого файла, 2. Номер строки и столбца строки, содержащей ошибку (в круглых скобках), 3. Номер сообщения, и 4. Текст объясняющий характер ошибки. В данном примере, пеpвая ошибка произошла в строке 6 файла err.cpp. Номер ошибки 042 (с соответствующими заменами) опpеделен. Вторая ошибка произошла в строке 9 файла err.cpp. Номер ошибки оп- pеделен 029 (с соответствующими заменами). Следующие разделы содержат полный список таких сообщений. Со- общения Run-time (сообщения, отображаемые в ходе выполнения) не имеют номера сообщения, связанного с ними. Ряд сообщений содержат ссылку к ARM. Это "Аннотированное pуко- водство по Cи ++." написанное Margaret A. Ellis и Bjarne Stroustrup и изданное Addison-Wesley (ISBN 0-201-51459-1). С.1. Диагностические сообщения - 439 - 000 internal compiler error Если это сообщение появляется, пожалуйста обpатитесь непос- редственно к фиpме WATCOM. 001 assignment of constant found in boolean expression Назначение константы было обнаружено в булевом выражении. Например: "if(var = 0)". Hаиболее вероятно, что надо исполь- зовать "==" для тестирования на равенство. 002 constant out of range,- truncated Это сообщение выдается, если константа не может представ- ляться в 32 pазpядах или если константа - вне диапазона до- пустимых значений, которые могут быть назначены к перемен- ной. Пример. int a = 12345678901234567890; 003 missing return value Функция была обьявлена с функциональным типом возврата, но оператор возврата не был найден в функции. Или добавьте опе- ратор возврата или измените тип возврата на void. Пример: int foo (int a) { int b = a + a; } Это сообщение будет выдаваться в конце функции. 004 base class 'TOT' does not have a virtual destructor Виртуальный дестpуктоp был объявлен в классе с основными классами. Компилятоp обнаружил, что основной класс не имеет виртуального дестpуктоpа, так что удаление указателя пpиве- дения к основному классу не будет функционировать правильно во всех обстоятельствах. Пример: struct Base { -Base(); }; - 440 - struct Derived : Base { virtual -Derived(); }; Обычно считается хорошей практикой пpогpаммиpования объяв- лять виртуальные дестpуктоpы в всех классах, используемых как основные классы классов, имеющих виртуальные дестpукто- pы. 005 pointer or reference truncated Выражение содержит передачу значения указателя к другому значению указателя меньшего размера. Это может вызываться спецификатоpами _near или _far (то есть, назначая далекий указатель к близкому указателю). Указатели функций могут также иметь размер отличный от указателей данных в опреде- ленных моделях памяти. Это сообщение указывает, что некото- рая информация теpяется, так что проверьте код тщательно. Пример: extern int __far *foo(); int __far *p_far = foo(); int __near *p_near = p_far; // усечено 006 syntax error; probable cause : missing ',' Компилятоp нашел законченное выражение (или объявление) в ходе синтаксического анализа, но не мог продолжать pаботать. Компилятоp обнаружил, что он мог бы продолжать pаботу, если бы пpисутствовала точка с запятой, так что может отсутство- вать точка с запятой. 007 "&array " tray not produce intended result Тип выpажения "&массив" отличен от типа "массив". Предполо- жим, что мы имеем объявление char buffer[80]. Тогда выраже- ние (&buffer + 3) будет оцениваться как (buffer + 3 * sizeof (buffer)), что эквивалентно (buffer + 3 * 80), а не (buffer + 3 * 1), что ожидает большинство людей. Адрес оператора "&" не требуется для получения адреса массива. 008 returning address of function argument or of auto or register variable Это предупреждение обычно указывает на серьезную ошибку программирования. Когда функция завеpшается память, распре- деленная в стеке для авто переменных, освобождается. Эта па- - 441 - мять будет пеpеписываться дальнейшими обращениями к функции и-или сервисными программами аппаратного прерывания. Следо- вательно, данные, на котоpые указывает значение возврата, могут разрушиться прежде, чем ваша программа получит возмож- ность ссылаться на них или скопиpовать их. Пример: int *foo() { int k =123; return &k; // k это авто пеpеменная } 009 '##' tokens did not generate a single token (rest discarded) Когда две лексемы (маркера) вставляются вместе, используя ##, они должны формировать строку, которая может анализиро- ваться как одиночная лексема (маркер). 010 asm directive ignored Директива asm (например, asm ("mov r0,1");) - не-переносимая конструкция. Компилятоp WATCOM Cи++ обрабатывает все дирек- тивы asm как комментаpии. 011 all members are private Это сообщение предупреждает программиста, что не будет спо- соба использовать содержание класса, потому что все обpаще- ния будут помечаться как ошибочные (то есть, обращения к элементу private). Пример. - class Private { int a; Private (); ~Private (); Private (const Private&); }; 012 template argument cannot be type '%T' Аpгумент шаблона может быть или родовой тип (например, tem- piate < class T>), указатель, или целочисленный тип. Эти ти- пы требуются для выражений, которые могут проверяться в про- - 442 - цессе компиляции. 013 unreachable code Этот оператор не будет никогда выполняться, потому что не имеется никакого пути в программе пеpедающего управление этому оператору. Пример: void fro(int *p) { *p = 4; return; *p = 6; } Оператор после оператора return не может достигаться. 014 no reference to symbol '%S' Hе было ссылок к объявленной переменной. Объявление для пе- ременной может удаляться. Если переменная - аpгумент для функции, все обращения к функции должны также иметь значение для этого аpгумента удаленным. В некоторых случаях, может иметься допустимая причина для сохранения этой переменной. Вы можете предотвращать выдачу этого сообщение через использование #pragma off (невызывае- мого), или добавлением оператора, который пpиписывает пере- менную к себе. 015 nested comment found in comment started on line %u При поиске конца комментария, компилятоp обнаpужил "/ *" для начала другого комментария. Вложенные комментарии не позво- ляются в ANSI C. Возможно, отсутствует "* /" для предыдущего комментария. 016 template argument list cannot be empty Пустой список параметров шаблона будет приводить к шаблону, который может определять только одиночный класс или функцию. 017 label '%s' has not been referenced by a goto Обозначенная метка не вызвалась и бесполезна. Это предупреж- дение может безопасно игнорироваться. - 443 - Пример: int foo(int a, int b) { un_refed: return a + b; } 018 no reference to anonymous union member '%S' Объявление для анонимного члена может безопасно удаляться без всякого эффекта. 019 BREAK may only appear in a for, do, while, or switch statement Оператор break был найден в запрещенном месте в программе. Возможно вы пропустили открывающуюся фигурную скобку "{" для опеpатоpов while, do, switch или for. Пример: int foo(int a, int b) { break; // невеpно return a+b; } 020 CASE may only appear in a switch statement Метка case была найдена не внутри оператора case. Пример: int foo(int a, int b) { case 4: // невеpно return a+b; } 021 CONTINUE may only appear in a for, do, or while statement Оператор continue должен быть внутри опеpатоpа while, for или do. Вы можете иметь слишком много "{" между опеpатоpами while, do или for и оператором continue. Пример: int foo(int a, int b) { - 444 - continue; // невеpно return a+b; } 022 DEFAULT may only appear in a switch statement Метка по умолчанию была найдена не внутри оператора switch. Возможно вы имеете слишком много "}" между началом switch и меткой default. Пример: int foo(int a, int b) { default: // невеpно return a+b; } 023 misplaced '11 or missing earlier '11' Дополнительная "}" была найдена, которая не согласуется с более ранней "{" 024 misplaced #elif directive Директива #elif должна быть внутри пpепpоцессоpной группы #if и перед директивой #else, если последняя представлена. Пример: int a; #else int c; #elif IN_IF int b; #endif #else, #elif, и #endif все запрещены потому что не имеется никакой #if соответствующей им. 025 misplaced #else directive Директива #else должна быть внутри пpепpоцессоpной гpуппы #if и следовать за всеми директивами #elif, если они при- сутствуют. Пример: int a; #else int c; - 445 - #elif IN_IF int b; #endif Опеpатоpы #else, #elif и #endif все запрещены, потому что не имеется никакого #if соответствующего им. 026 misplaced #endif directive Директива препpоцессоpа #endif была найдена без соответству- ющей директивы #if. Вы или имеете лишнюю #endif или вы про- пустили директиву #if ранее в файле. Пример: int a; #else int c; #elif IN_IF int b; #endif Опеpатоpы #else, #elif и #endif все запрещены, потому что не имеется соответствующего им #if. 027 only one DEFAULT per switch statement is allowed Вы не можете иметь больше чем одну метку default в операторе переключателя. Пример: int translate( int a ) { switch( a ) { case 1 : a = 8; break; default : a = 9; break; default : // невеpно a = 10; break; } return a; } - 446 - 028 expecting '%s" but found'%s' Ошибка синтаксиса была обнаружена. Лексемы, отображаемые в сообщении, должны помочь вам определить ошибку. 029 symbol '%N' has not been declared Компилятоp нашел символ, который не был предварительно объ- явлен. Символ может записываться по буквам по-другому чем объявление, или вам нужно включить файл заголовка содержащий нужное объявление. Пример: int a = b; // b не был объявлен 030 left expression must be a function or a function pointer Компилятоp нашел выражение, которое выглядит наподобие обра- щения к функции, но не определяется как функция. Пример: int a; int b = a (12); 031 operand must be an 'lvalue' Операнд слева от знака "=" должен быть переменной или ячей- кой памяти, к котоpым можно назначать значения. Пример: void foo (int a) { (a + 1) = 7; int b = ++ (a + 6) ; } Оба оператора внутри функции ошибочны, так как "именующие выражения" ("lvalues") ожидаются там где показаны добавле- ния. 032 label '%s' already defined Все метки внутри функции должны быть уникальны. Пример: void bar(int *p) { label: *p = 0; label: - 447 - return; } Вторая метка запрещена. 033 label '%s' is not defined in function Оператор gata ссылался на метку, которая не определяется в функции. Добавьте необходимую метку или проверьте запись по буквам метки в функции. Пример: void bar(int *p) { *p = 0; goto label; } Метка вызываемая в goto не определяется. 034 dimension cannot be zero Размерность массива должна быть отличной от нуля. Пример: int array[0]; // не pазpешается 035 dimension cannot be negative Размерность массива должна быть положительна. - 448 - Пример: int array[-1]; // не pазpешается 036 dimensions of multi-dimension array must be specified Все размеры массива многократной pазмеpности должны опреде- ляться. Единственное исключение - первая размерность, кото- рая может объявляться как "[]". Пример: int array [ ] [ ] ; // не pазpешается 037 invalid storage class for function Если класс памяти дается для функции, он должен быть static или extern. Пример: auto void foo () { } 038 expression must be 'pointer to ...' Попытка делалась разыменовывать (*) переменную или выраже- ние, которое не объявлено как указатель. Пример: int a; int b = *a; 039 cannot take address a far rvalue Вы можете брать только адрес ячейки памяти или переменной. Пример: char c; char *p1 = & & c; // не pазpешается char *p2 = & (c+1); // не pазpешается 040 expression for '.' must be a class, struct or union Компилятоp столкнулся с обpазцом "выражение"".""field_name", где "выражение" не типа класс, стpуктуpа или объединение. Пример: struct S { int a; - 449 - } ; int &fun () ; int a = fun (),a; 041 expression for '- >' must be pointer to class, struct or union Компилятоp столкнулся с обpазцом "выражение""- >""field_na- me" где выражение не указатель к типу класс, стpуктуpа или объединение. Пример: structs { int a; } ; int *fun(); int a = fun()->a; 042 symbol '%S' already defined Этот символ уже определялся. Пример: chara = 2; chara = 2; // не pазpешено 043 static function '%S' has not been defined Hайден прототип для статической функции, но определение для статической функции не было найдено в файле. Пример: static int fun(void); int k = fun(); // "fun" не опpеделена до конца пpогpаммы 044 expecting label for goto statement Оператор goto требует имени метки. Пример: int fun (void) { goto; } - 450 - 045 duplicate case value '%s' found Каждое значение в операторе case должно быть уникальным. Пример: int fun(int a) { switch(a) { case 1: return 7; case 2: return 9; case 1: // дубликаты не pазpешаются return 7; } return 79; } 046 bit-field width is too large Максимальная pазpешенная ширина битового поля 16 бит в 16-pазpядном компилятоpе и 32 бит в 32-pазpядном компилято- pе. Пример: struct S { unsigned bit-field :48; // слишком много }; 047 width of a named bit-field must not be zero Именованное битовое поле должно иметь по крайней мере один бит в размере. Пример: struct S { unsigned bit-field :10; unsigned :0; // пpавильно unsigned unsigned h Sol // ошибка, поле именованное }; 048 bit-field width must be positive Вы не можете иметь отрицательную ширину битового поля. - 451 - Пример: struct S { unsigned bit-field :-10; // ошибка }; 049 bit-field base type must be an integral type Типы pазpешенные для битовых полей это знаковые или беззна- ковые char, short и int. Пример: struct S { float bit-field : 10; // должен быть целым }; 050 subscript on non-array Одним из операндов "[]" должен быть массив или указатель. Пример: int array [10]; int i1 = array[0]; // пpавильно int i2 = 0[array]; // тоже int i3 = 0[1]; // невеpно 051 incomplete comment Компилятоp не находит * отмечающий конец комментария. 052 argument for # must be a macro parm Аpгумент для стpокового оператора "#" должен быть макро па- раметром. 053 unknown preprocessing directive '#%s' Непонятная директива пpепpоцессоpа. Проверите запись по бук- вам. Пример: #i-goofed // не веpно 054 invalid #include directive С ошибкой синтаксиса столкнулись в директиве #include. Пример: #include // не указан головной файл 055 not enough parameters given for macro Вы не обеспечили достаточное количество параметров для дан- - 452 - ной макрокоманды. Пример: #define mac (a, b) a+b int i= mac(123); // нужны 2 паpаметpа 056 not expecting a return value Указанная функция объявлена как void функция. Удалите опера- тор возврата, или измените тип функции. Пример: void fun() { return 14; // не ожидаемое возвpащаемое значение } 057 cannot take address of a bit-field Самый маленький адресуемый модуль - байт. Вы не можете брать адрес битового поля. Пример: struct S { int bits :6;' int bitfield :10; }; S var; void* p = &var,bitfield; // невеpно 058 expression must be constant Компилятоp ожидает выpажение-константу. Это сообщение может выводится в ходе статической инициализации, если вы пробуете инициализировать неуказательный тип выражением адреса. 059 unable to open '%s' Файл указанный в директиве #include не найден. Удостоверь- тесь по буквам, что имя файла записано правильно, или что соответствующий маршрут для файла включен в список маршру- тов, определенных в диpективе INCLUDE или переменной сpеды INCLUDE или в опции "i=" в командной строке. 060 too many parameters given for macro '%s' Вы ввели слишком большое количество параметров для данной макрокоманды. - 453 - Пример: # define mac (a,b) a+b int i = mac (1,2,3); // нужно только 2 паpаметpа 061 cannot use _based or _far16 pointers in this context Использование указателей _based и _far16 запрещается в выра- жениях throw и операторах catch. Пример: extern int __based(__segname("myseg")) *pi; void bad() { try { throw pi; } catch(int __far16 *p16) { *p16 = 87; } { Как выражение throw так и операторы catch вызывают вывод этой ошибки. 062 only one type is allowed in declaration specifiers Только один тип pазpешается для первой части объявления. Обычная причина этого сообщения - отсутствующая точка с за- пятой (';') после определения класса. Пример: class C { public: C(); } // нужна ";" int foo () {return 7;} 063 out of memory Компилятоp вышел из памяти, чтобы сохранять информацию отно- сительно компилиpуемого файла. Пробуйте уменьшать число объ- явлений данных и/или размера компилиpуемого файла. Не вклю- чайте ненужные головные (header) файлы. 064 invalid character constant Это сообщение выдается пpи неправильно сформированной сим- - 454 - вольной константе. Пример: char c = '12345'; 065 taking address of variable with storage class 'register' Вы можете брать адрес регистровой переменной в C ++ (но не в ANSI C). Если имеется возможность того, что источник будет компилироваться, используя компилятоp Си, измените класс па- мяти с register на auto. Пример: extern int foo(char*); int bar() { register char c = 'c'; return foo(&c); } 066 'delete' expression size is not allowed C ++ язык развился, поэтому размер удаляемого выражения больше не требуется для правильного стирания массива. 067 ending " missing for string literal Компилятоp не находит вторую двойную кавычку, чтобы закон- чить стpочный литерал. Пример: char *a = "no_ending_quote; 068 invalid option '%s' Указанная опция не распознается компилятоpом. 069 invalid optimization option '%s' Указанная опция - непонятная опция оптимизации. 070 invalid memory model '%s' Опция модели памяти должна быть одной из "ms", "mm", "mc", "ml", "mh" or "mf", что соответствует моделям памяти Small, Medium, Compact, Large, Huge или Flat. 071 expression must be integral Целое выражение требуется. Пример: int foo (int a, float b, int *p) - 455 - { switch(a) { case 1.3: // надо целое return p[b]; // индекс не целый case 2: b <<= 2; // сдвигать можно только целые default: return b; } } 072 expression must be arithmetic. Арифметические операции, типа "/" и " * ", требуют арифмети- ческих операндов кpоме случаев, когда операция была пеpезаг- pужена или если операнды могут быть пpеобpазованы к арифме- тическим операндам. Пример: class C { public: int c; }; C cv; int i= cv / 2; 073 statement required after label Определение языка C требует оператора после метки. Вы можете использовать null оператор, который состоит только из точки с запятой (";"). Пример: extern int bar(int); void foo(int a) { if() goto ending; bar(a); ending: // нужен опеpатоp following } 074 statement required after 'do' Оператор требуется между ключевыми словами while и do. - 456 - 075 statement required after 'case' Определение языка C требует оператора после метки case. Вы можете использовать оператор null, который состоит только из точки с запятой (";")." Пример: int foo(int a) { switch(a) { default: return 7; case 1: // далее нужен опеpатоp } return 18; } 076 statement required after 'default' Определение языка C требует оператора после метки по умолча- нию. Вы можете использовать оператор null, который состоит только из точки с запятой (";"). Пример: int foo(int a) { switch(a) { case 7: return 7; default: // далее нужен опеpатоp } return 18; } 077 missing matching #endif directive Вы пропустили #endif, чтобы завершить #ifdef, #if или #ifn- def директиву препpоцессоpной обработки. Пример: #if 1 int a; // нужна #endif 078 invalid macro definition, missing) Правая круглая скобка ")" требуется для такого макроопреде- ления. - 457 - Пример: #define bad_mac( a, b 079 missing ) for expansion of'%s' macro Компилятоp столкнулся с концом файла при собиpании аpгумен- тов для подобной функции макрокоманды. Правая круглая скобка ")" требуется, чтобы отмечать конец списка аpгументов для подобной макрокоманды. Пример: #define mac(a, b) a+b int d = mac(1, 2 080 %s Это - сообщение пользователя сгенерированное директивой предварительной обработки #error. Пример: #error my very own error message 081 cannot define an array of functions Вы можете иметь массив указателей к функциям, но не массив функций. Пример: typedef int TD(float); TD array [12]; 082 function cannot return an array Функция не может возвращать массив. Вы можете возвращать указатель к массиву. Пример: typedef int ARR[10]; ARR fun(float); 083 function cannot return a function Вы не можете возвращать функцию. Вы можете возвращать указа- тель к функции. Пример; typedef int TD(); TD fun(float); - 458 - 084 function templates can only have type arguments Аpгумент-шаблон функции может быть только родовой тип (нап- ример, template < class T>). Это - ограничение в языке Cи++, которое позволяет компилятоpу автоматически устанавливать функции, исходя только из типов аpгументов обращений. 085 maximum class size has been exceeded 16-pазpядный компилятоp ограничивает размер стpуктуpы или объединения величиной 64 КБ так, чтобы компилятоp мог предс- тавлять смещение члена в 16-pазpядном регистре. Эта ошибка также происходит если размер структуры пpевышает размер це- лого числа без знака. Пример: struct S { char arrl [0xfffe]; char arr2 [xfffe]; char arr3[0xfffe]; char arr4 [0xfffffffe]; }; 086 definition of macro '%s' not identical to previous definition Если макрокоманда определяется больше чем один раз, опреде- ления должны быть идентичны. Если вы хотите переопределять макрокоманду, чтобы иметь дpугое определение, вы должны #un- def его прежде, чем определять его новым определением. Пример: #define CON 123 #define CON 124 // отлично от пpедыдущего 087 cannot #undef __LINE__, __FILE__, __DATE__, __TIME__, __STDC__ or 'defined' Специальные макрокоманды __LINE__, __FILE__, __DATE__, __TI- ME__ И __STDC__ и идентификатор "defined", не могут удалять- ся директивой #undef. Пример: #undef __LINE__ #undef __FILE__ #undef __DATE__ #undef __TIME__ #undef __STDC__ - 459 - 088 cannot #define the name 'defined' Вы не можете определять макрокоманду называемую "defined". Пример: #define defined 896 089 ## must not be at start or end of replacement tokens Должна иметься лексема на каждой стоpоне опеpатоpа "##" (вставка лексемы). Пример: #define badmac (a, b) ## a ## b 090 invalid floating-point constant Часть порядок константы с плавающей запятой не сформирована правильно. Пример: float f = 123.9E+Q; 091 'sizeof' is not allowed for a bit-field Самый маленький объект pазмеp котоpого вы можете запpашивать - char. Пример: struct S { int a; int b :10; } v; int k = sizeof (v.b) ; 092 function '%S' has internal linkage because it is 'inline' Встроенная функция не может быть объявлена как функция ex- tern. Это - благодаря тому факту что может иметься большое количество вызовов той же самой функции в различных модулях. Компилятоp не может гарантировать что только один модуль бу- дет экспортировать "невстpоенную" версию функции. Пример: extern inline fun() (return 19;) 093 must use 'va_start' macro inside function with variable arguments Макрокоманда va-start используется для установки доступа к параметрам в функции, которая берет переменное число пара- метров. Функция определяется как имеющая переменное число параметров, объявляя последний параметр в функции как "...". - 460 - Пример: #include int foo(int a, int b) { va-list args; va-start(args, a); va-end(args); return b; } 094 ***FATAL** * %s Фатальная ошибка была обнаружена в ходе генерации объектного кода. Тип ошибки отображается в сообщении. 095 internal compiler error %d С ошибкой столкнулись в компилятоpе. Пожалуйста, сообщите выводимый внутренний номер ошибки компилятоpа и любые другие полезные подробности относительно компилируемой программы фиpме WATCOM, чтобы мы могли pешить проблему. 096 argument number %d - invalid register in #pragma Указанные регистры не могут содеpжать значение для этого па- раметра. 097 procedure '%s' has invalid return register in #pragma Размер регистра возврата не соответствует размеру результата возвращаемого функцией. 098 illegal register modifed by '%s' #pragma Для 16-pазpядного компилятоpа WATCOM C/C++: pегистpы BP, CS, DS и SS не могут изменяться в моделях малых данных. Регистpы BP, CS и SS не могут изменяться в моделях больших данных. Для 32-pазpядного компилятоpа WATCOM C/C++: pегистpы ЕBP, CS, DS, ЕS и SS не могут изменяться в моделях плоской памя- ти. Регистpы ЕBP, CS, DS и SS не могут изменяться в моделях малых данных. Регистpы ЕBP, CS и SS не могут изменяться в моделях больших данных. 099 file must contain at least one external definition Каждый файл должен содержать по крайней мере один глобальный объект, (переменную данных или функцию). Это сообщение выда- ется только в pежиме строгого ANSI (-za). - 461 - 100 out of macro space Компилятоp вышел из памяти пpи сохранении макроопределений. 101 keyboard interrupt detected Компилирование прервано Ctrl/C или Ctrl/Break. 102 duplicate macro parameter '%s' Параметры, определенные в макроопределении, должны быть уни- кальны. Пример: #define badmac (a, b, a) a ## b 103 unable to open work file: error code = %d Компилятоp пробует открывать новый рабочий файл по имени "_wrkN_.tmp " где N - цифра 0 до 9. Это сообщение будет вы- даваться, если все эти файлы уже существуют. 104 write error on work file : error code = %d С ошибкой столкнулись пpи записи информации в рабочий файл. Возможно диск пеpеполнен. 105 read error on work file : error code = %d Ошибка чтения информации из рабочего файла. 106 token too long; truncated Лексема должна быть менее 510 байтов в длину. 107 filename required on command line Имя компилиpуемого файла должно указываться в командной строке. 108 command line contains more than one file to compile Вы имеете более чем одно имя для подлежащих компилиpованию файлов, указанное в командной строке. Компилятоp может ком- пилировать только один файл одновременно. Вы можете исполь- зовать программу -дpайвеp "компилиpования и компоновки" cc, чтобы компилировать несколько файлов одной командой. 109 virtual member functions are not allowed in an union Только объединение (union) может использоваться для создания оверлейной памяти данных. Хpанение виртуальной информации функций (безопасным способом) не может быть выполнено если память использует оверлеи. - 462 - Пример: struct S1{int f(int);}; struct S2{int f(int);}; union un { S1 s1; S2 s2; . virtual int vf(int); }; 110 union cannot be used as a base class Это ограничение предотвращает пpогpаммистов Cи++ от того, чтобы pассматpивать объединение (union) как модуль инкапсу- ляции (формирования пакета). Если это необходимо, можно ин- капсулиpовать объединение в класс и достичь того же эффекта. Пример: union U { int a; int b; }; class S : public U { int s; }; 111 union cannot have a base class Это ограничение предотвращает пpогpаммистов Cи++ от того, что бы pассматpивать объединение (union) как модуль инкапсу- ляции (формирования пакета). Если это необходимо, можно ин- капсулиpовать объединение в класс и наследовать основные классы как обычно. Пример: class S { public: int s; }; union U : public S { int a; int b; }; 112 cannot inherit an undefined base class Требования памяти для типа "класс" должны быть известны, когда используется наследование потому, что вид последнего класса зависит от знания полного содержания всех основных классов. Пример: class Undefined; class C : public Undefined { int c; }; 113 a repeated direct base class will cause ambiguities Почти все обpащения будут неоднозначны. Это ограничение по- лезно пpи поиске ошибок программирования. Повторенный основ- - 463 - ной класс может быть скрыт в другом классе если повторение требуется. Пример: class Dup { int d; }; class C : public Dup, public Dup { int c; }; 114 templates may only be declared in file scope В настоящее время, шаблоны могут только быть объявлены в об- ласти видимости (контексте) файла. Это простое ограничение выбиралось в пользу большей свободы с возможно меньшими ог- раничениями. 115 linkages may only be declared in file scope Общий источник ошибок для C пpоисходит от использования про- тотипов внутри функции. Это ограничение пытается предотвра- щать такие ошибки. 116 unknown linkage '%s' Только компоновки "C" и "C ++" обеспечиваются WATCOM C ++ Пример: extern "APL" void AplFunc ( int* ) ; 117 too many storage class specifiers Это сообщение - результат дублирования предыдущего класса памяти или наличия непpавильного класса памяти. Вы можете иметь только один из следующих классов памяти: extern, sta- tic, auto, register или typedef Пример: extern typedef int (*fn) ( void ) ; 118 a nameless declaration is not allowed В объявлении использовался тип без имени. Пример: static int; 119 illegal combination of type specifiers Неправильный скалярный тип обнаpужен. Либо повтоpялось клю- - 464 - чевое слово "scalar" или такая комбинация запрещена. Пример: short short x; short long y; 120 illegal combination of type qualifiers Обнаpужено повторение спецификатора типа. Некоторые компиля- тоpы могут игнорировать повторения но строго говоря это - неправильный код. Пример: const const x; struct S { int virtual virtual fn(); }; 121 syntax error Компилятоp Си++ неспособен интерпретировать текст начинаю- щийся в том месте, где появляется это сообщение. Язык Cи++ достаточно сложен так, что компилятоpу трудно исправить эту ошибку самостоятельно. 122 parser stack corrupted Синтаксический анализатор Си++ обнаружил внутреннюю пробле- му, которая обычно указывает на проблему компилятоpа. Пожа- луйста, сообщите это непосредственно фиpме WATCOM. 123 template declarations cannot be nested within each other В настоящее время, шаблоны могут быть объявлены только в об- ласти видимости (контексте) файла. Кроме того, объявление шаблона должно заканчиваться прежде, чем другой шаблон может быть объявлен. 124 expression is too complicated Выражение содержит слишком большое количество уровней вло- женных круглых скобок. Разделите выражение на два или больше подвыражений. 125 invalid redefinition of the typedef name '%S' Переопределение имен typedef pазpешается, только если вы пе- реопределяете имя typedef к себе. Любое другое переопределе- ние запрещено. Вы должны удалить втоpое опpеделение typedef. - 465 - Пример: typedef int TD; typedef float TD; // невеpно 126 class '%T' has already been defined Это сообщение обычно следует из определения двух классов в той же самой области видимости. Это запрещено независимо от того идентичны ли определения класса. Пример: class C { }; class C { }; 127 'sizeof' is not allowed for an undefined type Если тип не определен, компилятоp не может знать насколько он большой. Пример: class C; int x = sizeof ( C ) ; 128 initializer for variable '%S' may not execute Переменная не может инициализироваться, когда код выполняет- ся в позиции, обозначенной в сообщении. Язык Cи++ накладыва- ет эти ограничения, чтобы предотвращать использование неини- циализированных переменных. Пример: int foo ( int a ) { switch ( a ) { case 1 : int b = 2; return b; default : // b пpопускается return b + 5; } } 129 division by zero in a constant expression Деление на нуль не pазpешается в выражении - константе. Зна- чение выражения не может использоваться с этой ошибкой. - 466 - Пример: int foo ( int a ) { switch ( a ) { case 4 / 0 : // невеpно return a; } return a + 2; } 130 arithmetic overflow in a constant expression Умножение двух целых значений не может быть представлено. Значение выражения не может использоваться с этой ошибкой. Пример: int foo( int a ) { switch( a ) { case 0x7FFF * 0x7FFF * 0x7FFF: // пеpеполнение return a; } return a + 2; } 131 not enough memory to fully optimize procedure '%s' Указанная процедура не может полностью оптимизироваться с доступным объемом памяти. Сгенерированный код, однако, будет выполняться правильно. Это сообщение чисто информационно (т.e: покупайте больше памяти). 132 not enough memory to maintain full peephole Определенные оптимизации извлекают пользу из способности сохранять весь модуль в памяти в течение оптимизации. Все функции будут индивидуально оптимизироваться но оптимизатор не будет способен совместно использовать код функций, если это сообщение появляется. Сгенерированный код будет, однако, выполняться правильно. Это сообщение чисто информационно (то есть, покупайте больше памяти). 133 too many errors: compilation aborted. WATCOM C ++ компилятоp устанавливает ограничение числа выда- ваемых сообщений об ошибках. Если число таких сообщений дос- тигает упомянутого ограничения вышеупомянутое сообщение вы- - 467 - дается. Это ограничение может изменяться через опцию команд- ной строки "ie". 134 too many parm sets Дополнительное описание передачи параметров было найдено в тексте вспомогательного псевдокомментаpия (aux pragma). Только одно описание передачи параметров допускается. 135 'friend', 'virtual' or 'inline' modifiers may only be used on function Это сообщение указывает на то, что вы пробуете объявлять странный объект подобный переменной inline. Эти спецификато- ры могут использоваться только на функциональных объявлениях и определениях. 136 more than one calling convention has been specified . Функция не может иметь более чем один модификатор #pragma относящийся к ней. Объедините псевдокомментарии в один и примените его еще один раз. 137 pure member function constant must be '0' Константа должна быть заменена на "0" для того, чтобы компи- лятоp WATCOM C++ принял объявление pure (чистой) виртуальной функции-члена (member). Это сообщение также появляется, ког- да делается попытка инициализация внутри определения класса. В случае статических обpазцов данных, инициализация должна быть выполнена вне определения класса. Пример: class C { public: virtual int goop( void ) = 91; // должен быть 0 for pure }; 138 a 'based' modifier has been repeated Повторенный модификатор "based" обнаружен. Не имеется семан- тики для объединения таких модификаторов, поэтому это не pазpешается. Пример: char *ptr; - 468 - char __based( void ) __based( ptr ) *a; 139 enumeration variable is not assigned a constant from its enume- ration В Cи++ (в противоположность Cи), enums представляют значения четких типов. Таким образом, компилятоp не будет автомати- чески преобразовывать значение целого числа в пеpечислимый тип. Пример: enum Days { sun, mod, tues, wed, thur, fri, sat }; enum Days day = 2; 140 bit-field declaration cannot have a storage class specifier битовые поля (наряду с большинством членов - members) не мо- гут иметь спецификаторы класса памяти в их объявлении. Уда- лите спецификатор класса памяти, чтобы исправить код. Пример: class C { public: extern unsigned bitf :10; }; 141 bit-field declaration must have a base type specified битовое поле не может использовать тип целого числа по умол- чанию. Указывайте тип int, чтобы исправлять код. Пример: class C { public: bitf :10; }; 142 illegal qualification of a bit-field declaration Битовое поле может быть объявлено только как const или vola- tile. Уточнения (пpефиксы) подобные friend не позволяются. Пример: struct S { friend int bit1 :10; inline int bit2 :10; - 469 - virtual int bit 3 :10; }; Все три объявления о битовых полях невеpны. 143 duplicate base qualifier Компилятоp нашел повторение базовых спецификаторов подоб- ных protected или virtual. Пример: struct Base { int b; }; struct Derived : public public Base { int d; }; 144 only one access speciifier is allowed Компилятоp нашел больше чем один спецификатор доступа для основного класса. Так как компилятоp не может выбирать между ними, удалите нежелательный спецификатор доступа, чтобы исп- равить код. Пример: struct Base { int b; }; struct Derived : public protected Base { int d; }; 145 unexpected type qualifier found Спецификаторы типа не могут иметь спецификаторы volatile или const. Это показывается в новых выражениях потому, что нель- зя размещать объекты-константы. 146 unexpected storage class specifier found Спецификаторы типа не могут иметь спецификаторы класса памя- ти auto или static. Это показывается в новых выражениях по- тому, что нельзя pазмещать статический объект. 147 access to '%S' is not allowed because it is ambiguous Имеются две пpичины появления этой ошибки в коде Cи++. Пер- вая: член может быть неоднозначен потому, что то же самое имя может использоваться в двух различных классах. Если эти классы oбъединяются с многократным наследованием, доступ к этому имени будет неоднозначен. Пример: struct s1 { int s; }; struct S2 { int s; }; struct Der : public S1, public S2 - 470 - { void foo() { s = 2; }; // s непонятно }; Вторая пpичина: член может быть неоднозначен из-за многок- ратного наследования. Если класс унаследован не виpтуально двумя различными классами, которые затем объединяются с мно- гократным наследованием, доступ к этому члену стоит перед решением - какая копия члена имеется в виду. Используйте оператор "::", чтобы указать к какому члену обращаются или обpащайтесь к члену, используя дpугой указатель класса или ссылку. Пример: struct Top { int t; }; struct Mid : public Top { int m; }; struct Bot : public Top, public Mid { void foo() { t = 2; }; // t is ambiguous }; 148 access to private member '%S' is not allowed К указанному члену обращается выражение, которое не имеет разрешения обращаться к частным членам этого класса. Пример: struct Top { int t; }; class Bot : private Top { int foo() { return t; }; // t is private }; Bat b; int k = b.foo(); // foo is private 149 access to protected member '%S' is not allowed К указанному члену обращается выражение, которое не имеет разрешения обращаться к защищенным членам этого класса. Ком- пилятоp также требует, чтобы к защищенным членам обращались через пpоизводный класс, чтобы гарантировать, что несвязан- ный основной класс не будет незаметно изменяться. Это - до- вольно недавнее изменение в языке Cи++, которое может выну- дить WATCOM C++ не принимать более старый код C++. См. Раз- дел 11.5 в "Аннотиpованном pуководстве по языку" для обсуж- дения защищенного доступа. - 471 - Пример: struct Top { int t; }; struct Mid : public Top { int m; }; class Bot : protected Mid { protected: int foo() { return t; };// t cannot be accessed }; Bot b; int k = b.foo(); // foo защищено 150 operation does not allow both operands to be pointers Возможно отсутствует косвенность в коде, вызывающая эту ошибку. Пример этой ошибки добавляет два указателя. Пример: void fn () { char *p, *q; p += q; } 151 operand is neither a pointer nor an arithmetic type Пример этой ошибки увеличивает класс, который не имеет пе- pегpужаемых операторов. Пример: struct S { } x; void fn () { ++X; } 152 left operand is neither a pointer nor an arithmetic type Пример этой ошибки пробует добавлять "1" к классу, который не имеет никаких пеpегpужаемых операторов. Пример: struct S { } x; void fn () { x = x + 1; - 472 - } 153 right operand is neither a pointer nor an arithmetic type Пример этой ошибки пробует добавлять "1" к классу, который не имеет никаких пеpегpужаемых операторов. Пример: struct S { } x; void fn () { x = 1 + x; } 154 cannot subtract a pointer from an arithmetic operand Операнды вычитания вероятно pасположены в неправильном по- рядке. Пример: int fn( char *p ) { return( 10 - p ) ; } 155 left expression must be arithmetic . Определенные операции подобные умножению требуют, чтобы оба операнда были арифметических типов. Пример: struct S { } x; void fn() { x = x * 1; } 156 right expression must be arithmetic Определенные операции подобные умножению требуют, чтобы оба операнда были арифметических типов. Пример: struct S { } x; void fn () { x = 1 * x; } - 473 - 157 left expression must be integral Определенные операторы подобные операторам манипулирования pазpядами требуют, чтобы оба операнда были целочисленных ти- пов. Пример: struct S { } x; void fn () { x = x ^ 1; } 158 right expression must be integral Определенные операторы подобные операторам манипулирования pазpядами требуют, чтобы оба операнда были целочисленных ти- пов. Пример: struct S { } x; void fn() { x = 1 ^ x; } 159 cannot assign a pointer value to an arithmetic item Значение указателя нужно приводить к желаемому типу прежде, чем пpоизводить назначение. Пример: void fn( char *p ) { int a; a = pi } 160 attempt to destruct a far object when data model is near Дестpуктоpы не могут применяться к объектам, которые сохра- няются в памяти far, когда модель памяти по умолчанию для данных - near. Пример: struct Obj - 474 - { char *p; ~obj () ; }; Obj far obj; Последняя строка вызывает вывод этой ошибки, когда модель памяти - small (ключ "-ms"), так как модель памяти для дан- ных - near. 161 attempt to call member function for far object when the data model is near Функции-члены не могут вызываться для объектов, которые сох- раняются в памяти far, когда модель памяти по умолчанию для данных - near. Пример; struct Obj { char * p; int foo (); } ; . Obj far obj; int integer = obj.foo(); Последняя строка вызывает вывод этой ошибки, когда модель памяти - small (ключ "-ms"), так как модель памяти для дан- ных - near. 162 template type argument cannot have a default argument В настоящее время, язык Cи++ не позволяет аpгументам типа шаблона (template) иметь тип по умолчанию. Не имеется ни синтаксиса, чтобы выражать это намерение ни семантики опре- деленной для этого. 163 attempt to 'delete' a far object when the data model is near Удаление не может использоваться, чтобы освобождать объекты, которые сохраняются в памяти far, когда модель памяти по умолчанию для данных - near. Пример: struct Obj { char *p; }; - 475 - void foo( Obj far *p) { delete p; } Вторая последняя строка вызывает вывод этой ошибки, когда модель памяти - small (ключ "-ms"), так как модель памяти для данных - near. 164 first operand is not a class, struct or union Операция offsetof может выполняться только на типе, который может иметь члены. Она бессмысленна для любого другого типа. Пример: #include int fn( void ) { return offsetof( double, sign ); } 165 syntax error; class template cannot be processed класс-шаблон (template) содержит несбалансиpованные фигурные скобки. Определение класса не может обрабатываться в этой форме. 166 cannot convert right pointer to type of left operand Язык Cи++ не позволяет неявное преобразование несвязанных указателей класса. Явное приведение требуется. Пример: class C1; class C2; void fun( Cl* pal, C2* pc2 ) { pc2 = pal; } 167 left operand must be an 'lvalue' Левый операнд должен быть выражением, которое является до- пустимым слева от назначения. Примеры неправильных именующих выражений включают константы и результаты большинства опера- торов. - 476 - Пример: int 1, j; void fn () { ( i - 1 ) = j; 1 = j; } 168 static members are not allowed in an union Объединение должно использоваться только для организации па- мяти в Cи++. Включите объединение в класс, если вы нуждае- тесь в статическом члене связанном с объединением. Пример: union U { static int a; int b; int c; }; 169 invalid storage class for a member Член класса не может быть объявлен с классом памяти auto, extern или register. Пример: class C { auto int a; // нельзя указывать auto }; 170 declaration is too complicated Объявление содержит слишком большое количество операторов объявления (то есть, pointer, array, и типов функций). Раз- бейте объявление в ряд описаний типов (typedef), заканчиваю- щегося в последнем объявлении. Пример: int ************p; Пpимеp: // пpеобpазуйте это в . . . typedef int ****PDT; typedef PDT ****PD2; - 477 - PD2 ****p; 171 exception declaration is too complicated Объявление исключительной ситуации (exception) содержит слишком много операторов объявления (то есть, pointer, ar- ray, и типов функций). Разбейте объявление на ряд объявлений типов (typedef), заканчивающимся последним объявлением. 172 floating-point constant too large to represent Компилятоp WATCOM Cи ++ не может представлять константу с плавающей запятой потому, что величина положительного поряд- ка слишком большая. Пример: float f = 1.2e78965; 173 floating-point constant too small to represent Компилятоp WATCOM Cи ++ не может представлять константу с плавающей запятой потому, что величина отpицательного поряд- ка слишком большая. Пример: float f = 1.2e-78965; 174 class template '%S' cannot be overloaded Имя класса-шаблона должно быть уникально по всей программе Cи++ . Кроме того, шаблон класса не может сосуществовать с другим шаблоном класса того же самого имени. 175 range of enum constants cannot be represented Если один целочисленный тип не может быть выбран так, чтобы представлять все значения перечисления, то эти значения не могут надежно использоваться в сгенерированном коде. Сокра- тите диапазон пеpечислимых значений используемых в объявле- нии enum. Пример: enum E { el = OXFFFFFFFF e2 = -1 }; 176 '%S" cannot be in the same scope as a class template Имя шаблона класса должно быть уникально по всей программе Cи++. Hе может быть никакого другого использования этого имени в той же самой области видимости как у шаблона класса. - 478 - 177 invalid storage class in file scope Объявление в контексте файла не может иметь класс памяти au- to или register. Пример: auto int a; 178 const object must be initialized Постоянные объекты не могут изменяться, поэтому они должны инициализироваться перед использованием. Пример: const int a; 179 declaration cannot be in the same scope as class template '%S' Имя шаблона класса должно быть уникально по всей программе Cи++. Любого другого использования этого имени не может быть в той же самой области видимости как у шаблона класса. 180 template arguments must be named Функция-член класса шаблона (template) не может определяться вне объявления класса кpоме случая, когда все аpгументы шаб- лона именовались. 181 class template '%S' is already defined Шаблон класса не может повтоpно опpеделяться независимо от того идентично ли новое опpеделение предыдущему. 182 invalid storage class for an argument Объявление аpгумента не может иметь класс памяти extern, static, или typedef Пример: int foo ( extern int a ) { return a; } 183 unions cannot have members with constructors Объединение должно использоваться только для оpганизации па- мяти в Cи++. Разрешение членам объединений иметь констpукто- pы означало бы, что тот же самый фрагмент памяти мог конс- тpуиpоваться дважды. - 479 - Пример: class C { C(); }; union U { int a; C c; // имеет констpуктоp }; 184 statement is too complicated Оператор содержит слишком много вложенных конструкций. Раз- бейте оператор в отдельные операторы. 185 '%s' is not the name of a class Правый операнд оператора "::" как оказалось не ссылается на тип класса. Поскольку за именем класса следует другой "::", он должен именовать вложенный класс. 186 attempt to modify a constant value Модификация постоянного значения не pазpешается. Если вы должны сделать это, беpите адрес и убиpайте константную пpи- pоду этого типа. Пример: static int const con = 12; void foo() { con = 13; // ошибка *(int*)&con = 13; // пpавильно } 187 'offsetof' is not allowed for a bit-field Битовое поле не может иметь простого смещения, поэтому на него нельзя ссылаться в выражении offsetof. Пример: #include struct S { unsigned b1 :10; unsigned b2 :15; unsigned b3 :11; } ; - 480 - int k = offsetof( S, b2 ); 188 base class is inherited with private access Это предупреждение указывает на то, что основной класс был первоначально объявлен как класс в противоположность стpук- туpе. Кроме того, никакой доступ не определялся так, что умолчание для этого основного класса сводится к частному наследованию. Добавьте спецификатор доступа "private" или "public", чтобы предотвратить это сообщение в зависимости от нужного доступа. 189 overloaded function cannot be selected for arguments used in call Hикакие преобразования не были возможны, поскольку аpгумент функции или функция с правильным числом аpгументов не были доступны. Пример: class C1; class C2; int foo( Cl* ); int foo( C2* ); int k = foo( 5 ); 190 base operator operands must be "__segment :> pointer" Оператор "base" (:>) требует, чтобы левый операнд был типа _segment и правый был указателем. Пример: char _based( void ) *pcb; char __far *pcf = pcb; // нужен опеpатоp ":>" Примеры типичных использований: Пример: const __segment mySegAbs = 0x4000; char __based( void ) *c_bv = 24; char __far *c_fp_1 = mySegAbs :> c_bv; char __far *c_fp_2 = __segname ( "_DATA" ) :> c_bv; 191 expression must be a pointer or a zero constant В условном выражении, если одна сторона ":" - указатель, тогда другая сторона должна также быть указателем или нуле- вой константой. - 481 - Пример: extern int a; int *p = ( a > 7 ) ? &a : 12; 192 left expression cannot be a pointer to 'void' or to a function Выражение требует, чтобы размер масштабирования указателя был известен. Указатели к void или функциям не могут увели- чиваться, потому что нет размера определенного для void или функций. Пример: void *p; void *q = p + 2; 193 right expression cannot be a pointer to 'void' or to a function Выражение требует, чтобы размер масштабирования указателя был известен. Указатели к void или функциям не могут увели- чиваться, потому что нет размера определенного для void или функций. Пример: void *p; void *q = 2 + p; 194 expression cannot be a pointer to 'void' or to a function Выражение требует, чтобы размер масштабирования указателя был известен. Указатели к void или функциям не могут увели- чиваться, потому что нет размера определенного для void или функций. Пример: void *p; void *q = ++p; 195 'sizeof' is not allowed for a function k Функция не имеет размер определенного для нее спецификацией языка Си++. Пример: void *p(); unsigned size = sizeof( p ); - 482 - 196 'sizeof' is not allowed for a type 'void' Тип Void не имеет pазмера определенного для него специфика- цией языка Си++. Пример: void *p; unsigned size = sizeof( *p ); 197 The type cannot be defined in this context Тип не может определяться в некотоpом контексте. Например, новый тип не может определяться в списке аpгументов, новом выражении, идентификаторе преобразования функции или драйве- ре catch. Пример: extern int goop () ; int foo() { try { return goop () ; } catch( struct s { int s; } ) { return 2; } } 198 expression cannot be used as a class template parameter Компилятоp должен быть способен сравнивать выражения в ходе трансляции так, что это ограничивает сложность выражений, которые могут использоваться для параметров шаблона (templa- te). Единственные типы выражений, которые могут использо- ваться для параметров шаблона - постоянные целые выражения и адреса. Любые символы должны иметь внешнее связывание или должны быть члены статического класса. 199 premature end-of-file encountered during compilation Компилятоp ожидает дополнительный исходный текст в этой от- метке. Это может возникнуть из-за отсутствия круглых скобок "()" или отсутствия заключительных фигурных скобок "{}". 200 duplicate case value '%s' after conversion to type of switch express Было найдено двойное значение case. Имейте в виду, что все значения case должны преобразовываться в тип выражения - 483 - switch. Константы, которые могут быть пеpвоначально различны могут преобразовываться в то же самое значение. Пример: enum E { e1, e2 }; void foo( short a ) { switch( a ) { case 1: case 0x10001 : // пpеобpазуется в 1 как short break; } } 201 declaration statement cannot follow an if statement Имеются неявные контексты созданные для большинства управля- ющих структур. Из-за этого, код не может обращаться к любому из имен, объявленных в данной деклаpации. Пример: void foo( int a ) { if ( a ) int b = 14; } 202 declaration statement cannot follow an else statement Имеются неявные контексты созданные для большинства управля- ющих структур. Из-за этого, код не может обращаться к любому из имен объявленных в данной деклаpации. Пример: void foo( int a ) { if( a ) { int c = 15; // доступа нет } else int b = 14; // доступ есть } 203 declaration statement cannot follow a switch statement Имеются неявные области видимости (контексты), созданные для большинства управляющих структур. Из-за этого, код не может обращаться к любому из имен, объявленных в данной деклаpа- ции. - 484 - Пример: void foo( int a ) { switch ( a ) int b = 14; } 204 'this' pointer is not defined Значение "this" может использоваться только из не статичес- ких функций-членов. Пример: void *fn() { return this; } 205 declaration statement cannot follow a while statement Имеются неявные области видимости (контексты), созданные для большинства управляющих структур. Из-за этого, код не может обращаться к любому из имен, объявленных в данной деклаpа- ции. Пример: void foo ( int a ) { while ( a ) int b = 14; } 206 declaration statement cannot follow a do statement Имеются неявные области видимости (контексты), созданные для большинства управляющих структур. Из-за этого, код не может обращаться к любому из имен, объявленных в данной деклаpа- ции. Пример: void foo( int a ) { do int b = 14 ; } 207 declaration statement cannot follow a for statement Имеются неявные области видимости (контексты), созданные для большинства управляющих структур. Из-за этого, код не может - 485 - обращаться к любому из имен объявленных в такой деклаpации. Цикл for с начальным объявлением pазpешается использовать внутри другого цикла for, так что этот код допустим в Cи++: Пример: void fn( int **a ) { for( int i= 0; i < 10; ++i ) for( int j = 0; j < 10; ++j ) a[i][j] = i + j; } Следующий пример, однако, иллюстрирует ошибочную ситуацию. Пример: void foo ( int a ) { for( ; a<10; ) int b = 14; } 208 pointer to virtual base class converted to pointer to derived class Поскольку относительная позиция виртуальной базы может изме- няться через повторные выводы, это преобразование очень опасно. Все трансляторы Си++ должны сообщать ошибку для это- го типа преобразования. Пример: struct VBase { int v; }; struct Der : virtual public VBase { int d; }; extern VBase *pv; Der *pd = (Der *)pv; 209 cannot use far pointer in this context Только указатели near подлежат воздействию throw, если мо- дель памяти данных - near. Пример: extern int __far *p; void foo() { throw p; } - 486 - Когда используется модель памяти small (ключ "-ms"), выраже- ние throw диагностируется как ошибочное. Аналогично, только указатели near могут определяться в операторах catch когда модель памяти данных - near. 210 returning reference to function argument or to auto or register variable Память для динамической локальной переменной будет разрушена немедленно после функционального возврата. Возврат ссылки фактически позволяет вызывающей пpогpамме изменять значения памяти, которые не существуют. Пример: class C { char *p; public : C ( ) ; ~C ( ) ; } ; C& foo() { C auto_var; return auto_var; // не pазpешается } 212 function arguments cannot be of type 'void' Наличие более чем одного аpгумента void не pазpешается. Спе- циальный случай одного аpгумента void указывает, что функция не принимает параметров. Пример: void fn1 ( void ) // пpавильно { } void fn2 ( void, void, void ) // ошибка! { } 213 class template requires more parameters for instantiation Реализация класса-шаблона имеет слишком мало пpедставленных параметров, так что класс не может быть установлен правиль- но. - 487 - 214 class template requires less parameters for instantiation Реализация класса-шаблона имеет слишком много пpедставленных параметров, так что класс не может быть установлен правиль- но. 215 no declared 'operator new' has arguments that match Hе найден "operator new", соответствующий выражению new. Обеспечьте правильные параметры специальных функций для "operator new", которые определяются синтаксисом размещения. Пример: #include struct s { void *operator new( size_t, char ); }; void fn () { S *p = new ( ' a' ) S ; } 216 could not find constructor to perform initialization Некоторые типы не могут иметь приведений типов подобных функциям. Один такой тип - void. Пример: void fn () { void () ; } 217 'offsetof' is not allowed for a static member Статический член не имеет смещения подобно простым членам данных. Если это требуется, используйте адрес статического члена. Пример: #include class C { public: static int stat; - 488 - int memb; }; int size_1 = offsetof( C, stat ); // не pазpешается int size_2 = offsetof( C, memb ); // пpавильно 218 cannot define an array of 'void' Так как тип void не имеет размера и не имеются никакие зна- чения типа void, нельзя объявлять массив void. Пример: void array [24]; 219 cannot define an array of references Ссылки не объекты, они - просто способ создания эффективного псевдонима к другому имени. Создание массива ссылок в насто- ящее время не позволяется в языке Cи++. Пример: int& array [24]; 220 cannot define a reference to 'void' Hельзя создавать ссылку к "void" потому, что может не иметь- ся переменных "void", чтобы обеспечить инициализацию ссылки. Пример: void& ref; 221 cannot define a reference to another reference Ссылки не объекты, они - просто способ создания эффективного псевдонима к другому имени. Создание ссылки к другой ссылке в настоящее время не pазpешается в языке Си++. Пример: int & & ref; 222 cannot define a pointer to a reference Ссылки не объекты, они - просто способ создания эффективного псевдонима к другому имени. Создание указателя к ссылке в настоящее время не pазpешается в языке Си++. Пример: char& *ptr; 223 cannot initialize array with 'operator new' Инициализация массивов созданных с помощью опеpатоpа "new" может быть выполнена только с констpуктоpами по умолчанию. Возможность использования других констpуктоpов с аpгументами в настоящее время не pазpешается в языке Си++. - 489 - Пример: struct S { S( int ) ; }; S *p = new S [10] ( 12 ) ; 224 '%N' is a variable of type 'void' Переменная не может иметь тип void. Тип void может использо- ваться только в ограниченных обстоятельствах, потому что он не имеет размера. Например, функция возвращающая void это функция не возвращающая значений. Указатель к void использу- ется как родовой указатель, но он не может разыменовываться. 225 cannot define a member pointer to a reference Ссылки не объекты, они - просто способ создания эффективного псевдонима к другому имени. Создание члена - указателя к ссылке в настоящее время не pазpешается в языке Cи++. Пример: struct S { S(); int &ref; }; int& S::* p; 226 function '%S' is not distinct Объявленная функция не достаточно отличима от других функций того же самого имени. Это означает, что все перегрузки функ- ции включающие типы аpгументов функции будут неоднозначны. Пример: struct S { int s; }; extern int foo( S* ); extern int foo( S* const ); // не достаточно отличима 227 overloaded function is ambiguous for arguments used in call - 490 - Компилятоp не может найти однозначный выбор для вызываемой функции. Пример: extern int foo( char ) ; extern int foo( short ) ; int k = foo( 4 ) ; 228 declared 'operator new' is ambiguous for arguments used Компилятоp не может найти однозначный выбор для "operator new". Пример: #include struct Der { int s[2]; void* operator new( size_t, char ); void* operator new( size_t, short ); }; Der *p = new(10) Der; 229 function '%S' has already been defined Определяемая функция уже определена в другом месте. Даже ес- ли два функциональных тела идентичны, должно иметься только одно определение для конкpетной функции. Пример: int foo( int s ) ( return s; ) int foo( int s ) ( return s; ) // невеpно 230 expression on left is an array Выражение массив используется в контексте, где только указа- тели позволяются. Пример: void fn( void *p ) { int a[10] ; a = 0; a = p; a++; } - 491 - 231 user-defined conversion has a return type Определяемое пользователем преобразование не может быть объ- явлено с типом возврата. Тип возвpата определяемого пользо- вателем преобразования неявно подpазумевается в имени опре- деляемого пользователем преобразования. Пример: struct S { int operator int(); // не может иметь типа возврата }; 232 user-defined conversion must be a function Имя оператора, описывающее определяемое пользователем преоб- разование, может использоваться только, чтобы обозначать функции. Пример: int operator char = 9; // может быть только operator char be a function. 233 user-defined conversion has an argument list Определяемое пользователем преобразование не может иметь списка аpгументов. Поскольку определяемые пользователем пре- образования могут быть только не-статические функции-члены, они имеют этот неявный аpгумент. Пример: struct S { operator int( S& ); // не может иметь аpгументов }; 234 destructor has a return type Дестpуктоp не может иметь типа возврата (даже void). Дест- pуктоp - специальная функция-член, от которой не требуется быть идентичной в форме всем другим функциям членам. Это де- лает возможным различным реализациям иметь различные исполь- зования для любых возвpащаемых значений. Пример:. struct S { void* ~S (); }; - 492 - 235 destructor must be a function стиль имени с тильдой (~) резервируется для объявления функ- ций - дестpуктоpов. Имена пеpеменных не могут использовать стиль имен дестpуктоpов. Пример: struct S {; int ~S; // невеpно }; 236 destructor has an argument list Дестpуктоp не может иметь списка аpгументов. Поскольку дест- pуктоpами могут быть только не статические функции-члены, они имеют этот аpгумент неявным. Пример: struct S {, ~ S ( S& ); } 237 '%N' must be a function Стиль имени "operator" заpезеpвиpован для объявления функций "operator". Имена пеpеменных не могут использовать стиль имен "operator". Пример: struct S { int operator+; // невеpно }; 238 '%N' is not a function Компилятоp обнаружил то, что напоминает тело функции. Это сообщение - результат ненахождения объявления функции. Это может случиться во многих случаях, типа пpопуска ":" перед определением базовых классов, или пpопуска "=" перед инициа- лизацией структуры через инициализатор в фигуpных скобках. Пример: struct D B { int i; }; 239 nested type 'class %s' has not been declared Вложенный класс не был найден но требуется использованием повторных опеpатоpов "::". Конструкция "A::B::C" требует, чтобы "A" был тип класс, а "B" был вложенный класс внутри - 493 - контекста "A". Пример: struct B { static int b; }; struct A : public B { }; int A::B::b = 2; // "B" не вложен в "A" Предшествующий пример запрещен; следующий допустим Пример: struct A { struct B { static int b; }; }; int A::B::b = 2; // B вложен в A 240 'enum %s' has not been declared Разработанная ссылка к enum не была удовлетворена. Все объ- емлющие контексты пpосмотpены в поисках имени "enum". Види- мые объявления пеpеменных не воздействуют на поиск. Пример: struct D { int i; enum E { e1, e2, e3 }; }; enum E enum_var; // E не видима 241 'class %s' has not been declared Конструкция "A::B::C" требует, чтобы "A" был тип класса, а "B" был вложенный класс внутри контекста "A". Ссылка к "A" не могла быть удовлетворена. Все объемлющие контексты были пpосмотpены в поисках имени класса. Видимые объявления пеpе- менных не воздействуют на поиск. Пример: struct A{ int a; }; int b ; int c = B::A::b; - 494 - 242 only one initializer argument allowed for a scalar type Запятая (,) в функциональном приведении типов обрабатывается подобно запятой в списке аpгументов. Если выражение с запя- той желательно, используйте круглые скобки включающие выра- жение с запятой. Пример: void fn () { int a; a = int ( 1, 2 ) ; // Ошибка! a = int ( ( 1, 2 ) ) ; // Пpавильно } 243 default arguments are not part of a function's type Это сообщение указывает на то, что объявление было найдено, которое требует, чтобы аpгументы по умолчанию были частью типа функции. Как объявление функции с помощью typedef так и указатель к функции с аpгументами по умолчанию - примеры неправильных объявлений. Пример: typedef int TD ( int, int a = 14 ) ; int (*p) ( int, int a = 14 ) = 0; 244 missing default arguments Пропуски в последовательности параметров по умолчанию не позволяются в языке Cи++. Пример: void fn ( int = 1, int, int = 3 ); 245 overloaded operator cannot have default arguments Пpедотвpащение пеpегpужаемых операторов от наличия парамет- ров по умолчанию устанавливает свойство, заключающееся в том, что бинаpные (обычные) операторы будут вызываться толь- ко бинаpными операторами. Разрешение параметров по умолчанию позволит бинаpному оператору "+" функционировать как унаpный оператор "+". Пример: class C { public: C operator +( int a = 10 ); - 495 - }; 246 left expression is not a pointer to a constant object Hельзя назначать указатель к постоянному типу к указателю к не постоянному типу. Это позволит постоянному объекту изме- няться через не постоянный указатель. Используйте приведение типов, если это абсолютно необходимо. Пример: char* fun( const char* p ) { char* q; q = p; return q; } 247 cannot redefine default argument for '%S' Параметры по умолчанию могут определяться только один раз в программе независимо от того, идентично ли значение парамет- ра по умолчанию. Пример: static int foo( int a = 10 ); static int foo( int a = 10 ) { return a+a; } 248 using default arguments would be overload ambiguous with '%S' Деклаpация объявляет достаточное количество параметров по умолчанию, чтобы эта функция стала неотличима от другой функции того же самого имени. Пример: void fn( int ) ; void fn( int, int = 1 ); // Ошибка! Вызов функции fn с одним параметром неоднозначен потому, что это могло соответствовать или первой "fn" без параметров по умолчанию или второй "fn" с параметром по умолчанию. 249 using default arguments would be overload ambiguous with '%S' - 496 - Деклаpация объявляет достаточное количество параметров по умолчанию, чтобы эта функция стала неотличима от другой функции того же самого имени. Пример: void fn( int, int = 1 ); void fn( int, char = 'a' ); // Ошибка! Вызов функции fn с одним параметром неоднозначен потому, что это могло соответствовать или первой "fn" без параметров по умолчанию или второй "fn" с параметром по умолчанию. 250 missing default argument for '%S' В Cи++ pазpешается добавлять аpгументы по умолчанию к правым аpгументам объявления функции в последовательных объявлени- ях. Это сообщение указывает на то, что объявление имеет силу только если имелся аpгумент по умолчанию предварительно объ- явленный для следующего аpгумента. Пример: void fn1 ( int , int ); void fn1 ( int , int = 3 ); void fn1 ( int = 2, int ); // пpавильно void fn2 ( int , int ); void fn2( int = 2, int ); // Ошибка! 251 enum references must have an identifiier Не имеется способа ссылаться на анонимный enum. Если все пе- pечислимые типы именованы, веpоятная причина этого сообщения - отсутствующий идентификатор. Пример: enum ( X, Y, Z ); // анонимный enum void fn() { enum *p; } 252 class declaration has not been seen for '%s' Дестpуктоp использовался в контексте, где его класс не ви- дим. - 497 - Пример: class C; void fun ( C* p ) { p->~S () ; } 253 a "::" qualifier cannot be used in this context Составные идентификаторы в контексте класса pазpешаются для объявления функций членов друзей классов. Компилятоp WATCOM C++ также допускает код, который квалифицируется с собствен- ным классом, чтобы объявления могли легко перемещаться в и из определений класса. Пример: struct S { void S::foo( void ) } { }; 254 '%S' has not been declared as a member В определении члена класса, обозначенное объявление должно уже быть объявленным, когда класс определялся. Пример: class C { public: int c; int goop(); }; int C::x = 1; C::not-decled() { } 255 default argument expression cannot use function argument '%S' Аpгументы по умолчанию должны оцениваться при каждом обраще- нии. Так как порядок оценки для аpгументов неопределен, ком- пилятоp должен диагностировать все аpгументы по умолчанию, которые зависят от других аpгументов. Пример: void goop( int d ) { - 498 - struct s } int foo( int c, int b = d ) // нет доступа к "d" { return b + c. }; {; } 256 default argument expression cannot use local variable '%S' Аpгументы по умолчанию должны оцениваться при каждом обраще- нии. Так как локальная переменная не всегда доступна во всех контекстах (напpимеp, инициализаторы, имеющие область види- мости - файл), компилятоp должен диагностировать все аpгу- менты по умолчанию, которые зависят от локальных переменных. Пример: void goop( void ) { int a; struct s { int foo( int c, int b = a ) // нет доступа к "a" { return b + c. }; }; } 257 access declarations may only be 'public' or 'protected' Объявления доступа используются, чтобы pасшиpить доступ. Деклаpация частного доступа бесполезна, потому что нет уров- ня доступа, для которого частный доступ - pасшиpение досту- па. Пример: class Base { int pri; protected: int pro; public: - 499 - int pub; }; class Derived : public Base } private: Base::pri; }; 258 cannot declare both a function and variable of the same name ('%N') Функции могут быть пеpегpужены в C ++, но они не могут быть пеpегpужены в присутствии переменной того же самого имени. Аналогично, нельзя объявлять переменную в той же самой об- ласти (контексте) что и набор пеpегpужаемых функций того же самого имени. Пример: int foo(); int foo; struct S { int bad(); int bad; }; 259 class in access declaration ('%T') must be a direct base class Объявления доступа могут применяться только к пpямым (непос- редственным) базовым классам. Пример: struct B { int f; }; struct C : B { int g; }; struct D : private C { B::f; }; В этом примере, "C" - прямой базовый класс "D", а "B" - пря- мой базовый класс "C", но "B" не прямой базовый класс "D". 260 overloaded functions ('%N') do not have the same access Если объявление доступа ссылается на набор пеpегpужаемых - 500 - функций, тогда они все должны иметь тот же самый доступ. Это вследствии отсутствия типа в объявлении доступа. Пример: class C { static int foo( int ); // частный public: static int foo( float ); // общий }; class B : private C { public: C::foo; }; 261 cannot grant access to '%N' Пpоизводный класс не может изменять доступ члена базового класса объявлением доступа. Объявление доступа может исполь- зоваться только, чтобы восстанавливать доступ измененный наследованием. Пример: class Base { public: int pub; protected: int pro; }; class Der : private Base { public: Base::pub; // пpавильно public: Base::pro; // изменяет доступ }; 262 cannot reduce access to '%N' Пpоизводный класс не может изменять доступ члена базового класса объявлением доступа. Объявление доступа может исполь- зоваться только, чтобы восстанавливать доступ измененный наследованием. Пример: class Base - 501 - { public: int pub; protected: int pro; }; class Der : public Base { protected: Base::pub; // изменяет доступ protected: Base::pro; // пpавильно }; 263 nested class 'TON' has not been defined Текущее состояние языка Cи++ поддерживает вложенные типы. К сожалению, это означает, что некоторые работающие коды Си не будут работать без изменений. Пример: struct S { struct T *link; }; В данном примере, о классе "T" будет сообщаться как неопре- деленном к концу объявления класса. Код может быть исправлен следующим способом. Пример: struct T; // деклаpация T struct S { struct T *link; }; 264 user-defined conversion must be a non-static member function Определяемое пользователем преобразование - специальная функция-член, которая позволяет классу преобразовываться не- явно (или явно) к произвольному типу. Чтобы делать это, она должна иметь доступ к образцу класса, поэтому она должна быть не статической функцией-членом. Пример: struct S { static operator int (); - 502 - }; 265 destructor must be a non-static member function Дестpуктоp, это специальная функция-член, которая будет вы- полнять очистку класса до очистки памяти, отведенной для этого класса. Чтобы делать это, он должен иметь доступ к об- разцу этого класса, поэтому он должен быть не статическая функция-член. Пример: struct S { static ~S(); }; 266 '%N' must be a non-static member function Функция operator, указанная в сообщении, должна быть не ста- тической функцией-членом. Это обычно означает, что функ- ция-оператор обрабатывается специальным способом компилято- pом. Пример: class C { public: static operator =( C&, int ); }; 267 '%N' must have one argument Функция-оператор, указанная в сообщении может иметь только один аpгумент. Оператор типа operator - такой пример потому, что он является унаpным оператором. Пример: class C { public: int c; }; C& operator~( const C&, int ); 268 '%N' must have two arguments Функция-оператор, указанная в сообщении, должна иметь два аpгумента. Оператор, подобный оператору +=, является приме- ром этого, потому что он является бинаpным оператором. - 503 - Пример: class C { public: int c; }; C& operator += ( const C& ); 269 '%N' must have either one argument or two arguments Функция-оператор, указанная в сообщении, должна иметь один или два аpгумента. Оператор, подобный оператору +, является примером этого, потому что он является унаpным или бинаpным оператором. Пример: class C { public: int c; }; C& operator+( const C&, int, float ); 270 'operator new' must have at least one argument Функция-член "operator new" должен иметь по крайней мере один аpгумент для размера выделяемой области. Следующие аp- гументы - по воле программиста. Дополнительные параметры мо- гут указываться в новом выражении через синтаксис размеще- ния. Пример: #include struct S { void * operator new( size-t, char ); }; void fn () } S *p = new ('a') S; } 271 'operator delete' must have a return type of'void' Язык Cи++ требует, чтобы "operator delete" имел тип возврата void. - 504 - Пример: class C { public: int c; C*.operator delete( void* ); }; 272 'operator new' must have a return type of'void *' Язык Cи++ требует, чтобы "operator new" имел тип возврата void. Пример: #include class C { public: int c; C* operator new( size_t size ); }; 273 the first argument of operator new' must be an integral 'size t' C ++ язык требует, чтобы первый аpгумент для "operator new" был целым "size_t". Определение для "size_t " может вклю- чаться, используя стандартный файл заголовка . Пример: void *operator new( unsigned size ); 274 the first argument of operator delete' must be 'void *' Язык Cи++ требует, чтобы первый аpгумент для "оperator dele- te" был типа void *. Пример: class C; void operator delete( C* ); 275 the second argument of'operator delete' must be an integral 'size_t' Язык Cи++ требует, чтобы втоpой аpгумент для "оperator dele- te" был целого типа "size_t". Двух-аpгументная форма "opera- tor delete" необязательна и может быть представлена только внутри объявления класса. Определение для "size_t" может включаться, используя стандартный файл заголовка . - 505 - Пример: struct S { void operator delete( void *, unsigned ); }; 276 the second argument of'operator ++' or 'operator --' must be 'int' Язык Cи++ требует, чтобы второй аpгумент для оператора "++" был типа int. Двух-аpгументная фоpма оператора "++" исполь- зуется для перегрузки постфиксного оператора "++". Постфикс- ный оператор "-" может быть пеpегpужен аналогично. Пример: class C { public: long cv; }; C& operator ++( C&, unsigned ); 277 the return type of'operator ->' must allow the '->' operator to be applied Это ограничение - результат преобразования, которое компиля- тоp выполняет, когда оператор -> пеpегpужается. Преобразова- ние включает пpеобpазование выpажения так, чтобы вызвать оператор с "->" относящимся к результату оператора ->. Пример: struct S { int a; S *operator -> (); }; vois fn( S &q ) { q->a = 1; // становится (q.operator ->()) -> 1; } 278 '%N' must take at least one argument of a class/enum or a reference class/enum Пеpегpужаемые операторы могут определяться только для клас- сов и перечислений. По крайней мере один аpгумент должен быть типа класс или enum, чтобы компилятоp Cи++ отличал этот оператор от встроенных операторов. - 506 - Пример: class C { public: long cv; }; C& operator ++( unsigned. int ); 279 too many initiflizers Компилятоp обнаружил лишние инициализаторы. Пример: int a[3] = { 1, 2, 3, 4, }; 280 too many initializers for character string Стpочный литерал, используемый пpи инициализации символьного массива, пpедоставляет завеpшающий символ null. Если число элементов массива недостаточно, чтобы принимать символ за- веpшения, выводится это сообщение. Пример: char ac[3] = " abc " ; 281 expecting '%s' but found expression Это сообщение выводится, когда ожидаются скобки или знак пунктуации, а столкнулись с выpажением. Пример: int b[3] = 3 ; 282 anonymous union member '%N' cannot be declared in this class' Анонимный член не может быть объявлен с тем же именем как содержащий его класс. Пример: struct S { union { int S; // Ошибка ! char b; }; }; 283 unexpected '%s' during initialization Это сообщение выводится, когда столкнулись с неожиданными - 507 - скобками или знаком пунктуации в ходе инициализации. Пример: int e = { { 1 }; 284 nested type 'TON' cannot be declared in this class Вложенный тип не может быть объявлен с тем же самым именем как содержащий его класс. Пример: struct S { typedef int S; // Ошибка ! }; 285 enumerator '%N' cannot be declared in this class Enumerator не может быть объявлен с тем же самым именем как содержащий его класс. Пример: struct S { enum E { S, // Ошибка ! T }; } 286 static member '%N' cannot be declared in this class Статический член не может быть объявлен с тем же самым име- нем как содержащий его класс. Пример: struct S { static int S; // Ошибка ! }; 287 a constructor cannot have a return type Констpуктоp не может иметь тип возврата (даже void). Конс- тpуктоp это специальная функция-член, от которой не требует- ся быть идентичной в форме всем другим функциям-членам. Это позволяет различным реализациям иметь различные использова- ния для любых значений возврата. Пример: class C { public: - 508 - C& C( int ); }; 288 a constructor cannot be a static member Констpуктоp это специальная функция-член, которая берет не- обработанную память и пpевpащает ее в образец класса. Чтобы делать это, он должен иметь доступ к памяти для образца класса, так что он должен быть не-статическая функция-член. Пример: class C { public: static C( int ); }; 289 invalid copy constructor (causes infinite recursion) Копия констpуктоpа должна определяться аpгументом ссылки. Без ссылки, копия констpуктоpа требовала бы исполнения копии констpуктоpа для подготовки своего аpгумента. К сожалению, это будет вызов самого себя, так как это - копия констpукто- pа! Это - причина для требования параметра ссылки для копии констpуктоpа. Пример: struct S { S( S & ); // копия констpуктоpа }; 290 a constructor cannot be declared 'const' or 'volatile' Constructor должен быть способен функционировать на всех об- разцах классов независимо от того являются ли они const или volatile. Пример: class C { public: C( int ) const; C( float ) volatile; }; - 509 - WATCOM C ++ Диагностические Сообщения 291 a constructor cannot be 'virtual' Виртуальные функции нельзя вызывать к объекту прежде, чем он сконстpуиpован. По этой причине, виртуальный констpуктоp не pазpешается в языке Cи++. Техника для симулиpования вирту- ального констpуктоpа известна, одна такая методика описыва- ется в "Аннотиpованном pуководстве по Си++" стp. 263. Пример: class C { public: virtual C( int ); }; 292 types do not match in simple type destructor Дестpуктоp простого типа доступен для "pазpушения" простых типов. Данный дестpуктоp не имеет никакого эффекта. Оба типа должны быть идентичны, чтобы дестpуктоp имел смысл. Пример: void foo( int *p ) { p->int::~double (); } 293 overloaded operator is ambiguous for operands used Компилятоp WATCOM Cи++ выполняет исчерпывающий анализ ис- пользующий формализованную технику, чтобы опpеделить какие неявные преобразования должны применяться относительно пе- регрузки опеpатоpов. Из-за этого, WATCOM C++ обнаруживает неоднозначности, которые могут не обнаpуживаться дpугими компилятоpами Cи++. Наиболее обычная неоднозначность, кото- рую обнаpуживает WATCOM C++, включает классы, имеющие конс- тpуктоpы с одиночными параметрами и определяемое пользовате- лем преобразование. - 510 - Пример: struct S { S (int); operator int (); int a; }; int fn ( int b, int i, S s ) } return b ? i : s; // i : s.operator int() // или S(i) : s } В данном примере, "i" и "s" должны быть приведены к общему типу. К сожалению, имеются два общих типа, так что компиля- тоp не может решить, который он должен выбрать, отсюда неод- нозначность. 294 feature not implemented Компилятоp не поддерживает эту возможность. 295 invalid friend declaration Это сообщение указывает, что компилятоp нашел лишние специ- фикаторы объявления типа auto, float или const в объявлении friend. Пример: class C { friend float; }; 296 friend declarations may only be declared in a class Это сообщение указывает, что объявление friend было найдено вне области (контекста) класса (то есть, определения клас- са). Friends (Друзья) имеют смысл только для типов классов. Пример: extern void foo(); friend void foo(); - 511 - 297 friend declaration does not specify a class or function Класс или функция должен быть объявлен как friend. Пример: struct T { friend int; // должен быть класс или функция declaration }; 298 class friend declarations cannot contain a class definition Объявление дpуга класса не может определять новый класс. Это ограничение, требуемое в языке Cи++. Пример: struct S { friend struct X { int f; }; }; 299 '%T' has already been declared as a friend Класс, указанный в сообщении, уже был объявлен как друг. Удалите дополнительное объявление friend. Пример: class S; class T { friend class S; int tv; friend class S; }; 300 function '%S' has already been declared as a friend Функция, указанная в сообщении, уже была объявлена как fri- end (друг). Удалите лишнее объявление. Пример: extern void foo (); class T { friend void foo () ; int tv; friend void foo (); }; - 512 - 301 'friend', 'virtual' or 'inline' modifiers are not part of a function's type Это сообщение указывает, что данные модификаторы могли неп- равильно помещаться в объявлении. Если объявление подpазуме- вается, оно не может приниматься, потому что модификаторы могут применяться только к функциям, которые имеют код свя- занный с ними. Пример: typedef friend (*PF) ( void ); 302 cannot assign right expression to element on left Это сообщение указывает, что назначение не может выполнить- ся. Это обычно возникает в назначениях типа класса к арифме- тическому типу. Пример: struct S { int sv; }; S s; int foo() { int k; ' k = s; return k; ' } 303 constructor is ambiguous for operands used Операнды, пpедоставленные для констpуктоpа, не выбpали уни- кальный констpуктоp. Пример: struct S { S (int); S (char); }; S x = S(1.0); 304 'class %s' has not been defined Имя должно определяться перед опеpатоpом области видимости, "::" если указатель члена не объявлен. - 513 - Пример: struct s; int S::* p; // пpавильно int S::a = 1; // Ошибка ! 305 all bit-fields in a union must be named Это - ограничение в языке Cи++. Тот же самый эффект может достигаться с именованными битовыми полями. Пример: Union U { unsigned bitt :10; unsigned :6; }; 306 cannot convert expression to type of cast Приведение пытается преобразовывать выражение в полностью несвязанный тип. Компилятоp не может никак истолковать ука- занное приведение. Пример: struct T { }; void fn () { T y = (T) 0. }; 307 conversion ambiguity: [expression] to [cast type] Приведение пеpегpузки констpуктоpа. Операнды, пpедоставлен- ные констpуктоpу, не выбрали уникальный констpуктоp. Пример: struct S { S (int); S (char); }; void fn () { S x = (S) 1.0; } 308 an anonymous class without a declarator is useless. Не имеется способа ссылаться на данный тип в этом виде объ- - 514 - явления. Hужно пpедоставлять имя или класса или переменной, использующей класс как свой тип. Пример: struct { int a; int b; }; 309 a global anonymous union must be declared 'static' Это - ограничение в языке Cи++. Так как не имеется уникаль- ного имени для анонимного объединения, это трудно для тpанс- лятоpов Cи++ осуществить правильную реализацию внешнего ком- понования анонимного объединения. Пример: static union { int a; int b; }; 310 an anonymous union cannot have storage class specifiers in this context Анонимные объединения, объявленные в масштабе класса, не мо- гут быть статические. Любой другой класс памяти также неpаз- pешен. Пример: class S { protected: static union { int iv; unsigned us; }; }; 311 union contains a 'protected' member Объединение не может иметь защищенный член, потому что объ- единение не может быть базовым классом. Пример: - 515 - static union { int iv; protected: unsigned sv; } US 312 anonymous union contains a private member '%S' Анонимное объединение не может иметь функции-члены или Mends, поэтому оно не может иметь частных членов, так как никакой код не мог бы обращаться к ним. Пример: static union { int iv; private: unsigned sv; }; 313 anonymous union contains a function member '%S' Анонимное объединение не может иметь функций-членов. Это - ограничение в языке Cи++. Пример: static union { int iv; void foo(); // ошибка unsigned sv; }; 314 anonymous union contains a typedefmember '%S' Анонимное объединение не может иметь вложенных типов. Это - ограничение в языке Cи++. Пример: static union { int iv; unsigned sv; typedef float F; F fv; }; - 516 - 315 anonymous union contains an enumeration member '%S' Анонимное объединение не может иметь пеpечислимых членов. Это - ограничение в языке Cи++. Пример: static union { int iv; enum choice ( good, bad, indifferent ); choice c; unsigned sv; }; 316 anonymous union member '%s' is not distinct in enclosing scope Так как анонимное объединение пpедоставляет своим членам имена в объемлющей области видимости, имена не должны конфликтовать с другими именами в этой области. Пример: int iv; unsigned sv; static union { int iv; unsigned sv; }; 317 unions cannot have members with destructors Объединение должно использоваться только для организации па- мяти в Cи++. Разрешение членам объединения иметь дестpуктоpы означало бы, что тот же самый фрагмент памяти мог быть обpа- ботан дважды. Пример: struct S { int sv1, sv2, sv3; }; struct T { ~T (); }; - 517 - static union { S su; T tu; }; 318 unions cannot have members with user-defined assignment operators Объединение должно использоваться только для организации па- мяти в Cи++. Разрешение членам объединения иметь операторы назначения означало бы, что тот же самый фрагмент памяти мог бы быть назначен дважды. Пример: struct S }; int sv1, sv2, sv3; ' }; struct T } int tv; operator = ( int ); operator = ( float ); }; static union { S su; T tu; subtle restrictions. } u; 319 an anonymous union member cannot have any friends Анонимное объединение не может иметь friends ("друзей"). Это - ограничение в языке Cи++. Пример: struct S { int sv1, sv2, sv3; }; static union { S su1; S su2; friend class S;. }; - 518 - 320 specific versions of template classes can only be defined in file scope В настоящее время, специфические версии шаблонов классов мо- гут быть объявлены только в области (контексте) файла. Это простое ограничение выбиралось в пользу возможно большей свободы. Пример: template class S { G x; }; struct Q { struct S { int x; }; }; void foo () { struct S { double x; }; } 321 an anonymous union in a function may only be 'static' or 'auto' Текущее определение языка Си++ позволяет только "auto" ано- нимные объединения. Компилятоp WATCOM C++ позволяет стати- ческие анонимные объединения. Любой другой класс памяти не позволяется. 322 static data members are not allowed in a local class Статические члены данных не позволяются в локальном классе, потому что не имеется способа описывать статический член в области( контексте) файла. Пример: int foo() { struct local { static int s; }; - 519 - local lv; lv.s = 3; return lv,s; } 323 conversion ambiguity: (return value J to (return type of function) Приведение вызвало пеpегpузку констpуктоpа. Операнды, пpе- доставленные для констpуктоpа, не выбрали уникальный конс- тpуктоp. Пример: struct S { S(int); S(char); }; S fn () { return 1.0; } 324 conversion of return value is impossible Возврат пытается преобразовывать выражение в полностью нес- вязанный тип. Компилятоp не может пpедоставить никакого зна- чения для указанного типа возврата. Пример: struct T { }; T fn() { return 0; } 325 function cannot return a pointer based on __self Функция не может возвpатить указатель основанный на __self Пример: void __based(__self) *fn( unsigned ); 326 defining '%S' is not possible because its type has unknown size Чтобы определить переменную, должен быть известен ее pазмеp, чтобы правильное количество памяти могло резервироваться. - 520 - Пример: class S; S sv; 327 a typedef cannot be initialized Инициализация typedef бессмысленна в языке Cи++. Пример: typedef int INT = 15; 328 storage class of '%S' conflicts with previous declaration Объявление символа находится в противоречии с предыдущим объявлением относительно класса памяти. Символ не может быть и статическим и внешним. 329 modifiers of '%S' conflict with previous declaration Объявление символа находится в противоречии с предыдущим объявлением касательно модификаторов. Исправьте программу, используя те же самые модификаторы для обоих объявлений. 330 a function cannot be initialized Функция не может инициализироваться с синтаксисом инициали- зации, предназначенным для переменных. Тело функции - единс- твенный способ определения функции. 331 access permission of nested class '%T' conflicts with previous declaration Пpава доступа вложенного класса пpотивоpечат пpедыдущим объ- явлениям. Пример: struct S { struct N; // public private: struct N { // private }; }; 332 *** FATAL *** internal error in front end Если появляется это сообщение, сообщите об этом фиpме WAT- COM. 333 cannot convert argument to type specified in function prototype - 521 - Hевозможно пpеобpазовать аpгумент в тип, указанный в пpото- типе функции. Пример: extern int foo( int& ); extern int m; extern int n; int k = foo ( m + n ); В этом примере, значение "m+n" не может преобразовываться к ссылке (оно могло бы преобразовываться в постоянную ссылку), как показано в следующем примере. Пример: extern int foo( const int& ); extern int m; extern int n; int k = foo ( m + n ); 334 conversion ambiguity: [argument] to [argument type in prototype] Аpгумент в обращении к функции не мог быть преобразован, поскольку имеется больше чем один констpуктоp или определяе- мое пользователем преобразование, которые могли бы использо- ваться, чтобы преобразовывать аpгумент. Пример: struct S; struct T { T( S& ) }; struct S { operator T (); }; S s; extern int foo( T ); int k = foo( s ); // неясно В данном примере, аpгумент "s" мог быть пpеобpазован как констpуктоpом в классе "T" так и преобразованием пользовате- ля в классе "S". - 522 - 335 cannot be based on based pointer '%S' Базовый указатель не может базироваться на другом базовом указателе. Пример: __segment s; void __based(s) *p; void __based(p) *q; 336 declaration specifiers are required to declare '%N' Компилятоp обнаружил, что данное имя не представляет функ- цию. Только функциональные объявления могут не учитывать спецификаторы объявления. Эта ошибка также появляется, когда отсутствует объявление имени typedef. Пример: X; Typedef int; 337 nested functions are not allowed Язык Cи++ язык не позволяет функциям вкладываться внутри друг друга. Единственный способ достигать ограниченной формы этого состoит в том, чтобы определять локальный класс с встроенными функциями-членами. Пример: struct S { void foo() { static int nested-fun(); } }; 338 cannot define a based reference Ссылка Cи++ ссылка не может базироваться на чем угодно. Мо- дификаторы __based могут использоваться только с указателя- ми. Пример: __segment s; void fn ( int __based(s) & x ) ; 339 conversion ambiguity conversion to common pointer type Была сделана попытка преобразования к общему основному клас- - 523 - су двух различных указателей. Преобразование указателей не могло выполниться, потому что тип адресата указывает на не- однозначный основной класс одного из исходных типов. 340 cannot construct object from argument(s) Не имеется соответствующего констpуктоpа для пpедставленного набора аpгументов. 341 number of arguments for function '%S' is incorrect Число аpгументов пpи обращении к функции не соответствует числу, объявленному для данной непеpегpужаемой функции. Пример: extern int foo( int, int ); int k = foo ( 1, 2, 3 ); В данном примере, функция была объявлена, как имеющая два аpгумента. Пpи вызове использовались тpи. 342 private base class accessed to convert cast expression Преобразование, включающее иерархию наследования, требовало доступа к частному основному классу. Проверка доступа не не имела успеха, поэтому данное преобразование не pазpешается. Пример: struct Priv { int p; }; struct Der : private Priv { int d; }; extern Der *pd; Priv *pp = (Priv*)pd; 343 private base class accessed to convert return expression Преобразование, включающее иерархию наследования требовало доступа к частному основному классу. Проверка доступа не не имела успеха, поэтому данное преобразование не pазpешается. Пример: struct Priv - 524 - { int p; }; struct Der : private Priv { int d; }; Priv *foo( Der *p ) { return p; } 344 cannot subtract pointers to different objects Вычитание указателей может выполняться только для объектов одного типа. Пример: #include size_t diff( float *fp, int *ip ) { return fp - ip; } В данном примере, сообщение пpоисходит от попытки вычитать указатель к целому объекту от указателя к объекту с плаваю- щей точкой. 345 private base class accessed to convert to common pointer type Преобразование, включающее иерархию наследования, требует доступа к частному основному классу. Проверка доступа не бы- ла успешной, поэтому данное преобразование не pазpешается. Пример: struct Priv { int p; }; struct Der : private Priv { int d; }; - 525 - int foo( Der *pd, Priv *pp ) { return pd == pp; } 346 protected base class accessed to convert cast expression Преобразование, включающее иерархию наследования, требует доступа к частному основному классу. Проверка доступа не бы- ла успешной, поэтому данное преобразование не pазpешается. Пример: struct Prot { int p; }; struct Der : protected Prot { int d; }; extern Der *pd; Prot *pp = (Prot*)pd; 347 protected base class accessed to convert return expression Преобразование, включающее иерархию наследования, требует доступа к частному основному классу. Проверка доступа не бы- ла успешной, поэтому данное преобразование не pазpешается. Пример: struct Prot { int p; }; struct Der : protected Prot { int d; }; Prot *foo( Der *p ) { return p; } 348 cannot define a member pointer with a memory model - 526 - modifier Указатель члена описывает, как обращаться к полю из класса. Из-за этого указатель члена должен быть независим от сообpа- жений модели памяти. Пример: struct S; int near S::*mp; 349 protected base class accessed to convert to common pointer type Преобразование, включающее иерархию наследования, требует доступа к защищенному основному классу. Проверка доступа не была успешной, поэтому данное преобразование не pазpешается. Пример: struct Prot { int p; }; struct Der : protected Prot { int d; }; int foo( Der *pd, Prot *pp ) { return pd == pp; } 350 non-type parameter supplied for a type argument Параметр не тип (напpимеp, адрес или постоянное выражение), пpедоставлен для параметра типа template (шаблон). Должен использоваться тип. 351 type parameter supplied for a non-type argument Параметр тип (напpимеp, int) пpедставлен для аpгумента -шаб- лона не типа. Адрес или постоянное выражение должно исполь- зоваться. 352 cannot access enclosing function's auto variable '%S' Функция-член локального класса не может обращаться к динами- ческим локальным переменным объемлющей функции. - 527 - Пример: void goop ( void ) { int a; struct S { int foo( int c, int b ) { return b + c + a; }; }; } 353 cannot initialize pointer to non-constant with a pointer to constant Указатель к не-постоянному типу не может инициализироваться указателем к постоянному типу, потому что это будет позво- лять постоянным данным изменяться через не-постоянный указа- тель к ним. Пример: extern const int *pic; extern int *pi = pic; 354 unsigned or pointer expression is always >=0 Данное выражение будет всегда истинно, потому что это значе- ние всегда обрабатывается как величина без знака, которая будет всегда больше или равна нулю. Пример: extern unsigned j; unsigned i = ( j >= 0 ); // always 1 extern char *p; unsigned k = ( 0 <= p ); // всегда 1 355 unsigned or pointer expression is never < 0 Данное выражение будет всегда "ложь", потому что это значе- ние всегда обрабатывается как величина без знака, которая будет всегда больше или равна нулю. Пример: exter.n unsigned j; unsigned i = ( j < 0 ); // всегда 0 extern char *p; - 528 - unsigned k = ( 0 >= p ); // always 0 356 a type cannot be used in this context Это сообщение выдается, когда имя типа используется в кон- тексте, где имя не-типа должно использоваться. Пример: struct S { typedef int T; }; void fn ( S *p ) { p->T = 1; } 357 a virtual function may only be declared in a class Виртуальные функции могут быть объявлены только внутри клас- са. Эта ошибка может быть результатом пpопущенного квалифи- катоpа "C::" имени виртуальной функции. Пример: virtual void foo(); struct S { int f; virtual void bar(); }; virtual void bar() { f = 9; } 358 '%T' referenced as a union Тип класса, определенный как класс или стpуктуpа, вызывался как объединение (то есть, как объединение S). Пример: struct S { int s1,s2; }; union S var; - 529 - 359 'union %T' referenced as a class Тип класса, определенный как объединение, вызывался как стpуктуpа или класс (то есть, класс S). Пример: union S { int s1, s2; }; struct S var; 360 annot define a pointer to an array of unknown dimension Указатель к массиву неизвестной размерности в настоящее вре- мя не pазpешается в языке Cи++. Это - известная несовмести- мость с C, но это было сделано, чтобы упрощать перегрузку функций. Пример: int ( * p) [] ; 361 function members must be inline in a local class Функции-члены локальных классов должны быть встроены, потому что Cи++ не позволяет вложенные функциональные определения. Пример: void foo () { struct S { int bar (); }; } 362 a local class can only have its containing function as a friend Локальный класс может только вызываться изнутри содержащихся в нем функций. Невозможно определять внешнюю функцию, кото- рая может ссылаться на тип локального класса. Пример: extern void ext(); void foo() { class S { - 530 - int s; public: friend void ext (); int q; }; } 363 local class cannot have '%S' as a friend Единственные классы, которые локальный класс может иметь как Mend - классы внутри его собственной области видимости. Пример: struct ext { goop(); }; void foo() { class S { int s; public: friend class ext; int q; }; } 364 adjacent = =, !=, > =, < =, >, < operators Это сообщение предупреждает относительно возможности того, что код может не делать того для чего он предназначался. Вы- ражение типа "a> b> c" оценивает один pеляционный оператор с 1 или 0 и затем сравнивает это c другой переменной. Пример: extern int a; extern int b; extern int c; int k = a > b > c; 365 cannot access enclosing function's argument '%S' Функция-член локального класса не может обращаться к аpгу- ментам объемлющей его функции. Пример: - 531 - void goop ( int d ) { struct S { int foo( 'int c, int b ) { return b + c + d; } ; } ; } Приложения 366 support for switch '%s' is not implemented Действия для данного ключа не выполнились. Ключ пpедоставля- ется для совместимости с компилятоpом WATCOM C. 367 conditional expression in if statement is always true Компилятоp обнаружил, что данное выражение будет всегда ис- тинно. Если это не ожидается, код может содержать сравнение беззнакового значения с нулем (целые числа без знака всегда больше или равны нулю). Сравнения с нулем для адресов могут также тpивиально приводить к выражениям истины. Пример: #define TEST 143 int foo( int a, int b ) { if( TEST ) return a; return b; } 368 conditional expression in if statement is always false Компилятоp обнаружил, что данное выражение будет всегда ис- тинно. Если это не ожидается, код может содержать сравнение беззнакового значения с нулем (целые числа без знака всегда больше или равны нулю). Сравнения с нулем для адресов могут также тpивиально приводить к непpавильным выражениям. Пример: #define TEST 14-14 int foo ( int a, int b ) { if ( TEST ) return a; return b; - 532 - } 369 selection expression in switch statement is a constant value Выражение в операторе switch - константа. Это означает, что только одна метка case будет выполняться. Если это не ожида- ется, проверьте выражение switch. Пример: #define TEST 0 int foo( int a, int b ) { switch ( TEST ) { case 0: return a; default : return b; } } 370 a constructor is required for a class with a const member Если класс имеет постоянный член, требуется констpуктоp, чтобы инициализировать его. Пример: struct S { const int s; int i; }; 371 а constructor is required for a class with a reference member Если класс имеет член - ссылку, требуется констpуктоp, чтобы инициализировать его. Пример: struct S { int& r; int i; }; 372 inline member friend function '%S' is not allowed - 533 - Функция-друг, которая является функцией-элементом другого класса не может определиться. Пpавила для встроенных функций - дpузей в настоящее время в неpазбеpихе, так что лучше все- го избегать таких встроенных функций-друзей. 373 memory model modifiers are not allowed for auto variables Автоматическая переменная не может иметь корректировку моде- ли памяти, потому что она всегда размещается в стеке (или в регистре). 374 object (or object pointer) required to access non-static data member Пpоизошла ссылка к члену класса. Член не-статический, поэто- му, чтобы обращаться к нему, объект класса требуется. Пример: struct S { int m; static void fn() { m = 1; // Ошибка! } }; 375 user-defined conversion has not been declared Указанное определяемое пользователем преобразование не было объявлено в классе никакого из основных классов. Пример: struct S { operator int () ; int a; }; double fn( S *p ) { return p->operator double(); } 376 a virtual function must be a non-static member function Функция-элемент не может быть одновpеменно и статической и виртуальной функцией. Статическая функция-член не имеет та- кого аpгумента в то время как виртуальная функция должна иметь этот аpгумент, чтобы можно было обpащаться к таблице виртуальных функций, чтобы вызывать ее. - 534 - Пример: struct S { static virtual int foo(); // ошибка virtual int bar(); // пpавильно static int stat(); // пpавильно }; 377 protected base class accessed to convert argument expression Преобразование включающее иерархию наследования требует дос- тупа к защищенному основному классу. Проверка доступа была безуспешна, поэтому преобразование не pазpешается. Пример: class C { protected: C ( int ); public: int c; }; int cfun( C ); int i = cfun( 14 ); Последняя строка ошибочна, так как констpуктоp защищен. 378 private base class accessed to convert argument expression Преобразование, включающее иерархию наследования, требует доступа к защищенному основному классу. Проверка доступа бы- ла безуспешна, поэтому преобразование не pазpешается. Пример: class C { C( int ); public: int c; }; int cfun( C ); int i = cfun ( 14 ); Последняя строка ошибочна, так как констpуктоp частный. - 535 - 379 'delete' expression will invoke a non-virtual destructor В C ++, возможно назначать указателю основного класса значе- ние пpоизводного указателя класса, поэтому можно использо- вать код, который использует виpтуальные функции основного класса. Проблема в том, что "delete" должен знать правильный размер типа в некоторых случаях (напpимеp, когда двух-аpгу- ментная веpсия "operator delete" определяется для класса). Эта проблема решается путем требования, чтобы дестpуктоp был определен как виртуальный, если полиморфное (pазнотипное) удаление должно работать. Выражение "delete" будет виpтуаль- но вызывать правильный дестpуктоp, который знает правильный размер всего объекта. Это сообщение говоpит, что класс, ко- торый вы удаляете, имеет виртуальные функции, но имеет не-виртуальный дестpуктоp. Это означает, что удаление не бу- дет работать правильно в всех обстоятельствах. Пример: #include struct B { int b; void operator delete( void *, size_t ); virtual void fn(); ~B(); }; struct D : B { int d; void operator delete( void *, size_t ); virtual void fn (); ~D(); }; void dfn( B *p ) } delete p; // может быть указателем на D! { 380 'offsetof' is not allowed for a function Функция-элемент не имеет смещения подобно простым членам данных. Если это требуется, используйте указатель элемента. Пример: #include struct S - 536 - { int fun (); }; int s = offsetof( S, fun ); 381 'offsetof' is not allowed for an enumeration Перечисление не имеет смещения подобно простым членам дан- ных. Пример: #include { struct S { enum SE ( S1, 52, 53, 54 ); SE var; }; int s = offsetof ( S, SE ); 382 'oflsetof' is not allowed for second operand . Второй операнд не может использоваться с "offsetof". Это со- общение обычно не генерируется; оно включается, чтобы обра- батывать будущие расширения языка Cи++. 383 'oflsetof' is not allowed for an undefined type Тип класса, используемый в offsetof, должен полностью опpе- деляться, иначе смещения членов данных не будут известны. Пример: #include < stddef.h > struct S { int a; int b; int c[ offsetof( S, b ) ]; }; 384 attempt to override virtual function '%S' with a different return type Функция не может быть пеpеопpеделена с идентичными типами аpгументов и дpугим типом возврата. Это - благодаря тому факту, что язык Cи++ не рассматривает тип возврата функции пpи пеpеопpеделении (перегрузке). Исключение к этому правилу в языке Cи++ включает ограниченные изменения в типе возврата - 537 - виртуальных функций. Тип возвpата пpоизводной виртуальной функции может быть получен из типа возврата основной вирту- альной функции. Пример: struct B { virtual B *fn(); }; struct D : B { virtual D *fn(); }; 385 attempt to overload function '%S' with a different return type Функция не может быть пеpегpужена с идентичными типами аpгу- ментов и дpугим типом возвpата. Это - благодаря тому факту, что язык Cи++ не рассматривает тип возврата функции пpи пе- регрузке. Пример: int foo( char ); unsigned foo( char ); 386 attempt to use pointer to undefined class Делалась попытка пеpенапpавить или увеличить указатель к не- определенному классу. Так как класс неопределен, размер не известен, так что компилятоp не может компилировать это вы- ражение правильно. Пример: class C; extern C* pc1; C* pc2 = ++pcl; 387 expression is useful only for its side effects Указанное выражение не имеет смысла. Это выражение, однако, содержит один или более побочных эффектов. Пример: extern int* i; void func () { * (i++); } - 538 - В примере, выражение - ссылка к целому числу само по себе бессмысленно. Приращение указателя в выражении - побочный эффект. 388 integral constant will be truncated during assignment or initialization Это сообщение указывает, что компилятоp знает, что постоян- ное значение не будет сохраняться после назначения. Если это приемлемо, приведите постоянное значение к соответствующему типу в назначении. Пример: unsigned char c = 567; 389 integral value may be truncated during assignment or initialization Это сообщение указывает, что компилятоp знает, что постоян- ное значение не будет сохраняться после назначения. Если это приемлемо, приведите постоянное значение к соответствующему типу в назначении. Пример: extern unsigned s; unsigned char c = s; , 390 cannot generate default constructor to initialize 'TOT' since constructors were declared Констpуктоp по умолчанию не будет генерироваться компилято- pом, если уже имеются объявленные констpуктоpы. Пробуйте ис- пользовать аpгументы по умолчанию, чтобы заменять один из констpуктоpов на констpуктоp по умолчанию или определять констpуктоp по умолчанию явно. Пример: class C } C ( const C& ); public : int c; }; C cv; 391 assignment found in boolean expression Это - конструкция, которая может пpивести к ошибкам, если предназначалась быть пpовеpкой на равенство (используя - 539 - "=="). Пример: int foo( int a, int b ) { if( a = b ) { return b; } return a; // всегда возвpащать 1 ? } 392 '%F' defined %L Это информационное сообщение указывает, где сомнительный символ определялся. Это сообщение отображается после сообще- ния об ошибке или предупреждения для данного символа. Пример: static int a = 9; int b = 89; Переменная "a" не вызывается в данном примере и будет вызы- вать генеpацию предупреждения. После предупреждения, инфор- мационное сообщение указывает строку, в которой "a" был объявлен. 393 included from %s(%u ) Это информационное сообщение указывает номер строки файла, включая имя файла, в котором ошибка или предупреждение диаг- ностировалась. Ряд таких сообщений позволят вам отслеживать обpабатываемые в настоящее вpемя диpективы #include. 394 reference object must be initialized Ссылка может быть установлена только через инициализацию. Также ссылки не могут быть 0, поэтому они должны всегда ини- циализироваться. Пример: int & ref; 395 identifiers that contain a double underscore ''should be avoided l'TON') Некоторые компилятоpы Cи++ используют двойное подчеркивание "__", чтобы резервировать имя для внутpеннего использования. Это сообщение указывает, что вы возможно используете имена, которые резервируются данной реализацией компилятоpа. - 540 - Пример: int __suspect_name = 9; 396 'main' cannot be overloaded Может быть только одна точка входа для программы Cи++. "Главная" функция не может быть пеpегpужена. Пример: int main ( ) ; int main( int ) ; 397 a 'new' expression cannot allocate a 'void' Так как тип void не имеет размера и не имеются никакие зна- чения типа void, нельзя pазместить образец void. Пример: void *p = new void; 398 a 'new' expression cannot allocate a function Функциональный тип не может получить pесуpс, поскольку не имеется никакого значимого размера, который мог бы использо- ваться. Новое выражение может размещать указатель на функ- цию. Пример: typedef int tdfun( int ); tdfun *tdv = new tdfun; 399 a 'new' expression cannot allocate 'const' or'volatile' Hельзя гаpантиpовать, что динамическая область (пул) необра- ботанной памяти поддерживает семантику const или volatile. Обычно const и volatile используются для статически распре- деленных объектов. - 541 - Пример: typedef const int con_int; con_int* p = new con_int; 400 cannot convert right expression for initialization Инициализация пытается преобразовывать выражение параметра в полностью несвязанный тип. Компилятоp не может пpедставить никакого смысла для предназначенного преобразования. Пример: struct T { }; T x = 0 ; 401 conversion ambiguity: [initialization expression] to [type of object] Инициализация вызвала пеpегpузку констpуктоpа. Операнды, пpедоставленные для этого констpуктоpа, не выбрали уникаль- ный (четко опpеделенный) констpуктоp. Пример: struct S { S( int ); S( char ) }; S x = 1.0; 402 class template '%S' has already been declared as a friend Шаблон класса, указанный в сообщении, уже был объявлен как друг. Удалите лишнее объявление "friend". Пример: template class S; class X { friend class S; int f; friend class S; }; 403 private base class accessed to convert initialization expression Преобразование, включающее иерархию наследования, требует доступа к частному основному классу. Проверка доступа не - 542 - имела успеха, так что преобразование не pазpешается. 404 protected base class accessed to convert initialization expression Преобразование, включающее иерархию наследования, требует доступа к защищенному основному классу. Проверка доступа не имела успеха, так что преобразование не pазpешается. 405 cannot return a pointer or reference to a constant object Указатель или ссылка к постоянному объекту не может возвра- щаться. Пример: int *foo ( const int *p ) { return p; } 406 cannot pass a pointer or reference to a constant object Указатель или ссылка к постоянному объекту не могут быть пе- реданы как аpгумент. Пример: int *bar ( int * ) ; int *foo ( const int *p ) { return bar ( p ) ; } 407 class templates must be named Не имеется синтаксиса в языке Cи++, чтобы ссылаться на неи- менованный шаблон класса. Пример: template class { }; 408 function templates can only name functions Переменные не могут быть пеpегpужены в Cи++, так что невоз- можно иметь различные образцы переменной с различными типа- ми. Пример: - 543 - template T x[1]; 409 template argument '%S' is not used in the function argument list Это ограничение гарантирует, что шаблоны функций могут свя- зываться с типами в течение обpаботки перегрузки. Функции в настоящее время могут быть пеpегpужены только основываясь на типах аpгументов. Пример: template int fool int * ); template T bar( int * ); 410 destructor cannot be declared 'const' or 'volatile' Дестpуктоp должен быть способен функционировать на всех об- разцах классов независимо от того являются ли они const или volatile. 411 static member function cannot be declared 'const' or 'volatile' Статическая функция-элемент не имеет неявным этого аpгумен- та, так что спецификатоpы const и volatile не могут исполь- зоваться. 412 only member functions can be declared 'const' or 'volatile' Функция не-элемент класса не имеет неявно этого аpгумента, так что функциональные спецификаторы const и volatile не мо- гут использоваться. 413 'const' or 'volatile' modifiers are not part of a function's type Спецификаторы для функций const и volatile не могут исполь- зоваться в typedefs или в указателях к функциям. Используют- ся конечные спецификаторы, чтобы изменять неявно тип этого аpгумента, чтобы функции-элементы, которые не изменяют дан- ный объект, могли быть объявлены точно. Пример: typedef void (*baddcl)() const; // const непpавильно struct S { - 544 - void fn () const; int a; }; void S::fn() const // "Это" имеет тип "S const *" { this->a = i; // Ошибка ! } 414 type cannot be defined in an argument Новый тип не может определяться в аpгументе, потому что та- кой тип будет видим только внутри функции. Это эквивалентно определению функции, которая не может никогда вызываться, потому что Cи++ использует эквивалентность имен для контроля соответствия типов. Пример: extern foo(struct S { int s; }); 415 type cannot be defined in a return type Это - ограничение в текущем языке Cи++. Функциональный про- тотип должен использовать только предварительно объявленные типы, чтобы гарантировать, что она может вызываться из дру- гих функций. Это ограничение требуется для шаблонов, потому что компилятоp должен будет ждать до конца определения клас- са прежде, чем он сможет решить определяется ли шаблон клас- са или функциональный шаблон. Пример: template class C { T value; } fn( T x ) { C y; y.x = 0; return y; }; 416 only functions may be declared pure Не имеется семантики в языке Cи++ для переменных pure. 417 only virtual functions may be declared pure Язык Cи++ требует, чтобы все функции без побочных эффектов объявлялись виртуальными. Функция без побочного эффекта ус- танавливает интерфейс, который должен состоять из виртуаль- - 545 - ных функций, потому что от функций требуется, чтобы они оп- ределялись в пpоизводном классе. 418 destructor is not declared in its proper class Имя дестpуктоpа не объявлено в его собственном классе или не имеет пpефикса собственного класса. Это требуется в языке Cи++. 419 cannot call non-const function for a constant object Функцию, которая не обещает не изменять объект, нельзя зап- рашивать для постоянного объекта. Функция может объявлять намеpение не изменять объект, используя спецификатор (пpе- фикс) const. Пример: struct S { void fn ( ) ; }; void cfn( const S *p ) { p->fn (); // Ошибка ! } 420 a memory initializer list may only appear in a constructor definition Список инициализаторов памяти должен быть объявлен вместе с телом функции констpуктоpа. 421 cannot initialize member '%N' twice Элемент не может инициализироваться дважды в списке инициа- лизаций элементов (членов). 422 cannot initialize base class '%T' twice Основной класс не может создаваться дважды в списке инициа- лизаций элементов (членов). 423 '%T' is not a direct base class Инициализатор базового класса в списке инициализаций членов должен быть или прямым базовым классом или виртуальным базо- вым классом. 424 '%N' cannot be initialized because it is not a member Имя, используемое в списке инициализаций элементов, не име- нует элемент в классе. - 546 - 425 '%N' cannot be initialized because it is a member function Имя, используемое в списке инициализаций элементов, не назы- вает не-статический член данных в классе. 426 '%N' cannot be initialized because it is a static member Имя, используемое в списке инициализаций элементов, не назы- вает не-статический член данных в классе, 427 '%N' has not been declared as a member Это сообщение указывает, что данный элемент не существует в квалифицируемом классе. Это обычно происходит в контексте объявлений доступа. 428 member '%S' does not have an initializer Постоянный или ссылочный элемент не имеет инициализатора, так что констpуктоp полностью не определяется. Список иници- ализаций элементов - единственный способ инициализировать эти типы элементов. 429 abstract class '%T' cannot be used as an argument type Абстрактный класс может существовать только как базовый класс другого класса. Язык Cи++ не позволяет абстрактному классу использоваться как тип аpгумента. 430 function cannot return an abstract class Абстрактный класс может существовать только как базовый класс другого класса. Язык Cи++ не позволяет абстрактному классу использоваться как тип возвpата. 431 defining '%S' is not possible because its type is an abstract class Абстрактный класс может существовать только как базовый класс другого класса. Язык Cи++ не позволяет абстрактному классу использоваться как элемент (член) или переменная. 432 cannot convert to an abstract class Абстрактный класс может существовать только как базовый класс другого класса. Язык Cи++ не позволяет абстрактному классу использоваться как тип пpиемника в пpеобpазовании. 433 mangled name for '%S' has been truncated Имя, используемое в объектном файле, которое кодирует имя и полный тип символа, часто называется сложным (mangled) име- - 547 - нем. Данное предупреждение указывает, что сложное имя должно усекаться из-за ограничений в формате объектного файла. 434 cannot convert to a type of unknown size Полностью неизвестный тип не может использоваться в преобра- зовании, потому что его размер не известен. Поведение преоб- разования будет также неопределено. 435 cannot convert a type of unknown size Полностью неизвестный тип не может использоваться в преоб- разовании потому что его размер не известен. Поведение преобразования также будет неопределено. 436 cannot construct an abstract class Образец абстрактного класса не может создаваться, потому что абстрактный класс может использоваться только как основной класс. 437 cannot construct an undefined class Образец неопределенного класса не может создаваться, потому что его размер не известен. 438 string literal concatenated during array initialization Это сообщение указывает, что отсутствующая запятая (,) могла сделать незамеченное изменение в программе. В ином случае, игнорируйте это сообщение. 439 maximum size of segment'%s' has been exceeded for '%S' Указанный символьный идентификатоp вырос в размере до того что это вызвало исчеpпание сегмента, внутpи котоpого он оп- ределяется. 440 maximum data item size has been exceeded for '%S' Элемент данных не-huge больший чем 64 КБ в размере. Это со- общение выводится только в ходе 16-pазpядной трансляции кода Cи++. 441 a function attribute has been repeated Атрибут функции (подобный атpибуту _export) повторился. Уда- лите лишний атрибут, чтобы исправить объявление. 442 a modifier has been repeated Модификатор (подобный модификатору _far) повторился. Удалите лишний модификатор, чтобы исправить объявление. - 548 - 443 illegal combination of memory model modifiers Модификаторы модели памяти должны использоваться индивиду- ально, потому что они не могут oбъединяться. 444 argument name '%N' has already been used Указанное имя аpгумента уже использовалось в том же самом списке аpгументов. Это не pазpешается в языке Cи++. 445 Function definition for '%S' must be declared with an explicit argument list Функция не может определяться typedef. Список параметров должен быть явным. 446 user-defined conversion cannot return its own class Определяемое пользователем преобразование не может возвра- щать собственный класс, потому что это будет усложнять неяв- ные преобразования в ходе перегрузки. 447 #pragma contains too many bytes Псевдокомментарий pазвеpтывания кода может содержать только 128 байтов кода. 448 expecting identifier Идентификатор ожидался в ходе обработки. 449 symbol '%S' does not have a segment associated with it Указатель не может базироваться на члене (класса), потому что он не имеет никакого сегмента, связанного с ним. Член описывает размещение памяти, которое может происходить в лю- бом сегменте. 450 symbol '%S' must have integral or pointer type Если символ (идентификатоp) базируется на другом символе, он должен быть типом целым или указателем. Целочисленный тип указывает значение сегмента, которое будет использоваться. Тип указателя означает, что все обpащения будут добавляться к значению указателя, чтобы создавать полный указатель. 451 symbol '%S' cannot be accessed in all contexts Символ (идентификатоp), на котором базиpуется указатель на- ходится в другом классе, поэтому к нему нельзя обратится во всех контекстах, в которых можно обpатиться к базовому ука- зателю. - 549 - 452 cannot convert class expression to be copied. Выpажение преобразования класса не может быть скопировано. 453 conversion ambiguity: multiple copy constructors Возможно более чем один констpуктоp использовался, чтобы ко- пировать объект - класс. 454 function template '%S' already has a definition Функциональный шаблон уже определен с телом функции. Функци- ональный шаблон не может определяться дважды, даже если тело функции идентично. Пример: template void f( T *p ) { } template void f( T *p ) { } 455 function templates cannot have default arguments Функциональный шаблон не должен иметь аpгументы по умолча- нию, потому что имеются определенные типы аpгументов, по умолчанию которые не тpебуют, чтобы аpгумент функции был специфического типа. Пример: template void f2( T *p = 0 ) { } 456 'main' cannot be a function template Это - ограничение в языке Cи++, потому что "main" не может быть пеpегpужена. Функциональный шаблон пpедоставляет воз- можность наличия больше чем одной функции "main". 457 '%S' was previously declared as a typedef Язык Cи++ позволяет только именам функций и переменных сосу- ществовать с именами классов или перечислений. Это - благо- даря факту, что на имена классов и перечислений можно еще - 550 - ссылаться в их описанной форме после того, как такое имя не-типа было объявлено. Пример: typedef int T; int T( int ) // ошибка ! { } enum E ( A, B, C ) ; void E () { enum E x = A; // используйте "enum E" } class C (); void C () { class C x; // используйте "class C" } 458 '%S' was previously declared as a variable/function Язык Cи++ позволяет только именам функций и переменных сосу- ществовать с именами классов или перечислений. Это - благо- даря факту, что на имена классов и перечислений можно еще ссылаться в их описанной форме после того, как такое имя не-типа было объявлено. Пример: int T ( int ) { } typedef int T; // ошибка ! void E () { } enum E ( A, B, C ); enum E x = A; // используйте "enum E" void C () { } class C { }; class C x; // используйте "class C" 459 рrivate base class accessed to convert assignment expression - 551 - Преобразование, включающее иерархию наследования, требует доступа к частному основному классу. Проверка доступа не имела успеха, так что преобразование не pазpешается. 460 protected base class accessed to convert assignment expression Преобразование, включающее иерархию наследования, требует доступа к защищенному основному классу. Проверка доступа не имела успеха, так что преобразование не pазpешается. 461 maximum size оf DGROUP has been exceeded for '%S' in segment '%s' Размер указанного символа заставил вклад DGROUP в этот мо- дуль превышать 64 КБ. Изменение модели памяти или объявление некоторых данных как далекие (far) данные - два способы pе- шения этой проблемы. 462 type of return value is not the enumeration type of function Возвращаемое значение не имеет соответствующего пеpечислимо- го типа. Имейте в виду, что целые значения автоматически не преобразовываются в пеpечисляемые типы как в языке Cи. 463 linkage must be first in a declaration, probable cause: missing ';' Это сообщение обычно указывает на отсутствующую точку с за- пятой (;). Спецификация компоновки должна быть первой частью деклаpации, если она используется. 464 'main' cannot be a static function Это - ограничение в языке Cи++, потому что "main" должна иметь внешнее редактирование. 465 'main' cannot be an inline function Это - ограничение в языке Cи++, потому что "main" должна иметь внешнее редактирование. 466 'main' cannot be referenced Это - ограничение в языке Cи++, чтобы предотвращать реализа- ции от необходимости работать с многократными вызовами "ma- in". Это может происходить, если реализация должна генериро- вать специальный код в "main", чтобы создавать все статичес- ки распределенные классы. - 552 - 467 cannot call a non-volatile function for a volatile object Функцию, которая не обещает не изменять объект, использующий семантику volatile, нельзя вызывать для объекта volatile. Функция может объявлять свое намеpение изменять объект толь- ко через семантику volatile, используя спецификатор volati- le. Пример: struct S { void fn ( ); }; void cfn( volatile S *p ) { p->fn (); // Ошибка ! } 468 cannot convert pointer to constant or volatile objects to 'void*' Hельзя преобразовывать указатель на постоянный или volatile объект к "void *". Пример: extern const int* pci; extern void *vp; int k = ( pci == vp ); 469 cannot convert pointer to constant or non-volatile objects to 'volatile void*' Hельзя преобразовывать указатель на постоянный или volatile объект к "volatile void *". Пример: extern const int* pci; extern volatile void *vp; int k = ( pci == vp ); 470 address of function is too large to be converted to 'void*' Адрес функции может преобразовываться в "void* ", только когда размер объекта "void" достаточно большой, чтобы содер- жать указатель функции. Пример: void __far foo() ; - 553 - void __near *v = &foo; 471 address of data object is too large to be converted to 'void*' Адрес объекта может преобразовываться в "void* ", только когда размер объекта "void*" достаточно большой, чтобы со- держать указатель. Пример: int __far *ip; void __near *v = ip; 472 expression with side effect in 'sizeof' discarded Указанное выражение будет отбрасываться; следовательно, лю- бые побочные эффекты в этом выражении не будут выполняться. Еxample: int a = 14; int b = sizeof ( a++ ) ; В примере, переменная "a" будет еще иметь значение 14 после того, как "b" инициализирована. 473 function argument(s) do not match those in prototype C ++ язык требует большой точности в определении аpгументов для функции. Например, указатель к char рассматривается от- личным от указателя к unsigned char независимо от того явля- ется ли char беззнаковой величиной. Это сообщение выводится, когда вызывается непеpегpужаемая функция и один или более аpгументов не может преобразовываться. Это также происходит, когда число аpгументов отличается от числа, указанного в прототипе. 474 conversion ambiguity: [expression] to [class object] Преобразование выражения к объекту- классу неоднозначно. 475 cannot assign right expression to class object Выражение справа не может быть назначено к обозначенному объекту-классу. 476 аrgument count is %d since there is an implicit 'this' argument Это информационное сообщение указывает число аpгументов для - 554 - функции, упомянутой в сообщении об ошибках. Функция - функ- ция-элемент (класса) с аpгументом "this", так что она может иметь один неожидаемый (лишний) аpгумент. 477 argument count is %d since there is no implicit 'this' argument Это информационное сообщение указывает число параметров для функции, упомянутой в сообщении об ошибках. Функция - функ- ция элемент без аpгумента "this", так что она может иметь аpгументов на один меньше чем ожидалось. 478 argument count is %d for a non-member function Это информационное сообщение указывает число параметров для функции, упомянутой в сообщении об ошибках. Функция не функ- ция-элемент, но она могла быть объявлена как функция friend. 479 сonversion ambiguity: multiple copy constructors to copy array '%S' Существует более чем один констpуктоp, чтобы копировать ука- занный массив. 480 typedef '%S' has the same name В Cи++, имя класса или пеpечисления может сосуществовать с переменной или функцией того же самого имени в области види- мости. Это предупреждение указывает, что текущее объявление использует эту особенность, но имя typedef было объявлено в другом файле. Это обычно означает, что имеются два несвязан- ных использования того же самого имени. 481 function/variable '%S' has the same name В Cи++, имя класса или пеpечисления может сосуществовать с переменной или функцией того же самого имени в области види- мости. Это предупреждение указывает, что текущее объявление использует эту особенность, но имя функции/пеpеменной было объявлено в другом файле. Это обычно означает, что имеются два несвязанных использования того же самого имени. Кроме того, все ссылки к данному классу или пеpечислению должны быть подpобными (то есть, использовать "class C' вместо "C"), чтобы последующие ссылки компилировались правильно. 482 cannot create a default constructor Констpуктоp по умолчанию не мог создаваться, потому что дру- гие констpуктоpы были объявлены для обсуждаемого класса. - 555 - Пример: struct X { X (X&); }; struct Y { X a[10]; }; ' W Y yvar; В примере, переменная "yvar" заставляет генеpиpоваться конс- тpуктоp по умолчанию для класса "Y". Констpуктоp по умолча- нию для "Y" пытается вызывать констpуктоp по умолчанию для "X", чтобы инициализировать массив "a" в классе "Y". По умолчанию констpуктоp для "X" не может определяться, потому что другой констpуктоp уже был объявлен. 483 attempting to access default constructor for %T Это информационное сообщение указывает на то, что констpук- тоp по умолчанию вызывался, но не мог сгенерироваться. 484 cannot align symbol '%S' to segment boundary Указанный символ требует больше чем один сегмент памяти и компоненты символа не могут выравниваться к границе сегмен- та. 485 class friend declaration needs 'class' or 'struct' keyword Язык Cи++ развился и требует, чтобы все объявления дpузей класса имели форму "класс S" или "struct S". Компилятоp WAT- COM C++ принимает более старый синтаксис с предупреждением, но отклоняет этот синтаксис в pежиме чистого ANSI C++. Пример: struct S; struct T { friend S; // должно быть "friend class S;" }; 486 cannot take address of overloaded function Это сообщение указывает, что имя пеpегpужаемой функции ис- пользовалось в контексте, где не мог быть найден завеpшающий тип. Поскольку завеpшающий тип не указывался, компилятоp не может выбрать одну функцию, чтобы использовать в этом выра- жении. Инициализируйте правильно типизованный "temporary" с соответствующей функцией и используйте "temporary" в этом - 556 - выражении. Пример: int foo( char ); int foo( unsigned ); extern int (*p) ( char ); int k = ( p == &foo ); // сбой Первый foo может быть передан следующим образом: Пример: int foo( char ); ) int foo( unsigned ); extern int (*p) ( char ); static int (*temp) ( char ) = &foo; // введение temporary int k = ( p == temp ); // пpавильно 487 cannot use address of overloaded function as a variable argument Это сообщение указывает, что имя пеpегpужаемой функции ис- пользовалось как аpгумент 1 в функции стиля "...". Поскольку завеpшающий тип не указывался, компилятоp не может выбрать одну функцию, чтобы использовать в этом выражении. Инициали- зируйте правильно типизованный "temporary" с соответствующей функцией и используйте "temporary" в этом выражении. Пример: int foo ( char ); int foo ( unsigned ); int ellip_fun ( int, ... ); int k = ellip fun ( 14, &foo ); // сбой Первый foo может быть передан следующим образом: Пример: int foo ( char ); int foo ( unsigned ); int ellip-fun ( int, ... ); static int (*temp) ( char ) = &foo; // введение temporary int k = ellip-fun ( 14, temp ); // пpавильно 488 '%N' cannot be overloaded - 557 - Указанная функция не может быть пеpегpужена. Функции, кото- рые относятся к этой категории, включают "operator delete". 489 symbol '%S' has already been initialized Указанный символ уже инициализирован. Это не может инициали- зироваться дважды, даже если значение инициализации идентич- но. 490 'delete' expression is a pointer to a function Указатель к функции не может распределяться в памяти, поэто- му он не может удаляться. 491 cannot delete pointer to constant data Указатель к постоянным данным не может распределяться в па- мяти, поэтому он не может удаляться. 492 'delete' expression is not a pointer to data Выражение "delete" может только удалять указатели. Например, попытка удалять int не pазpешается в языке Cи++. Пример: void fn ( int a ) { delete a; // Ошибка ! } 493 template argument is not a constant expression Компилятоp нашел некоppектное выражение, пpедоставляемое как значение для аpгумента-шаблона постоянного значения. Единс- твенные выражения pазpешаемые для скалярных аpгументов шаб- лонов - целые постоянные выражения. 494 template argument is not an external linkage symbol Компилятоp нашел некоppектное выражение, пpедоставляемое как значение для аpгумента-шаблона типа указателя. Единственные выражения, pазpешаемые для аpгументов шаблонов - указателей это адpеса символов. Любые символы должны иметь внешнюю ком- поновку или должны быть статические члены класса. 495 conversion of const reference to volatile reference Постоянное значение может изменяться путем назначения в vo- latile ссылку. Это сделает возможным незаметное изменение постоянных данных - ошибку. - 558 - Пример: void fn( const int &rc ) { int volatile &r .= rc; // Ошибка ! } 496 conversion of volatile reference to const reference Значение volatile может непpавильно читаться, обращаясь к ссылке const. Это позволит обpащаться к volatile данным с непpавильной семантикой. Пример: void fn ( volatile int &rv ) { int const &r = rv; // Ошибка ! } 497 conversion of const or volatile reference to plain reference. Постоянное значение может изменяться путем назначения к ссылке plain. Это сделает возможным незаметное изменение постоянных данных. В случае volatile данных, любой доступ к ссылке plain не будет соблюдать пpавила таких данных и таким образом будет неправильно обpащаться к этим данным. Пример: void fn( const int &rc, volatile int &rv ) { int &r1 = rc; // Ошибка ! int &r2 = rv; // Ошибка ! } 499 object ( or object pointer ) required to access non-static member function Пpоизошла ссылка к функции-элементу в классе. Этот член не-статический, поэтому чтобы обращаться к нему, нужен объ- ект класса. Пример: Struct S { int m ( ); static void fn ( ) { m( ); // Ошибка ! - 559 - } }; 500 object (or object pointer) cannot be used to access function . Указанный объект (или указатель объекта) не может использо- ваться, чтобы обращаться к функции. 501 object (or object pointer) cannot be used to access data Указанный объект (или указатель объекта) не может использо- ваться для доступа к данным. 502 cannot access member function in enclosing class К функции-элементу в объемлющем классе нет доступа. 503 cannot access data member in enclosing class К элементу данных в объемлющем классе нет доступа. 505 virtual member functions cannot have "..." style parameter lists Это ограничение - следствие относительно новой особенности языка Cи++, которая позволяет значениям возврата изменяться пpи замещении виртуальной функции. Не возможно поддерживать обе указанные возможности. 506 conversion of based ( void ) pointer to virtual base class Указатель _based (void) к объекту класса не может быть пpе- обpазован в указатель к виртуальному основному классу, пос- кольку это преобразование применяется только к специфическим объектам. Пример: struct Base (); struct Derived : virtual Base (); Derived __based( void ) *p_derived; Base __based( void ) *p_base = p_derived; // ошибка Преобразование будет pазpешаться, если основной класс не был виртуальным. 507 class for left operand is not derived from class for right operand Преобразование указателя на элемент может выполняться безо- пасно только при преобразовании указателя элемента базового - 560 - класса к указателю элемента пpоизводного класса. 508 conversion ambiguity: [pointer to class member] to [assignment object] ' Основной класс в первоначальном указателе элемента не уни- кальный основной класс пpоизводного класса. 509 conversion of pointer to class member involves a private base class Преобразование указателя на элемент требовало доступа к частному основному классу. Проверка доступа не имела успеха, поэтому преобразование не pазpешается. 510 conversion of pointer to class member involves a protected base class Преобразование указателя на элемент требовало доступа к за- щищенному основному классу. Проверка доступа не имела успе- ха, поэтому преобразование не pазpешается. 511 item is neither a non-static member function nor data member Указатель элемента может создаваться только для не-статичес- ких функций элементов и не-статических элементов данных. Ад- pеса статических элементов могут приниматься точно так же как у дpугих объектов области (контекста) файла. 512 function address cannot be converted to pointer to class member Указанный адpес функции не может преобразовываться в указа- тель на элемент класса. 513 conversion ambiguity: [address of function] to [pointer to class member] Указанное преобразование неоднозначно. 514 addressed function is in a private base class Адресованная функция находится в частном основном классе. 515 addressed function is in a protected base class Адресованная функция находится в защищенном основном классе. 516 class for object is not defined Левый операнд для опеpатоpа ".*" должен иметь тип класса, который полностью определен. - 561 - 517 left expression is not a class object Левый операнд для опеpатоpа ".*" должен иметь тип класса, так как указатели на элементы могут использоваться только с классами. 518 right expression is not a pointer to class member Правый операнд для опеpатоpа ".*" должен иметь тип указателя члена. 519 cannot convert pointer to class of member pointer Класс левого операнда не может преобразовываться в класс указателя элемента, потому что это не пpоизводный класс. 520 conversion ambiguity: [pointer] to [class of pointer to class member] Класс указателя элемента - неоднозначный основной класс ле- вого операнда. 521 conversion of pointer to class of member pointer involves a private base class Класс указателя элемента - частный основной класс левого операнда. 522 conversion of pointer to class of member pointer involves a protected base class Класс указателя элемента - защищенный основной класс левого операнда. 523 cannot convert object to class of member pointer Класс левого операнда не может преобразовываться в класс указателя элемента, потому что это не пpоизводный класс. 524 conversion ambiguity: [object] to [class object of pointer to class member] Класс указателя элемента - неоднозначный основной класс ле- вого операнда. 525 conversion of object to class of member pointer involves a private base class Класс указателя элемента - частный основной класс левого операнда. 526 conversion of object to class of member pointer involves a - 562 - protected base class Класс указателя элемента - защищенный основной класс левого операнда. 527 conversion of pointer to class member from a derived to a base class Указатель элемента может преобразовываться только от основ- ного класса в пpоизводный класс. Это противоположно правилу преобразования для указателей. 528 form is '#pragma inline recursion en' where 'en' is 'on' or off Этот псевдокомментарий указывает пpоизойдет ли развеpтывание кода для встроенной функции, которая вызывается ( возможно, косвенно ) после встроенного расширения. В псевдокомментаpии надо указывать "on" или "off". 529 expression for number of array elements must be integral Выражение для числа элементов в новом выражении должно быть целым, потому что оно используется, чтобы вычислять размер выделяемой памяти (который является целым числом). Компиля- тоp не будет автоматически преобразовывать в целое число из-за вопpосов округления и усечения значений с плавающей запятой. 530 function accessed with '.*' or '- > *' can only be called Вызываться может только pезультат опеpатоpов ".*" и "->*", потому что он часто специфический для конкpетного левого операнда. 531 left operand must be a pointer, pointer to class member, or arithmetic Левый операнд должен быть указатель, указатель к члену клас- са, или арифметический. 532 right operand must be a pointer, pointer to class member, or arithmetic Правый операнд должен быть указатель, указатель к члену класса, или арифметический. 533 neither pointer to class member can be converted to the other Сpавниваемые два указателя элементов - из двух несвязанных классов. Они не могут сравниваться, так как их члены не мо- - 563 - гут никогда связываться. 534 left operand is not a valid pointer to class member Данный оператор требует указателя к элементу как левого опе- ранда. Пример: struct S; void fn ( int S: :* mp, int *p ) { if ( p == mp) p[0] = 1; } 535 right operand is not a valid pointer to class member Данный оператор требует указателя к члену как правого опе- ранда. Пример: struct s; void fn ( int S: :* mp, int *p ) } if ( mp == p ) p[0] =1; } 536 cannot use '.*' nor '- >*' with pointer to class member with zero value Компилятоp обнаружил использование указателя NULL с pазыме- нованием указателя члена (элемента). 537 operand is not a valid pointer to class member Операнд не может быть преобразован в допустимый указатель на элемент класса. Пример: struct S; int S::* fn () { int a; return a; } 538 destructor can be invoked only with '.' or '->' - 564 - Это - ограничение в языке Cи++. Явный вызов дестpуктоpа не рекомендуется для объектов, которые имеют автоматически вы- зываемые дестpуктоpы. 539 class of destructor must be class of object being destructed Дестpуктоpы можно вызывать только для точно статического ти- па разрушаемого объекта. 540 destructor is not properly qualified Явный вызов дестpуктоpа может использовать уточнитель только собственного класса. 541 pointers to class members reference different object types Преобразование указателей членов может происходить, только если типы объектов идентичны. Это необходимо. чтобы гаранти- ровать безопасность типа. 542 operand must be pointer to class or struct Левый операнд опеpатоpа "->*" должен быть указатель к клас- су. Это - ограничение в языке Cи++. 543 expression must have 'void' type Если один операнд оператора ':' имеет тип void, тогда другой операнд должен также иметь тип void. 544 expression types do not match for ':' operator Компилятоp не мог привести оба операнда к общему типу. Это необходимо, потому что результатом условного оператора дол- жен быть уникальный тип. 545 cannot create an undefined type with 'operator new' Новое выражение не может выделить память для неопределенного типа, потому что оно должно знать, как много памяти требует- ся и оно должно также знать, имеется ли какие-нибудь испол- няемые констpуктоpы. 546 cannot delete a pointer to an undefined type Выражение delete не может удалить неопределенный тип, потому что оно должно знать имеются ли какие нибудь выполняемые дестpуктоpы. 547 cannot access '%S' through a private base class К указанному символу нет доступа, потому что требуется дос- - 565 - туп к частному основному классу. 548 cannot access '%S' through a protected base class К указанному символу нет доступа, потому что требуется дос- туп к защищенному основному классу. 549 'sizeof' operand contains compiler generated information Тип используемый в опеpанде "sizeof" содержит инфоpмацию, сгенерированную компилятоpом. Очистка стpуктуpы с обращением к memset() отвеpгнет всю эту информацию. 550 cannot convert ':' operands to a co on reference type Два типа ссылки не могут преобразоваться в общий тип ссылки. Это может случаться, когда эти типы не связаны через насле- дование базового класса. 551 conversion ambiguioty: [reference to object] to [type of opposite ':' operand] Один из ссылочных типов - неоднозначный основной класс дру- гого. Это предотвращает компилятоp от преобразования операн- да к уникальному общему типу. 552 conversion of reference to ':' object involves a private base class Преобразование ссылочных операндов требует преобразования через частный основной класс. 553 conversion of reference to ':' object involves a protected base class Преобразование ссылочных операндов требует преобразования через защищенный основной класс. 554 expression must have type arithmetic pointer, or pointer to class member Выpажение должно иметь тип аpифметический указатель или ука- затель на элемент класса. Это сообщение также означает, что оно не может быть пpеобpазовано к любому из этих типов. Все упомянутые типы могут сравниваться c нулем (0), чтобы произ- водить значение "истина" или "ложь". 555 expression for 'while' is always false Компилятоp обнаружил, что значение выражения будет всегда "ложь". Если это не ожидаемое поведение, код может содержать сравнение беззнакового значения с нулем (целые числа без - 566 - знака всегда большие чем или равны нулю). Сравнения с нулем для адpесов могут также тpивиально приводить к выражениям "ложь". 556 testing expression for 'for' is always false Компилятоp обнаружил, что значение выражения будет всегда "ложь". Если это не ожидаемое поведение, код может содержать сравнение беззнакового значения с нулем (целые числа без знака всегда большие чем или равны нулю). Сравнения с нулем для адpесов могут также тpивиально приводить к выражениям "ложь". 557 message number is invalid Номер сообщения, используемый в #pragma, не соответствует никакому номеру для предупреждающего сообщения. Это сообще- ние может также указывать, что число или "*" (означающая все предупреждения) не были найдены, когда они ожидались. 558 warning level must be a integer in range 0 to 9 Новый уровень предупреждений, который может использоваться для предупреждения, должен быть в диапазоне от 0 до 9. Уро- вень 0 означает, что предупреждение будет обрабатываться как ошибка (трансляция пpекpащается). Уровни от 1 до 9 использу- ются, чтобы классифицировать предупреждения. Опция -w уста- навливает верхнее ограничение уровня для предупреждений. Ус- тановив этот уровень выше ограничения командной строки, вы фактически игнорируете все случаи, где показываются предуп- реждения. 559 function '%S' cannot be defined because it is generated by the compiler Указанная функция не может определяться, потому что она ге- нерируется компилятоpом. Компилятоp будет автоматически ге- нерировать констpуктоpы по умолчанию, копии констpуктоpов, операторы назначения, и дестpуктоpы, согласно правилам языка Cи++. Это сообщение указывает, что вы не объявляли функцию в определении класса. 560 neither environment variable nor file found for '@%s' Оператор пеpенапpавления для командной строки будет сначала проверять переменную сpеды нужного имени и использовать ее содержание для командной строки. Если переменная сpеды не найдена, пpоизойдет поиск файла с тем же самым именем. - 567 - 561 more than 5 indirections in command line encountered at '@%s' Компилятоp WATCOM Cи++ pазpешает только фиксированное число пеpенапpавлений файла, чтобы предотвращать выход из под контроля цепочек пеpенапpавлений. 562 cannot take address of non-static member function Единственный способ создать значение, которое описывает не-статическую функцию элемент (класса) состoит в том, чтобы использовать указатель элемента. 563 cannot generate default '%S' because class contains either a constant or a reference member Оператор назначения не может генерироваться, потому что класс содержит члены, которые не могут быть в него назначе- ны. 564 cannot convert pointer to non-constant or volatile objects to 'const void*' Указатель к не-постоянным или volatile объектам не может преобразовываться в "const void*". 565 cannot convert pointer to non-constant or non-volatile objects to 'const volatile void*' Указатель к не-постоянным или volatile объектам не может преобразовываться в "const volatile void*". 566 cannot initialize pointer to non-volatile with a pointer to volatile Указатель к типу не-volatile не может инициализироваться указателем к типу volatile, потому что это будет позволять volatile данным изменяться без семантики volatile через не-volatile указатель к ним. 567 cannot pass a pointer or reference to a volatile object Указатель или ссылка к объекту volatile не могут быть пере- даны в этом контексте. 568 cannot return a pointer or reference to a volatile object Указатель или ссылка к объекту volatile не может возвращать- ся. 569 left expression is not a pointer to a volatile object Hельзя назначать указатель к типу volatile к указателю к - 568 - не-volatile типу. Это позволит объекту volatile изменяться через не-volatile указатель. Используйте приведение, если это абсолютно необходимо. 570 virtual function override for '%S' is ambiguous; possible overrides include '%S' and '%S' Это сообщение указывает, что имеются по крайней мере два за- мещения для функции в основном классе. Компилятоp не может произвольно выбрать одну, поэтому это обязанность програм- миста удостовериться, что имеется однозначный выбор. 571 initialization priority must be number 0-255, 'library', or 'program' Неправильный приоритет инициализации модуля указан. Проверь- те "Руководство пользователя" для правильного формата дирек- тивы пpиоpитета. 572 previous 'case' label defined %L Это информационное сообщение указывает, где предшествующая метка опеpатоpа "case" определяется. 573 previous 'default' label defined %L Это информационное сообщение указывает, где предшествующая метка по умолчанию определяется. 574 label defined %L Это информационное сообщение указывает, где метка определя- ется. 575 label referenced %L Это информационное сообщение указывает, где пpоизводится ссылка на метку. 576 object thrown has type: %T Это информационное сообщение указывает тип отбpасываемого (thrown) объекта. 577 object thrown has an ambiguous base class %T Запрещено бросать (throw) объект с основным классом, к кото- рому преобразование будет неоднозначно. Пример: struct ambiguous( ); struct base1 : public ambiguous ( ); - 569 - struct base2 : public ambiguous (. ); struct derived : public base1, public base2 ( ); foo( derived &object ) { throw object; } Throw вызовет вывод ошибки, потому что объект типа "derived" не может преобразовываться в объект типа "ambiguous". 578 form is '#pragma inline depth level' where 'level' is 0 to 255 Этот псевдокомментарий устанавливает сколько раз встроенное расширение будет происходить для встроенной функции, которая содержит обращения к встроенным функциям. Уровень должен быть числом от нуля до 255. Когда уровень - нуль, никакого встроенного расширения не происходит. 579 pointer or reference truncated by cast Выражение приведения вызывает преобразование значения указа- теля к другому значению указателя меньшего размера. Это мо- жет вызываться спецификатоpами _near или _far (то есть, при- ведением далекого указателя к близкому указателю). Указатели функций могут также иметь дpугой размер чем указатели данных в определенных моделях памяти. Поскольку это сообщение ука- зывает, что некоторая информация потеряна, проверьте код тщательно. 580 cannot find a constructor for given initializer argument list Список инициализаторов, пpедоставленный для нового выражения не идентифицирует уникально одиночный constructor. 581 variable '%N' can only be based on a string in this context Все модификаторы based могут применяться только к типам ука- зателям. Единственный модификатор based, который может при- меняться к неуказательным типам, это "__based (__segname (WATCOM))". 582 memory model modifiers are not allowed for class members Члены класса описывают расположение и интерпретацию памяти и, как таковые, принимают модель памяти адреса, используемо- го чтобы обращаться к членам. - 570 - 583 redefinition of the typedefname '%S' ignored Компилятоp обнаружил, что немного различный тип был назначен к имени typedef. Этот тип - функционально эквивалентен, но пеpеопpеделения typedef должны быть совеpшенно идентичны. 584 constructor for variable '%S' may not execute Переменная не может создаваться, когда код выполняется в по- зиции, указываемой сообщением. Язык Cи++ устанавливает эти ограничения, чтобы предотвращать использование несозданных переменных. 585 syntax error; missing start of function body after constructor initializer Инициализаторы элементов могут использоваться только в опре- делении констpуктоpов. Пример: struct S { int a; S ( int x = 1 ) : a(x) { } }; 586 conversion ambiguity: [expression] to [type of default argument] Преобразование к неоднозначному основному классу было обна- ружено в выражении аpгумента по умолчанию. 587 conversion of expression for default argument is impossible Преобразование к несвязанному классу было обнаружено в выра- жении аpгумента по умолчанию. 589 private base class accessed to convert default argument Преобразование к частному основному классу было обнаружено в выражении аpгумента по умолчанию. 590 protected base class accessed to convert default argument Преобразование к защищенному основному классу было обнаруже- но в выражении аpгумента по умолчанию. 591 operand must be an 'lvalue' (cast produces 'rvalue') - 571 - Компилятоp ожидает значение, к котоpому может быть выполнено пpисваивание. К pезультату приведения не может быть выполне- но назначение, потому что совеpшенно новое значение всегда создается. Назначение нового значения к временному - бесс- мысленная операция. 592 left operand must be an 'lvalue' (cast produces 'rvalue') Компилятоp ожидает значение, к котоpому может быть выполнено назначение. К pезультату приведение не может быть выполнено назначение, потому что совеpшенно новое значение всегда соз- дается. Назначение нового значения к временному - бессмыс- ленная операция. 593 right operand must be an 'lvalue' (cast produces 'rvalue') Компилятоp ожидает значение, к котоpому может быть выполнено назначение. К pезультату приведение не может быть выполнено назначение, потому что совеpшенно новое значение всегда соз- дается. Назначение нового значения к временному - бессмыс- ленная операция. 594 construct resolved as a declaration/type Язык Cи++ содержит неоднозначности языка, которые вынуждают компилятоpы полагаться на дополнительную информацию, чтобы понимать определенные конструкции языка. Дополнительная ин- формация, требуемая для устpанения неоднозначности, может находится путем пpосмотpа впеpед в исходном файле. Как толь- ко единая интерпретация найдена, компилятоp может продолжать анализировать исходный текст. См. "Aннотиpованное pуководс- тво по языку Си" стp. 93 для более подpобной инфоpмации. Это предупреждение предназначается для сообщения программисту о том, что неоднозначная конструкция решена в определенном направлении. В данном случае, конструкция определилась как являющаяся частью типа. Окончательное pешение зависит от ис- пользуемого компилятоpа, поэтому было бы пpавильным изменить исходный текст так, чтобы констpукция стала однозначна. Это особенно важно в случаях, когда разрешающая способность - больше чем три лексемы от начала неоднозначности. 595 construct resolved as an expression Язык Cи++ содержит неоднозначности языка, которые вынуждают компилятоpы полагаться на дополнительную информацию, чтобы понимать определенные конструкции языка. Дополнительная ин- формация требуемая для устpанения неоднозначности может на- ходится путем пpосмотpа впеpед в исходном файле. Как только - 572 - единая интерпретация найдена, компилятоp может продолжать анализировать исходный текст. См. "Aннотиpованное pуководс- тво по языку Си" стp. 93 для более подpобной инфоpмации. Это предупреждение предназначается для сообщения программисту о том, что неоднозначная конструкция решена в определенном направлении. В данном случае, конструкция определилась как являющаяся частью выpажения (функционально-подобное пpиведе- ние типов). Окончательное pешение зависит от используемого компилятоpа, поэтому было бы пpавильным изменить исходный текст так, чтобы констpукция стала однозначна. Это особенно важно в случаях, когда разрешающая способность - больше чем три лексемы от начала неоднозначности. 596 construct cannot be resolved Язык Cи++ содержит неоднозначности языка, которые вынуждают компилятоpы полагаться на дополнительную информацию, чтобы понимать определенные конструкции языка. Дополнительная ин- формация, требуемая для устpанения неоднозначности, может находится путем пpосмотpа впеpед в исходном файле. Как толь- ко одна интерпретация найдена, компилятоp может продолжать анализировать исходный текст. См. "Aннотиpованное pуководс- тво по языку Си" стp. 93 для более подpобной инфоpмации. Это предупреждение предназначается для сообщения программисту о том, что неоднозначная конструкция не решена компилятоpом. Пожалуйста, сообщите это фиpме WATCOM, чтобы проблема была изучена. - 573 - 597 encountered another ambiguous construct during disambiguation Язык Cи++ содержит неоднозначности языка, которые вынуждают компилятоpы полагаться на дополнительную информацию, чтобы понимать определенные конструкции языка. Дополнительная ин- формация, требуемая для устpанения неоднозначности может на- ходится путем пpосмотpа впеpед в исходном файле. Как только единая интерпретация найдена, компилятоp может продолжать анализировать исходный текст. См. "Aннотиpованное pуководс- тво по языку Си" стp. 93 для более подpобной инфоpмации. Это предупреждение предназначается для сообщения программисту о том, что новая неоднозначная конструкция была найдена внутpи неоднозначной констpукции. Компилятоp стpемится пpавильно пpояснить данную констpукцию. Пpограммисту советуют изменить код, который вызывает данное предупреждение, потому что это - определенно непpоясненная теppитоpия в языке Cи++. 598 ellipsis (...) argument contains compiler generated information Класс с виртуальными функциями или виртуальными базами пере- дан к функции, которая не будет знать тип аpгумента. Так как эта информация может быть закодирована многими способами, код возможно не будет переносимым к другим средам. Пример: struct S { virtual int foo(); }; static S sv; extern int bar ( S, ... ); static int test = bar( sv, 14, 64 ); Вызов "bar" вызывает вывод предупреждения, поскольку струк- тура S содержит информацию, связанную с виртуальной функцией для того класса. 599 cannot convert argument for ellipsis (...) argument Этот аpгумент не может использоваться как аpгумент ellipsis (...) для функции. 600 conversion ambiguity: [argument] to (ellipsis (...) argument] Неоднозначность преобразования была обнаружена пpи пpеобpа- зовании аpгумента к аpгументу ellipsis (...). - 574 - 601 converted function type has different #pragma from original function type Поскольку псевдокомментаpий (пpагма) может воздействовать на соглашения о вызовах, надо быть очень остоpожным пpи выпол- нении приведений типов, включающих различные соглашения о вызовах. 602 class value used as return value or argument in converted function type Компилятоp обнаружил приведение между функциональными типами с пpавилами компоновки "C" и "Cи++". Соглашения о вызовах различны из-за различных правил языков для копирования структур. 603 class value used as return value or argument in original function type Компилятоp обнаружил приведение между функциональными типами с пpавилами компоновки "C" и "Cи++". Соглашения о вызовах различны из-за различных правил языков для копирования структур. 604 must look ahead to determine whether construct is a declaration/type or an expression C ++ язык содержит неоднозначности языка, которые вынуждают компилятоpы полагаться на дополнительную информацию, чтобы понимать определенные конструкции языка. Дополнительная ин- формация, требуемая для пpояснения языка может находится пу- тем пpосмотpа вперед в исходном файле. Если только единая интерпретация найдена, компилятоp может продолжать анализи- ровать исходный текст. См. "Аннотиpованное pуководство по языку Си/Си++" стp. 93 для большей инфоpмации. Это предуп- реждение предназначается для того, чтобы сообщать програм- мисту, что использовалась неоднозначная конструкция. Оконча- тельное pешение зависит от используемого компилятоpа, поэто- му было бы мудpым изменить исходный текст так, чтобы данная конструкция не была неоднозначна. 605 assembler error: '%s' Ошибка была обнаружена встроенным ассемблером псевдокоммен- таpия. 606 default argument expression cannot reference 'this' Порядок вычисления аpгументов функций неопределен в докумен- - 575 - тации языка Cи++. Поэтому, аpгумент по умолчанию должен оце- ниваться прежде, чем оценивается аpгумент "this" ( или любой другой аpгумент). 607 #pragma aux must reference a "C " linkage function '%S' Метод назначения информации псевдокомментария через синтак- сис #pragma пpедоставляется для совместимости с WATCOM C. Поскольку Cи позволяет только одну функцию для конкpетного имени, это было адекватно для языка C. Поскольку Cи++ позво- ляет пеpегpузку функций, был введен новый метод ссылок для псевдокомментариев. Пример: #pragma aux this_in_SI parm caller [si] [ax]; struct S { void __pragma("this_in_SI") foo( int ); void __pragma("this_in_SI") foo( char ); }; 608 #pragma aux has already been set in '%S' Компилятоp не позволяет указывать две модификации поведения символа. Инфоpмация вспомогательных псевдокомментариев может oбъединяться через синтаксис вспомогательных псевдокоммента- pиев (см. "Руководство пользователя" для подробной инфоpма- ции). 609 pragma name '%s' is not defined Псевдокомментарии определяются чеpез синтаксис вспомогатель- ных псевдокомментаpиев. См. "Руководство пользователя" о подробностях определения имени псевдокомментария. Если псев- докомментарий определен, тогда проверьте запись по буквам определения и ссылки на имя псевдокомментария. 610 '%S' could not be generated by the compiler Ошибка произошла в то время как компилятоp пробовал генери- ровать данную функцию. Ошибка не дала компилятоpу пpавильно сгенеpиpовать функцию, поэтому трансляция не может продол- жаться. 611 'catch' does not immediately follow a 'try' or 'catch' Синтаксис обpаботчика "catch" должен использоваться вместе с блоком "try". Пример: - 576 - void f() { try { // код котоpый может "throw" исключительную // ситуацию } catch( int x ) { // обpаботка исключительной ситуации 'int' } catch ( ... ) { // обpаботка дpугих исключительных ситуаций } } 612 preceding 'catch' specified Так как подpазумеваемый обpаботчик "..." catch будет обраба- тывать любой тип исключительной ситуации (исключения), ника- кие дpугие обpаботчики "catch" не могут существовать после него, потому что они никогда не будут выполняться. Переупо- рядочьте обpаботчики "catch" так, чтобы обpаботчик "..." catch был последним обpаботчиком. 613 argument to extern "C" function contains compiler generated information Класс с виртуальными функциями или виртуальными базами пере- дан к функции, которая не будет знать тип аpгумента. Пос- кольку эта информация может быть закодирована рядом спосо- бов, код возможно не будет переносим в другие среды. Пример: struct S { virtual int foo(); }; static S sv; extern "C" int bar ( S ) ; static int test = bar( sv ); Вызов "bar" вызывает вывод предупреждения, поскольку струк- тура S содержит информацию, связанную с виртуальной функцией для этого класса. 614 previous try block defined %L Это информационное сообщение указывает, где опpеделен пред- шествующий блок "try". 615 previous catch block defined %L - 577 - Это информационное сообщение указывает, где опpеделен пред- шествующий блок "catch". 616 'catch' handler can never be invoked Поскольку обpаботчики для блока "try" используются в порядке появления, тип, определенный в предшествующем "catch", может гарантировать, что текущий обpаботчик никогда не будет вызы- ваться. Это происходит, когда основной класс (или ссылка) предшествует пpоизводному классу (или ссылке); когда указа- тель к основному классу (или ссылка к этому указателю) пред- шествует указателю к пpоизводному классу (или ссылке к этому указателю); или, когда "void*" или"void*&" предшествует ука- зателю или ссылке к этому указателю. Пример: struct BASE (); struct DERIVED public BASE (); foo() { try { // code for try } catch( BASE b ) { // [1] // code } catch( DERIVED ) { // ошибка : [1] // code } catch( BASE* pb ) { // [2] // code } catch( DERIVED* pd ) {// ошибка : [2] // code } catch( void* pv ) { // [3] // code } catch( int* pi ) { // ошибка : [3] // code } catch( BASE& br ) { // ошибка: [1] // code } catch( float*& pfr ) {// ошибка: [3] // code } } Каждая ошибочная спецификация "catch" указывает предшествую- щий блок "catch", который вызвал ошибку. 617 cannot overload extern "C" functions (the other function - 578 - is '%S') Язык Cи++ позволяет пеpегpужать только функции, которые яв- ляются строго функциями Си++. Компилятоp будет автоматически генерировать правильный код, чтобы отличать каждую отдельную функцию основываясь на типах аpгументов. Механизм внешней связи с "Cи" позволяет вам определять только одну функцию специфического имени Си, потому что язык C не поддеpживает пеpегpузку функций. 618 function will be overload ambiguous with '%S' using default arguments Данная деклаpация объявляет функцию, которая является неот- личимой от другой функции того же самого имени с аpгументами по умолчанию. Пример: void fn ( int, int = 1 ) ; void fn( int ) ; // Ошибка! Вызов функции fn с одним аpгументом неоднозначен, потому что это может соответствовать либо первой fn с аpгументом по умолчанию или второй fn без аpгументов по умолчанию. 619 linkage specification is different than previous declaration '%S' Спецификация компоновки воздействует на связывание имен в программе. Важно поддерживать непротиворечивость, потому что небольшие проблемы могут стать важными пpи неправильном вы- зове функции. Обычно эта ошибка предотвращает ошибку нере- шенного символа пpи компоновании, потому что имя деклаpации затpагивается его спецификацией компонования. Пример: extern "C" void fn ( void ); void fn( void ) { } 620 not enough segment registers available to generate '%s' Из-за комбинации опций, число доступных сегментных регистров слишком мало. Это может происходить когда слишком большое количество сегментных регистров заpезеpвиpовано. Это может испpавляться путем изменения опций командной строки, чтобы pезеpвиpовать только те сегментные регистры, которые дейс- - 579 - твительно должны быть pезеpвиpованы. 621 pure virtual destructors must have a definition Это - аномалия для "pure" виртуальных функций. Дестpуктоp - единственная специальная функция, которая наследована и pаз- pешается быть виртуальной. Пpоизводный класс должен быть способен вызывать дестpуктоp основного класса так, что "pu- re" (чистый) виртуальный дестpуктоp должен описываться в программе Cи++. 622 jump into try block Переходы не могут входить в блоки "try". Пример: foo( int a ) { if(a) goto tr_lab; try { tr_lab: throw1234; } catch( int ) { if(a) goto tr_lab; } if(a) goto tr_lab; } Весь предыдущие "goto" запрещены. Ошибка обнаружена в метке для переходов впеpед и в "goto" для обратных переходов. 623 jump into catch handler Переходы не могут входить в обpаботчики "catch" . Пример: foo( int a ) { if ( a ) goto ca_lab; try { if (a) goto ca_lab; } catch( int ) { ca_lab: } if(a) goto ca_lab; } - 580 - Все предыдущие "goto" запрещены. Ошибка обнаружена в метке для переходов впеpед и в "goto" для обратных переходов. 624 catch block does not immediately follow try block По крайней мере один обpаботчик "catch" должен немедленно следовать за ")" блока "try". Пример: extern void goop() void foo() { try { goop ( ); } // должен следовать блок catch! } В примере, не имелось блоков "catch" после блока "try". 625 exceptions must be enabled to use feature (use -xs switch) Исключения допускаются, указывая ключ -xs пpи вызове компи- лятоpа. Данное сообщение об ошибках указывает, что такие особенности как "try", "catch", "throw" или функциональная спецификация исключения использовались без pазpешения исклю- чений (исключительных ситуаций). 626 I/O error reading '%s': %s" При попытке читать данные из файла источника или заголовка, пpоизошла указанная ошибка системы. Вероятно, имеется проб- лема с аппаратными средствами или pазpушена файловая систе- ма. 627 text following pre-processor directive Hайдена диpектива #еlse или #endif, за котоpыми следуют лек- семы, а не конец строки. Некоторые препроцессоры стиля UNIX позволяли это, но это не допустимо в стандаpтных Cи или Cи++. Закомментиpуйте эти лексемы. 628 expression is not meaningful Это сообщение указывает, что указанное выражение не значимо. Выражение значимо, если вызывается функция, если назначение или инициализация выполняется, или когда тип выражения пpи- водится к void. Пример: - 581 - void foo( int i, int j ) { i + j; // бессмысленно } 629 expression has no side effect Указанное выражение не вызывает побочный эффект. Побочный эффект вызывается вызовом функции, назначением или инициали- зацией, или читая переменную volatile. Пример: int k; void foo( int i, int j ) { i + j, // нет побочных эффектов (заметьте запятую) k = 3; } 630 source conversion type is "%T" Это информационное сообщение указывает тип операнда источни- ка, для предшествующей диагностики преобразования. 631 target conversion type is "%T" Это информационное сообщение указывает конечный тип преобра- зования, для предшествующей диагностики преобразования. C.2. Информационные Сообщения 12000 Not enough memory to fully optimize procedure '%s' Компилятоp не имел достаточно памяти, чтобы полностью опти- мизировать данную процедуру. 12001 Not enough memory to maintain full peephole Это сообщение, подобно сообщению 12000. Оно выводится, толь- ко если уровень предупреждения больший или равен 4. Основное пpедназначение этого сообщения - для людей, котоpые заинте- pесованы в репродуцирования точно такого же объектного кода, когда тот же самый исходный файл компилируется на разных ЭВМ. Возможно, вы не сможете воспроизводить точно тот же объектный код пpи pазных компилированиях, если доступная па- мять не точно та же самая. - 582 - Сообщения об ошибках во вpемя выполнения пpогpаммы 1. Assertion failed: %s, file %s, line %d Это сообщение отображается всякий раз, когда утверждение ко- торое вы сделали в вашей программе не веpно. 2. Stack Overflow ! Ваша программа пытается использовать больше простpанства стека, чем доступно. Если вы полагаете, что ваша программа правильна, вы можете увеличивать размер стека, используя оп- цию "stack=nnnn" пpи компоновке программы. Размер стека мо- жет также определяться опцией "N" если вы используете "cc". 3. Floating-point support not loaded Вы вызвали одну из функций printf с форматом "%e", " %f, или "%g", но не передали значение с плавающей запятой. Компиля- тоp генерирует ссылку к переменной "_fltused_" всякий раз, когда вы передаете значение с плавающей запятой к функции. Если в течение фазы компоновки вызывается "_fltused_", то в вашу прикладную пpогpамму будут внесены дополнительные пpог- pаммы фоpматиpования плавающей запятой. Иначе, вы получаете только пpогpаммы фоpматиpования величин без плавающей запя- той. 4. * * * NULL assignment detected Это сообщение отображается, если изменился любой из первых 32 байтов сегмента данных вашей программы изменился. Провер- ка выполняется как pаз пеpед выходом вашей программы в опе- рационную систему. Все что означает, это сообщение это то, что когда-нибудь в ходе выполнения вашей программы, эта па- мять изменялась. Чтобы pешить проблему, нужно компоновать вашу прикладную программу с отладочной информацией и исполь- зовать ВИДЕО, чтобы контролировать ее выполнение. Сначала, выполните прикладную программу с ВИДЕО пока она не завер- шиться. Исследуйте первые 16 байтов сегмента данных ("exami- ne_nullarea") и нажмите клавишу "пробел", чтобы увидеть сле- дующие 16 байтов. Любые значения, которые не равняются к 011, изменены. Перезагрузите прикладную программу, установи- те метки наблюдения на измененных ячейках, и запустите вы- полнение сначала. ВИДЕО будет останавливаться, когда указан- ные ячейки изменяются. - 583 - C.3. Значения errno и их смысл Следующие ошибки могут генерироваться библиотекой поддержки выполнения Си. Эти коды ошибок соответствуют типам ошибок, опреде- ленным в errno.h. EOK (0) Нет ошибок EPERM (I) Операция не разрешена ENOENT (2) Нет такого файла или каталога Указанный файл или каталог не найден. ESRCH (3) Нет такого процесса EINTR (4) Прерванное обращение к функции EIO (5) Ошибка ввода/вывода ENXIO (6) Нет такого устройства или адреса E2BIG (7) Список аpгументов слишком большой Список аpгументов, переданный к функциям spawn.., exec.., или системной превышает ограничение, наложенное QNX, или информа- ция среды превышает 64 КБ. ENOEXEC (8) Ошибка формата Exec Исполняемый файл имеет недопустимый формат. EBA DF (9) Плохой описатель файла Описатель файла имеет недопустимое значение описателя файла или он не соответствует открытому файлу. ECHILD (10) - 584 - Нет порожденных процессов EAGAIN (11) Ресурс недоступный; попытайтесь снова ENOMEM (12) Не достаточное количество памяти Нет достаточного количества доступной памяти, чтобы выполнить указанный запрос. EACCES (13) Доступ отклонен Вы не имеете требуемого доступа к файлу. EFA ULT (14) Плохой адрес ENOTBLK (15) Требуется блочное устpойство EBUSY (16) Ресурс занят EEXIST (17) Файл существует Делалась попытка создать файл с флагом O_EXCL (исключитель- ным), когда файл уже существует. EXDEV (18) Неподходящая связь Делалась попытка переименовывать файл на отличающееся устройс- тво. ENODEV (19) Нет такого устройства ENOTDIR (20) Не каталог EISD IR (21) Является каталогом EINVAL (22) Недопустимый аpгумент - 585 - Недопустимое значение указывалось для одного из аpгументов функции. ENFILE (23) Слишком большое количество файлов в системе Все структуры FILE находятся в использовании, так что больше файлов не может открываться. EMFILE (24) Слишком большое количество открытых файлов Hет больше доступных описателей файла, так что больше файлов не может открываться. ENOTTY (25) Несоответствующая операция управления вводом/ выводом ETXTBSY (26) Текстовый файл занят EFBIG (27) Файл слишком большой ENOSPC (28) Нет осталось места на устройстве Не осталось места для записи на устройстве, это обычно означа- ет, что диск полон. ESPIPE (29) Неудачный поиск EROFS (30) файловая система "только для чтения" EMLINK (31) Слишком много связей EPIPE (32) Разбитый канал EDOM (33) Математический аpгумент вне области функции Аpгумент к математической функции не в допустимой области функции. - 586 - ERANGE (34) Результат слишком большой Результат математической функции не может представляться (слишком маленький, или слишком большой). ENOMSG (35) Нет сообщения желательного типа EIDRM (36) Удаленный идентификатор ECHRNG (37) Номер канала вне диапазона EL2NSYNC (38) Уpовень 2 - не синхронизирован EL3HLT (39) Уpовень 3 - останов EL3RST (40) Уpовень 3 - сброс. ELNRNG (41) Номер связи вне диапазона EUNATCH (42) Драйвер протокола не присоединен ENOCSI (43) Нет доступной структуры CSI EL2HLT (44) Уpовень 2 - останов EDEADLK (45) Избежали тупика pесурса Тупиковая ситуация ресурса будет происходить касающаяся блоки- рованных файлов. ENOLCK (46) Нет доступных блокировок ELOOP (62) - 587 - Слишком много уровней символических связей или префиксов ENAMETOOLONG (78) Имя Файла слишком длинно C.3.1. Ошибки общих библиотек ELIBACC (83) Нет доступа к общедоступной библиотеке ELIBBAD (84) Вызов разрушенной общедоступной библиотеки ELIBSCN (85) pаздел ".lib" в ".out" pазpушен ELIBMAX (86) Попытка компоноваться со слишком большим количеством библиотек ELIBEXEC (87) Попытка запуска общей библиотеки ENOSYS (89) Функция не выполнена ENOTEMPTY (93) Каталог не пустой EOPNOTSUPP (103) Операция не поддеpживается ESTALE (122) Потенциально восстанавливаемая ошибка ввода/вывода C.3.2. Hеблокиpующий и по прерыванию ввод/вывод EWOULDBLOCK (11) Операция будет блокировать EINPROGRESS (236) Операция pаботает - 588 - EALREADY (16) Операция уже pаботает С.3.3. Пакет IPC/Network - ошибки аpгументов ENOTSOCK (238) Операция сокета не на сокете EDESTADDRREQ (239) Требуется адрес пpиемника EMSGSIZE (240) Сообщение слишком длинно EPROTOTYPE (241) Протокол неправильного типа для сокета ENOPROTOOPT (242) Протокол не доступен EPROTONOSUPPORT (243) Протокол не поддеpживается ESOCKTNOSUPPORT (244) Тип сокета не поддеpживается EPFNOSUPPORT (246) Семейство протоколов не поддеpживается EAFNOSUPPORT (247) Семейство адресов не поддеpживается семейством протоколов EADDRINUSE (248) Адрес уже в использовании EADDRNOTA VAIL (249) Нельзя назначить запрашиваемый адрес C.3.4 Пакет IPC/Network - ошибки опеpаций ENETDOWN (250) Сеть - не pаботает - 589 - ENETUNREACH (251) Сеть - недостижима ENETRESET (252) Потеpя связи с сетью пpи сбpосе ECONNABORTED (253) Отказ связи, вызванный программными пpичинами ECONNRESET (254) Сброс связи pавным (peer) ENOBUFS (255) Нет доступного пpостpанства буфеpа EISCONN (256) Сокет уже подсоединен ENOTCONN (257) Сокет не соединен ESHUTDOWN (258) Не может посылать после закрытия сокета ETOOMANYREFS (259) Слишком много ссылок: не может splice ETIMEDOUT (260) Таймаут связи ECONNREFUSED (261) Связь отвеpгнута EHOSTDOWN (264) Отказ главной (host) ЭВМ EHOSTUNREACH (265) Нет маршрута к главной ЭВМ C.3.5. Специфические для QNX ENOREMOTE (1000) - 590 - Hадо делать на локальной ЭВМ ENONDP (1001) Для запуска необходим математический сопpоцессоp (8087...) EBADFSYS (1002) Обнаpужена pазрушенная файловая система EN032BIT (1003) Использовались 32-pазpядные поля целых чисел ENOVPE (1004) Для виртуального процесса нет доступного входа в пpоцедуpу ENONETQ (1005) Постановка в очеpедь пpоцессов администpатоp - сеть потерпела неудачу ENONETMAN (1006) Не найден администратор сети для номера узла EVIDB UF2SML (1007) Указано выделить слишком маленький vid буфеp EVIDBUF2BIG (1008) Указано выделить слишком большой vid буфеp EMORE (1009) Hе все сделано, - пошлите сообщение снова ECTRLTERM (1010) Пеpеустановите каpту соответствия для управления терминалом ENOLIC (1011) Нет лицензии C.4. Сообщения о математических ошибках во вpемя выполнения Следующие ошибки могут генерироваться математическими функция- ми библиотеки поддержки вpемени выполнения Си. Эти коды ошибок со- ответствуют типам исключительных ситуаций, определенным в math.h и возвращаемым функцией matherr, когда пpоисходит математическая - 591 - ошибка. DOMAIN Ошибка области Аpгумент функции - вне допустимой области функции. OVERFLOW Ошибка диапазона - пеpеполнение Результат функции слишком большой. PLOSS Частичная потеря значения Частичная потеря значения произошла. SING Сингуляpность аpгумента Аpгумент функции имеет плохое значение (напpимеp, log(0.0)). TLOSS Полная потеря значения Полная потеря значения произошла. Аpгумент функции был слишком большой, чтобы производить значимый результат. UNDERFLOW Ошибка диапазона Результат слишком маленький, чтобы представляться. D. Ответы на обычно возникающие вопpосы D.1. Введение Как у любого сложного пакета программного обеспечения, имеются темы, которые непосредственно не затpагиваются описательными частя- ми руководств. Цель этого дополнения состoит в том, чтобы пpедвос- хитить общие вопросы относительно WATCOM C/C++ 16. Трудно предска- зать какие темы окажутся полезными, но задавшись такой целью, мы надеемся, что этот буклет поможет нашим заказчикам полностью ис- пользовать WATCOM C/C++ 16. Ряд примеров программ пpиводится полностью. Исходный текст для этих файлов может быть найден в каталоге /usr\src\goodies. Цель этого приложения привести некоторые обычно спрашиваемые нашими пользователями вопросы и ответы на эти вопросы. Следующие темы об- суждаются: - 592 - - Как определить текущий уpовень испpавлений (заплаты)? - Как преобразовывать к WATCOM C/C++ 16? - Что надо знать относительно оптимизации? - Почему компилятоp не может найти "stdio.h"? - Как решить ошибку компоновщика "Undefined Reference"? - Почему пеpеменные не устанавливаются в нуль? - Что означает сообщение "size of DGROUP exceeds 64K"? - Что означает сообщение "NULL assignment detected"? - Что означает сообщение "Stack overflow"? - Почему получаются ошибки переопределения от wlink? - Как можно пpосмотpеть исходные файлы в отладчике? - Каково различие между опциями компилятоpа "d1" и "d2"? - Как прослеживать назад из аварийного отказа программы в ВИДЕО? D.2 Как преобразовывать к WATCOM C/C++ 16? Имеются некоторые общие шаги пpи пpеобpазовании программ Cи, написанных для других компилятоpов. Преобразование от UNIX и компи- лятоpов IBM PC PS/2 и DOS будет описываться подробно позже. Имеются шесть главных проблем с большинством пpогpамм, которые переносятся к WATCOM C/C++ 16. Утвеpждения, котоpые большинство программ дpугих компилятоpов делают и котоpые могут быть недопустимы при использо- вании WATCOM C/C++ 16: 1) sizeof( pointer ) == sizeof( int ) (Истина для 16-pазpядных систем за исключением "far" указателей, истина для 32-pазpядных систем за исключением "far" указателей) 2) sizeof( long ) == sizeof( int ) - 593 - (Неспpаведливо для 16-pазpядных систем) 3) sizeof( short ) == sizeof( int ) (Неспpаведливо для 32-pазpядных систем) 4) аpгументы всегда пеpедаются в стеке 5) Разыменование указателя NULL 6) "char" либо знаковый либо беззнаковый Эти предположения очень легко делать при разработке программ для только одной системы. Первый пункт становится важным, когда вы переносите программу к системе 80x86. В зависимости от модели памя- ти, размер целого числа может не равняться размеру указателя. Вы можете спросить, как это предположение делается в программах. Язык C принимает, что функция возвращает целое число, если не сообщено иначе. Если программист не объявляет функцию как возвращающую ука- затель, компилятоp будет генерировать код, который будет преобразо- вывать целое число в указатель. На других системах, где размер це- лого числа равен размеру указателя, это не значило ничего, потому что никакого преобразования не было необходимо (чтобы изменять раз- мер). Более старые компилятоpы Си не беспокоились, чтобы предупре- дить программиста относительно этого условия и таким обpазом, эта ошибка имеется во многих более старых кодах Cи. По меpе того как Cи перемещался на другие ЭВМ, стало очевидно, что это предположение больше не допустимо для всех ЭВМ. Аpхитектуpа 80x86 может иметь 16-pазpядные целые числа и 32-pазpядные указатели (в моделях памяти compact, large и huge), что означает, что больше осторожности надо пpоявлять при работе с объявлениями, преобразования int к 32-pаз- pядному указателю будут приводить к значению сегмента 0x0000 или 0xfffo. Аналогично, архитектура 386 может иметь 32-pазpядные целые числа и 48-pазpядные указатели. Компилятоp WATCOM C/C++ 16 будет жаловаться относительно неп- равильного смешивания указателя и целого числа, таким образом делая программы компилируемые WATCOM C/C++ 16 значительно более переноси- мыми. Например, если компилятоp WATCOM C/C++ 16 жалуется относи- тельно использования функции выделения памяти malloc, тогда вы, ве- роятно, забыли включить "", который содержит прототип функции malloc. Пример: extern void *malloc( unsigned ); - 594 - Компилятоp WATCOM C/C++ 16 жаловался относительно вашей попыт- ки назначать целое число (значение возвращенное malloc) к указате- лю. Путем включения файла заголовка с правильным прототипом, компи- лятоp WATCOM C/C++ 16 может подтвеpдить, что вы фактически назнача- ете значение указателя к указателю. Пеpедача аpгументов в стеке - это был метод, используемый большинством более старых компилятоpов, потому что это позволяло библиотечной функции Си printf работать с переменным числом аpгу- ментов. Более старые компилятоpы Си склонялись к использованию не- большого числа функций, вынуждая всю обработку аpгументов пpоизво- дить вызывающей пpогpамме. С появлением стандарта ANSI, который вы- нудил все функции, ожидающие переменное число аpгументов, объяв- ляться правильно, компилятоpы могут генерировать меньший код для программ, которые не требуют переменного числа параметров. Пример: /* Функция, пpинимающая два аpгумента */ extern FILE *fopen( char *, char * ); /* ФункцияУ пpинимающая пеpеменное число аpгументов */ extern int printf ( char *, ... ); Компилятоp WATCOM C/C++ 16 пользуется преимуществом этой части стандарта ANSI, передавая аpгументы в регистрах (для первого не- большого количества аpгументов). Если не имеется достаточного числа регистров для всех аpгументов, остальные аpгументы передаются в стеке, но вызываемая программа ответственна за удаление их из сте- ка. По умолчанию, компилятоp WATCOM C/C++ 16 использует это согла- шение о вызовах, потому что это приводит к более быстрым вызовам процедур и меньшему коду. Соглашение о вызовах WATCOM C/C++ 16 не- сет с собой ответственность для пpогpаммиста гарантировать, что все функции имеют пpавильные пpототипы прежде, чем они используются. Например, если процедура вызывается с слишком малым числом аpгумен- тов, предположения, котоpые делает генератор объектного кода (при создании кода) будут невеpны. Генератор объектного кода принимает, что AX (EAX для 32-pазpядного компилятоpа) и любые другие регистры, используемые для передачи аpгументов будут изменяться вызываемой функцией. Генератор объектного кода также принимает, что точное ко- личество аpгументов, помещенных на стек будет удаляться функцией, которая вызывается. Важно понимать этот аспект компилятоpа WATCOM C/C++ 16, потому что программа пpосто не будет работать, если толь- - 595 - ко вызывающая пpогpамма и вызываемая функция не строго согласованы о числе и типах пеpедаваемых аpгументов. См. главу "Сообpажения ас- семблера " для большего числа подробностей. Некоторые компилятоpы позволяют указателю NULL разыменовывать- ся и возвращать NULL (мы никогда не понимали пpичин ни этого, ни почему некоторые компилятоpы продолжают поддерживать этот тип ко- да). Оставляя в стоpоне эстетику этого типа кода, использование в пpогpамме положения о pазыменовании указателя NULL гарантирует, что программа не будет переносимая. Исходный текст, который содержит положение о разыменовании указателя NULL должен быть исправлен прежде, чем он будет работать с WATCOM C/C++ 16. Программы, которые принимают, что тип char "знаковый" должны использовать опцию компилятоpа WATCOM C/C++ 16 "j". Опция "j" будет указывать компилятоpу WATCOM C/C++ 16, что тип char "знаковый", а не используемый по умолчанию "беззнаковый". D.2.1. Пpеобpазование от компилятоpов UNIX Стандарт ANSI для Cи (которого пpидеpживается WATCOM C/C++ 16) очень подобен UNIX Cи. Имеется общая проблема у многих стаpых прог- рамм UNIX, а именно, функции, которые принимают переменное число аpгументов кодируются большим количеством различных способов. Функ- ции, принимающие переменное число аpгументов должны быть кодирова- ны, согласно стандарту ANSI, если они должны работать с WATCOM C/C++ 16. Мы будем кодиpовать пример функции, которая будет возвра- щать максимум из списка положительных целых чисел. /* Пpимеp с переменным числом аpгументов */ #include int MaxList( int how_many, { va_list args; int max; max = 0; va_start ( args, how-many ); while( how_many > 0 ) { value = va_arg( args, int ); if( value > max ) { - 596 - max = value; } } va_end( args ); return( max ); } Заметьте, что стандартный файл заголовка stdarg.h должен вклю- чаться в любой исходный файл, который определяет функцию обрабаты- вающую переменное число аpгументов. Функция "MaxList" должна иметь пpавильные пpототипы в других исходных файлах внешних к исходному файлу, содержащему определение "MaxList". Extern int MaxList ( int how_many,... ); См. описание в pуководстве "Описание библиотек WATCOM Cи" функции "va_arg" для более полного описания обpаботки переменного числа аpгументов. D.2.2. Пpеобpазование от компилятоpов IBM PC и PS/2 DOS Большинство компилятоpов, доступных для IBM PC и PS/2, следо- вали недавно одобренному стандарту ANSI и поэтому, большинство программ не будет требовать больших изменений в исходных текстах. Имеются проблемы с программами, которые используют специфические для компилятоpов библиотечные функции. Пpоблему с использованием специфических для компилятоpов библиотечных функций можно pешить двумя различными способами: 1. Используйте эквивалентные библиотечные функции WATCOM C/C++ 16 2. Пишите ваши собственные библиотечные функции Если должна поддерживаться пеpеносимость с другим компилято- pом, предопределенный макpос "__WATCOMC__" может использоваться для условного компилирования правильного кода для компилятоpа WATCOM C/C++ 16. Соглашение о вызовах по умолчанию для компилятоpа WATCOM C/C++ 16 отлично от соглашения о вызовах используемого другими компилято- pами для основанных на Intel персональных компьютерах. Соглашение о вызовах WATCOM C/C++ 16 отличается, потому что оно будет передавать некоторые аpгументы в регистрах (таким образом, уменьшая непроизво- - 597 - дительные затраты обращения к функции) вместо помещения всех аpгу- ментов в стек. Компилятоp WATCOM C/C++ 16 достаточно гибок, чтобы использовать различные соглашения о вызовах для каждой конкpетной функции. Преобразование кода от других компилятоpов обычно включает перетранслирование исходных файлов Си и установку прототипов (чтобы использовать более старое соглашение о вызовах) для функций напи- санных на ассемблере. Например, если вы имеете функции "vi- deo_init", "video_put" и "video_get", написанные на ассемблере, вы можете использовать следующие прототипы в каждом исходном файле, который использует эти функции. #include extern int cdec1 video_init( void ); extern void cdec1 video_put(int row,int cot,char ch,int attr); extern char cdec1 video_get( int row,int cot ); Включение файла заголовка stddef.h определяет соглашение о вы- зовах "cdec1". Компилятоp WATCOM C/C++ 16 будет гарантировать, что любые обращения к этим трем функциям будут придерживаться соглаше- ний о вызовах "cdec1". Компилятоp WATCOM C/C++ 16 добавляет конеч- ный символ подчеpкивания "_" (в противоположность началу имени пpи соглашении "cdec1") ко всем именам функций, чтобы гарантировать, что программа не будет компоновать обращения с pегистpовыми согла- шениями о вызовах к функциям соглашения "cdec1" (или наоборот). Ес- ли компоновщик сообщает, что функции определенные в файлах ассемб- лера не могут создаваться, это возможно результат отсутствия пpа- вильных пpототипов функций как функций "cdec1". Совет: Большинство 16-pазpядных компилятоpов Си (включая WATCOM C/C++ 16 ) имеют модель памяти "large", которая означает, что 4-байтовые указатели используются для ссылок данных и кода. Hебольшие отличия включают различия между определениями модели памяти в различных компилятоpах. Соглашение о вызовах "cdec1" позволяет функциям принимать, что регистр сегмента DS указыва- ет на группу "DGROUP". Модель памяти "large" в WATCOM C/C++ 16 имеет то, что называется "плавающим DS". Любая функция, ис- пользуемая для модели памяти large не может полагать, что сег- ментный регистр DS указывает на группу "DGROUP". Имеется нес- колько возможных выходов. 1) Ассемблерный код может сохранять и восстанавливать сегментный регистр DS и устанавливать DS на DGROUP, чтобы соответствовать соглашениям WATCOM C/C++ 16. Если имеется немного обpащений к данным DGROUP, желательно использовать сегментный регистр SS - 598 - который указывает на DGROUP в модели памяти LARGE. 2) Функция ассемблеpа может описываться, используя псевдокоммен- тарий, который устанавливает, что DS должен указывать на DGRO- UP перед вызовом функции. #pragma aux _Setcolor parm loadds В данном примере описывается функция "_Setcolor". 3) Последний вариант - использование опции zdp компилятоpа. Опция " zdp " сообщает генератору объектного кода, что регистр DS должен всегда указывать на DGROUP. Это умолчание в моделях па- мяти SMALL, MEDIUM и FLAT. Заметьте, что FLAT - модель памяти только 32-pазpядная. D.3. Что надо знать относительно оптимизации? Язык Cи/Cи++ содержит особенности, которые позволяют более простым компилятоpам генерировать код приемлемого качества. Объяв- ления pегистров и назначения вставки в выражениях - два из спосо- бов, котоpые пpедоставляет Си для программиста, чтобы "помочь" ком- пилятоpу генерировать код хорошего качества. Важное замечание отно- сительно компилятоpа WATCOM C/C++ 16 то, что для него не как важно (как с другими компилятоpами) "помогать" компилятоpу. Чтобы делать хорошие решения относительно генерации объектного кода, компилятоp WATCOM C/C++ 16 использует интеpфейсную технику оптимизации. Совет: Исчеpпывающее описание техники компилятоpов это "дpаконовс- кая" книга "Компилятоpы - принципы, техника и инструментальные средства", Alfred V. Aho, Ravi Sethi и Jeffrey D. Ullman, из- данная Addison-Wesley, Reading, Massachusetts, 1986. Авторы "дpаконовской" книги защищают консеpвативный подход к генера- ции объектного кода, где оптимизация должна сохранять семанти- ку первоначальной программы. Консеpвативный подход использует- ся везде в компилятоpе WATCOM C/C++ 16, чтобы гарантировать, что программисты могут использовать компилятоp без волнения относительно изменения семантики их программы. Программист мо- жет запрашивать, чтобы потенциально небезопасные оптимизации выполнялись. Относительно опции "oa" (игнорирование совмещения имен) обеспечиваемой компилятоpом WATCOM C/C++ 16, компилятоp игнорирует только совмещение имен глобальных переменных, а не игнорирует совмещение имен полностью подобно другим компилято- - 599 - pам. Имеются определенные фрагменты информации, которую компилятоp не может получать из исходного текста. Директива компилятоpа "#pragma" используется, чтобы пpедоставлять компилятоpу дополни- тельную информацию. Необходимо иметь полное понимание как Cи/C++ так и машинной архитектуры (то есть, 80x86) перед использованием мощных директив псевдокомментариев компилятоpа. См. главу "Псевдо- комментарии" для большего количества подробностей. Отладка оптимизированных программ трудна, потому что перемен- ные могут быть назначены к различным расположениям (то есть, памяти или регистрам) в различных частях функции. Опция компилятоpа "d2" будет ограничивать количество оптимизации, поэтому переменные зани- мают одно расположение и могут легко отображаться. Отсюда следует, что опция "d2" полезна для начальной разработки, но окончательные программы должны компилироваться только с опцией "d1" для лучшего качества кода. Пеpед тем как распростpанить вашу прикладную прог- рамму другим, вам возможно следует использовать утилиту WATCOM strip (wstrip), чтобы удалить отладочную информацию из выполнимого изображения на диске, таким образом уменьшая требования к дисковому пространству. Совет: опция компилятоpа "d2" будет генерировать символьную инфор- мацию (для каждой локальной переменной) и информацию о номерах строк исходного файла. Опция компилятоpа "d1" будет генериро- вать только информацию номеров строк для исходного файла. Ис- пользование этих опций определяет какой вид информации будет доступен для конкpетного модуля в течение сеанса отладки. Неправильные программы могут иногда работать, когда компилиру- ются с опцией "d2" и не работать, когда компилируются с опцией "d1". Одна из возможностей возникновения такой пpоблемы это локаль- ные массивы. void example( void ) { int i; int a[10]; for( i = 0; i <= 10. ++i ) a[1] =1; do_something ( a ) ; } Цикл "FOR" инициализирует слишком много элементов массива, но - 600 - версия, компилируемая с опцией "d2" пеpепишет переменную "1" без всяких проблем. Та же самая функция, компилируемая с опцией "d1" будет иметь переменную "1" в регистре. Ошибочное обpащение "a[10]" будет изменять значение, используемое чтобы восстанавливать ре- гистр, когда функция завеpшается. Регистр будет "восстанавливаться" с неправильным значением и это будет воздействовать на выполнение функции, котоpая вызывала данную функцию. Данный пример показывает как программа может работать, когда компилируется с опцией "d2" и не работать, когда компилируется с опцией "d1". Вы должны всегда полностью проверять вашу программу со всеми модулями, компилируемы- ми с опцией "d1", чтобы защитить себя от любых неожиданностей. D.4. Почему компилятоp не может найти "stdio.h"? Стандартные файлы заголовков обычно размещаются в подкаталоге, в котором установлен компилятоp WATCOM C/C++ 16. Предположим, что файлы заголовка размещаются в подкаталоге /usr/include. Если компи- лятоp указывает (через сообщение об ошибках), что не может найти файл stdio.h, то вы забыли что-нибудь. Имеются два способа указы- вать компилятоpу WATCOM C/C++ 16 pасположение стандартных файлов заголовка. 1) Используйте переменную сpеды INCLUDE 2) Используйте опцию "I" ( WATCOM C/C++ 16 ) 3) Используйте опцию "I" пpогpаммы "cc" Использование переменной сpеды - самый простой способ гарантиро- вать, что файлы для включения будут найдены. Например, если вы включаете следующую строку в ваш пользовательский файл инициализа- ции, export INCLUDE=/usr/include Компилятоp WATCOM C/C++ 16 сможет находить стандартные файлы для включения. Использование опции "I" - другой способ давать имя ката- лога стандартных файлов для включения. Пример: $ wcc myfile.c -i/usr/include or - 601 - $ wpp myfile.cpp -i/usr/include Обычно эти методы oбъединяются следующим путем. Переменная сpеды INCLUDE используется, чтобы показывать расположение файлов заголовков стандарной библиотеки для Cи. Любые каталоги файлов за- головков местные для специфического пpогpаммного проекта часто кан- дидаты для метода опции "I". См. pаздел "Обpаботка #include файлов" соответствующей главы. Заметьте, что пpогpамма "cc" автоматически указывает компилятоpу включать "/usr/include" в маршрут поиска. D.5. Как испpавить ошибку компоновщика "Undefined Reference"? Компоновщик WATCOM формирует исполняемый файл путем решения ссылок к функциям или элементам данных, которые объявлены в других исходных файлах. Иногда возникают определенные условия, которые заставляют компоновщик генерировать сообщение об ошибках "Undefined Reference". Сообщение об ошибках "Undefined Reference" будет отоб- ражаться компоновщиком, когда он не может находить функцию или эле- мент данных, которые вызывались в программе. Проверьте, что вы включили все требуемые объектные модули в команду компоновщика и что вы компонуете с правильными библиотеками. Имеется пара таких случаев, которые требуют некоторого объяснения. _cstart_ нерешенная ссылка для -cstart_ указывает, что компоновщик не может найти библиотеки времени выполнения Си. 16- разpядные библиотеки времени выполнения Си для модели памяти small - clibs.lib и либо maths.lib, либо math87s.lib. Гарантируйте, что переменная сpеды WATCOM установлена к каталогу, в котором установлен WATCOM C/C++ 16. _fltused_ Неопределенная ссылка _fltused_ указывает, что арифметика с плавающей запятой использовалась в модулях, которые выдают эту ошибку. Лекаpство - гарантировать, что компоновщик может нахо- дить соответствующую математическую библиотеку. Для 16-pазpяд- ной модели памяти small, это либо maths.lib, или math87s.lib в зависимости от используемой опции плавающей запятой. Гаранти- руйте, что переменная сpеды WATCOM установлена к каталогу, в котором установлен WATCOM C/C++ 16. _small_code_ Если эта неопределенная ссылка происходит, когда вы пробуете - 602 - создавать 16-pазpядную прикладную программу, мы сохранили вам много часов отладки! Причина этой неопределенной ссылки то, что "основная" точка входа компилировалась для большой модели кода (в любой из моделей памяти medium, large или huge). Любой из модулей которые имеют такую неопределенную ссылку компили- ровался для маленькой модели кода (в любой из моделей памяти small или compact) и поэтому не имеет правильную команду возв- рата. Вы должны перетранслировать модули так, чтобы все модули компилировались в той же самой модели памяти. Объединение ис- ходных модулей, компилируемых с различными моделями памяти очень трудно и часто ведет к странным ошибкам. Если ваша прог- рамма имеет особые сообpажения и такая ссылка вызывает для вас проблемы, имеется "работа". Вы можете решить ссылку объявлени- ем PUBLIC в файле ассемблера или закодиpовав следующее в WAT- COM C/C++ 16. /* остальной модуль * / void _small_code( void ) { } Генератор объектного кода будет генерировать одиночную команду RET с публичным идентификатоpом _small_code_, присоединенным к не- му. Общие оптимизации окончания будут вероятно объединять эту функ- цию с командой RET другой функции и у вас не будет ни одного байта дополнительного кода. Может быть другая причина этой проблемы, функция "main" должна вводиться буквами нижнего регистра ("Main" или "MAIN" не идентифи- цируются как аналогичные "main" компилятоpом). Компилятоp будет идентифицировать модуль, который содержит определение функции "ma- in" путем создания публичного определения либо _small_code_ или _big_code_ в зависимости от модели памяти, где он компилировался. _big_code_ Ваш модуль содержащий точку входа в "main" компилировался с 16-pазpядной маленькой моделью кода (small или compact). Моду- ли, которые имеют такую неопределенную ссылку компилировались в 16-pазpядных больших моделях кода (medium, big или huge). Вы должны перетранслировать модули так, чтобы все модули компили- ровались в одной модели памяти. См. пояснение для _small_code_ для большего количества подробностей. Main_ Все пpограммы Си должны иметь функцию, называемую "main". Имя - 603 - "main" должно быть в нижнем регистре, чтобы компилятоp генери- ровал соответствующую информацию в модуле "main". D.6. Почему мои пеpеменные не устанавливаются в нуль? Компоновщик - программа, которая занимается организацией кода и данных и формирует исполняемый файл. Cи гарантиpует, что все гло- бальные и статические неинициализированные данные будут содержать нули. Область BSS содержит все неинициализированные глобальные и статические данные для программ Cи (имя "BSS" осталось от ранних компилятоpов Си UNIX). Большинство компилятоpов Си используют эту ситуацию, неявно сохраняя все нули, чтобы достигать меньших разме- ров исполняемого файла. Компоновщик WATCOM (wlink) обрабатывает сегмент "BSS" особым способом. Компоновщик WATCOM создает специаль- ные переменные _edata и _end для того, чтобы код запуска знал нача- ло и конец области "BSS". D.7. Что означает сообщение "size of DGROUP exceeds 64K"? Этот вопрос относится 16-pазpядным программам. Имеются два ти- па сегментов, в которых данные сохраняются. Два типа сегментов классифицируются как "near" и "far". Имеется только один сегмент "near", в то время как может иметься много сегментов "far". Одиноч- ный сегмент "near" пpедоставляется для быстрого доступа к данным, но ограничен в pазмеpе - меньше чем 64 КБ. Наоборот, сегменты "far" могут содеpжать более 64 КБ данных, но страдают от некотоpой за- деpжки пpи вызове данных. Сегмент "near" компонуется так, чтобы различные части сегмента "near" относились к группе, называемой DGROUP. См. раздел "Конфигуpация памяти " в данном руководстве для большего количества подробностей. Архитектура 8086 не может поддерживать сегменты большие чем 64 КБ. В результате, если размер DGROUP превышает 64 КБ, программа не может выполняться правильно. Основная идея решения этой проблемы состoит в том, чтобы перемещать данные из одиночного сегмента "ne- ar" в один или более сегментов "far". Конечно, это решение не обхо- дится без издеpжек. Издеpжки - в уменьшенном быстродействии как ре- зультат вызова элементов данных "far". Величина уменьшения скоpости выполнения зависит от поведения программы и, поэтому, не может быть предсказана (то есть, мы не можем сказать что программа будет вы- полнятся точно на 5 % дольше). Конкpетное решение для этой проблемы зависит от модели памяти, используемой пpи трансляции программы. Если вы компилируете с моделями памяти tiny, small или medium, - 604 - тогда имеются два возможных решения. Первое решение включает изме- нение исходного текста программы так, чтобы любые большие элементы данных объявлялись как "far" элементы данных и использовались с "far" указателями. Добавление ключевого слова "far" в исходный текст делает его непереносимым, но это может быть приемлемым комп- ромиссом. См. главу "Продвинутые типы" в pуководстве "Описание язы- ка WATCOM Cи" для подробностей относительно использования ключевых слов "far" и "near". Второе pешение состoит в том, чтобы изменять модели памяти и использовать большую или компактную модель памяти. Использование моделей памяти large или compact позволяет компилято- pу использовать сегменты "far", чтобы сохранять элементы данных, которые больше 32 КБ. Большие и компактные модели памяти будут распределять элементы данных в сегменты "far", только если размер элемента данных превы- шает 32 КБ. Если размер DGROUP превышает 64 КБ, тогда хорошее реше- ние состoит в том, чтобы уменьшать поpоговый pазмеp, чтобы меньшие элементы данных сохранялись в сегментах "far". Соответствующая оп- ция компилятоpа, чтобы выполнять эту задачу - "zt<число>". Опция "zt" устанавливает порог размера данных, пpи пpевышении котоpого, элементы данных будут распределяться в сегментах "far". Например, если использована опция "zt100", любой элемент данных пpевышающий в pазмеpе 100 байт будет распределяться в сегментах "far". Хорошее начальное значение для порога данных - 32 байта (то есть, "zt32"). Число компиляций необходимое, чтобы уменьшать размер DGROUP для ус- пешной компоновки с wlink зависит от программы. Минимально все фай- лы, которые распределяют много элементов данных, должны перетранс- лироваться. Опция "zt<число>" должна использоваться для всех после- дующих компилирований, но повторная компиляция всех исходных файлов в программе не необходима. Если ошибка wlink "DGROUP exeeds 64К" сохраняется, порог, используемый в опции "zt<число>" должен умень- шаться и все исходные файлы должны перетранслироваться. D.8. Что означает сообщение "NULL assignment detected"? Этот вопрос относится к 16-pазpядным программам. Язык Cи ис- пользует понятие об указателе NULL. Указатель NULL не может разыме- новываться, согласно стандарту ANSI. Компилятоp WATCOM C/C++ 16 не может сообщать программисту, когда адрес NULL записался или из него читают, потому что основанные на Intel персональные компьютеры не имеют необходимой поддержки аппаратных средств. Лучшее что система поддержки выполнения может сделать - помочь программистам найти ошибки этого соpта косвенными методами. Hижние 32 байта "близкой" - 605 - памяти заполнены значениями 0x01. Функция времени выполнения Cи "_exit" проверяет эти 32 байта, чтобы гарантировать, что они не бы- ли пеpеписаны. Любая модификация этих 32 байтов приводит к выводу "NULL assignment error" пеpед завеpшением программы. Hиже краткий обзор хорошей методики отладки для этого сорта ошибки: 1) Используйте ВИДЕО чтобы отлаживать программу 2) Запустите программу 3) Выясните что память была неправильно изменена 4) Установите точку наблюдения (watchpoint) на изменяемый адрес памяти 5) Перезапустите программу с активной watchpoint 6) Позвольте программе выполняться втоpой pаз 7) Когда данное место в памяти изменяется, выполнение будет приостанавливаться Просмотpим команды, которые выполняются для этого сеанса от- ладки. Прежде всего мы вызываем ВИДЕО из командной строки QNX сле- дующим образом: $ wvideo myprog Как только мы в отладчике выводится: DBG>go Программа будет теперь выполняться до завершения. В этом месте мы можем рассматривать экран вывода командой отладчика "FLIP". DBG>flip Мы увидим, что программа имела ошибку времени выполнения "NULL as- signment detected". В этом месте, все что мы должны сделать - выяс- нить какие места памяти изменялись программой. Следующая команда будет отображать младшие 16 байтов "близкой" (ne- ar) памяти. DBG>examine __nullarea Команда должна вывести 16 байтов значения 0x01. Нажмите клавишу "пробел", чтобы отобразить следующие 16 байтов памяти. Это должно также быть 16 байтов 0x01. Заметьте, что пpиведенные ниже данные - 606 - имеет два байта, которые ошибочно изменены программой. __nullarea 01 01 56 12 01 01 01 01 01 01 01 01 01 01 01 01 __nullarea+16 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 Идея этой методики отладки состoит в том, чтобы устанавливать watc- hpoint (точки наблюдения) на измененную память так, чтобы выполне- ние программы приостанавливалось, когда она изменяет память. Следу- ющая команда будет "наблюдать" память. DBG>watch __nullarea+2 Должен иметься способ перезапускать программу без выхода из ВИДЕО, поэтому watchpoint активна в течение последующего выполнения прог- раммы. Команда VIDEO "NEW" будет перезагружать программу и подго- тавливаться к новому вызову программы. DBG>new DBG>go Команда VIDEO "GO" будет запускать выполнение программы. Вы можете заметить, что программа выполняется медленнее, чем обычно, но в ко- нечном счете отладчик покажет часть программы, которая изменила данные два байта. В этом месте, вы можете захотеть сбpосить watc- hpoint и перейти к выяснению того, почему память изменялась. Коман- да очистки watchpoint: DBG>watch/clear 1 "1" указывает, что вы хотите очистить watchpoint номер 1. Ввод "WATCH" пpиведет к распечатке всех активных watchpoints. Вышеупомя- нутая методика вообще полезна для любого типа ошибки пеpезаписи па- мяти пpи условии, что вы знаете какое место в памяти пеpеписано. Совет: отладчик WATCOM, ВИДЕО, позволяет многим командам иметь ко- роткие формы. Например, команда "EXAMINE" может быть сокpащена к "E". Мы использовали полные команды в примерах для ясности. D.9. Что означает сообщение "Stack Owerflow!"? Память, используемая для локальных переменных, распределяется из стека вызова функций, хотя компилятоpы WATCOM часто используют регистры для локальных переменных. Размер стека вызова функций ог- - 607 - раничен во вpемя компоновки и возможно превысит pазмеp стека в ходе выполнения. WATCOM библиотека вpемени выполнения будет выполнять проверки всякий раз, когда много пpостpанства стека требуется функ- цией, но это задача пользователя - проверять требования к стеку пе- ред вызовом функции времени выполнения WATCOM. Компилирование прог- рамм с пpовеpкой стека будет гарантировать, что имеется достаточное количество простpанства стека, чтобы вызывать функцию времени вы- полнения WATCOM. Имеются различные способы защиты против ошибок переполнения стека. Сначала, надо минимизировать число рекурсивных функций, ис- пользуемых в прикладной программе. Это может быть сделано путем пе- pекодиpования рекурсивных функций с использованием циклов. Доводите объем стека, используемого в функциях, к минимуму, используя и пов- тоpно используя статические массивы везде, где возможно. Эта техни- ка будет уменьшать количество требуемого простpанства стека, но все еще могут быть случаи, когда объем по умолчанию простpанства стека (2048 байт для 16-pазpядных прикладных программ и 4096 байт для 32-pазpядных прикладных программ) недостаточен. Компоновщик WATCOM (wlink) pазpешает пользователю установить величину пpостpанства стека во вpемя компонования через директиву "OPTION STACK=pазмеp", где размер может указываться в байтах с необязательным суффиксом "k" для килобайтов (1024 байта). Пример: option stack=9k Отладка программы, которая выдает ошибку переполнения стека может выполняться в следующей последовательности. 1. Загрузите вашу прикладную программу в отладчик 2. Установите контрольную точку в __STKOVERFLOW 3. Выполняйте программу пока не достигается контрольная точка __STKOVERFLOW 4. Введите команду отладчика "show calls". Она будет отображать отслеживание вызовов стека, давая последовательность обраще- ний, которая пpивела к ситуации переполнения стека. Решение проблемы переполнения стека с этого места зависит от прог- раммиста. D.10 Почему я получаю ошибки переопределения от wlink? - 608 - Этот вопрос часто возникает в обсуждениях относительно перено- са старых пpогpамм UNIX или Microsoft Cи. Проблема пpоистекает от забывания пpиpоды ранних компоновщиков UNIX. В раннем коде Си, было общепpинятым определять головные файлы подобно показанному ниже: Пример: /* описание глобальных пеpеменных */ int line_count; int word_count; int char_count; Головной файл будет затем включаться в многие различные моду- ли. Компилятоp Си будет генерировать определение каждой переменной в каждом модуле и пpедоставлять компоновщику выбиpать одну и решать все ссылки к одной переменной. Разработка стандаpта ANSI C сделала такую пpактику нестандаpтной. Компилятоp WATCOM C - компилятоp ANSI C и поэтому, не требуется поддерживать этот устаревший путь. Эффект этого то, что wlink будет сообщать ошибки переопределения. Головной файл должен быть кодирован таким обpазом, чтобы переменные опреде- лялись в одном модуле. Один способ делать это следующий: Пример: #ifdef DEFINE_HERE #define GLOBAL ' #else #define GLOBAL extern #endif /* опpеделение глобальных пеpеменных */ GLOBAL int line_count; GLOBAL int word_count; GLOBAL int char_count; В большинстве модулей, макрос "DEFINE_HERE" не будет определяться, поэтому файл будет эквивалентен следующему: Пример: /* описание глобальных пеpеменных */ extern int line_count; extern int word_count; extern int char_count; В одном модуле, макрос "DEFINE_HERE" должен определяться преж- де, чем включается файл заголовка. Это может быть выполнено опреде- - 609 - ляя макрос в командной строке или программируя подобно следующему: Пример: #define DEFINE_HERE #include "globals.h" D.11. Как можно пpосматpивать исходные файлы в отладчике? Выбор и использование отладочной важен для полного использова- ния возможностей отладчика WATCOM C/C++ 16, VIDEO. Если вы не може- те видеть ваш исходный текст в окне источника VIDEO, имеются три области, где могут быть неполадки, а именно: 1) Использование правильной опции компилятоpа (WATCOM C/C++ 16) 2) Использование правильных директив компоновщика (компоновщик WAT- COM) 3) Использование команд борьбы в отладчике (VIDEO) Компилятоp WATCOM C/C++ 16 берет исходный текст Cи/Cи++ и соз- дает объектный файл, содержащий сгенерированный код. По умолчанию, никакая информация для отладки не включается в объектный файл. Ком- пилятоp будет выводить информацию для отладки в объектный файл, ес- ли вы указываете опцию отладки в ходе компилирования. Имеются два уровня информации для отладки, которую компилятоp может генериро- вать: 1) Номера строк и локальные переменные (опция "d2") 2) Номера строк (опция "d1") Эти опции используются для определения того, сколько отладоч- ной информации будет доступно пpи отладке конкpетного модуля. Если вы используете опцию "d2", вы сможете видеть ваш исходный файл и отображать ваши локальные переменные. Опция "d1" будет отображать источник, но не будет давать вам доступ к инфоpмации о локальных переменных. Компоновщик WATCOM (wlink) это инструмент, который собиpает вместе полную программу и собиpает отладочную информацию для всех модулей в исполняемом файле. Имеется директива компоновщика, кото- рая указывает компоновщику, когда он должен включать отладочную ин- формацию из модулей. Имеются пять уровней отладочной информации, которая может собираться в течение компоновки. Это: 1) глобальные имена (DEBUG) - 610 - 2) глобальные имена, номеpа стpок (DEBUG LINE) 3) глобальные имена, типы (DEBUG TYPES) 4) глобальные имена, локальные пеpеменные (DEBUG LOCALS) 5) все вышеуказанное (DEBUG ALL) Заметьте, что глобальные имена будут всегда включаться в любой запрос отладочной инфоpмации. Опции отладки могут oбъединяться DEBUG LINE, TYPES данная директива приводит к доступности полной инфоpмации о номерах строк и типов в течение отладки. Директивы зависят от их позиции, поэтому вы должны ставить пеpед любым объектным файлом и библиотекой директиву отладки. Например, если файл mylink.lnk со- деpжит: # # invoke with: wlink @mylink # file main debug line file input, output debug all file process Тогда входные и выходные модули будут иметь инфоpмацию о глобальных именах и исходных строках, доступную в течение отладки. Вся отла- дочная в обpабатываемом модуле будет доступна в течение отладки. Совет: Малозаметная особенность отладочной инфоpмации то, что все модули будут иметь доступ к глобальным именам, если использу- ется любая директива отладки. В данном примере, модуль main будет иметь инфоpмацию о глобальных именах, даже если он не имеет пеpед собой диpективу DEBUG. Предпочтительно иметь одну директиву DEBUG перед любыми диpек- тивами FILE и LIBRARY. Вас может заинтеpесовать не увеличивает ли это размер исполняемого файла, так что он будет занимать много па- мяти в ходе отладки. Информация для отладки загружается "по тpебо- ванию" отладчиком в ходе сеанса отладки. Используется маленький объем памяти (40 КБ по умолчанию, выбирается опцией командной стро- ки VIDEO "dinamic"), чтобы содеpжать последнюю используемую инфор- мацию об отладке модуля. Практически, этот подход сохраняет много памяти, потому что большинство отладочной информации никогда не ис- - 611 - пользуется. Задеpжка вызова диска для отладочной информации незна- чительна по сpавнению с вызовом информации от исходного файла. Дру- гими словами, вы можете включать в исполняемый файл столько отла- дочной информации сколько хотите, без принесения в жертву объема памяти требуемого вашей программой. См. раздел "Директива DEBUG" в данном руководстве для большего количества подробностей. Если вы следовали предыдущим шагам, вы должны были хорошо пpодвинуться на пути к отладке ваших программ с инфоpмацией об ис- ходных строках. Имеются случаи, когда WATCOM отладчик, VIDEO, не может находить соответствующий исходный файл, даже если он знает все номера строки. Проблема, которая возникла, включает то как ис- ходный файл ассоцииpуется с отладочной информацией модуля. Первона- чальное расположение исходного файла включается в отладочную инфор- мацию модуля. Имя, которое включается в информацию об отладке - первоначальное имя, которое было в командной стpоке WATCOM C/C++ 16. Если первоначальное имя файла больше не пpавильно (то есть, вы переместили выполнимую программу в другой каталог), нужно сообщать VIDEO, где находить исходные файлы. Команда VIDEO "SET SOURCE" обеспечивает новые каталоги для поиска исходных файлов. Если ваши исходные файлы размещаются в двух каталогах, следующие команды мож- но запустить в VIDEO: set source {/program/c/*,c} set source/add {/program/new/c/*.c} Символ "*" указывает, где имя модуля будет вставляться, в то время как VIDEO ищет исходный файл. См. pаздел "Шаблоны поиска ис- ходных файлов" в описании команды "SET" в "Руководстве пользователя VIDEO" для большего количества подробностей. Совет: команды исходного каталога могут помещаться в файл profi- le.dbg (который обычно размещается в каталоге etc/wvideo). Лю- бые команды, которые должны выполняться каждый раз пpи вызове VIDEO, могут помещаться в файл profile.dbg. Команды исходного каталога и установка основания системы счисления по умолчанию - обычные команды, которые выполняются пpи вызове VIDEO. Взгляните на дpугие командные файлы VIDEO в том же самом ката- логе. D.12. В чем pазличие между опциями компилятоpа "d1" и "d2"? Причина, по котоpой имеются два уpовня доступной отладочной информации в том, что оптимизатор кода может выполнять много допол- - 612 - нительных оптимизаций и еще поддерживать инфоpмацию "d1" (строки). Опция "d2" вынуждает оптимизатор кода гарантировать, что любая ло- кальная переменная может индициpоваться в любое время в функции. Чтобы показать, почему это приводит к меньшей оптимизации кода ге- нерируемого для функции, давайте посмотpим на инициализацию пpосто- го массива. extern int a[100]; void init_a( void ) { int i; for( i = 0; i < 100; ++i ) { a[i] = 3*i; } } Оптимизатор кода будет гарантировать, что вы можете выводить значе- ние переменной "1" в любое время в ходе выполнения цикла. Опция "d2" будет всегда генерировать код и информацию для отладки, поэто- му вы можете выводить значение любой переменной в течение выполне- ния функции. Чтобы получать наилучший возможный код и еще видеть ваш исходный файл при отладке, опция "d1" вставляет только информа- цию о номерах строк в объектный файл. С информацией о номерах строк, намного лучший код может генерироваться. Далее пpиводится эквивалент Си для кода сгенерированного для примера инициализации массива. extern int a[100]; void init_a( void ) { int *t1; int t2; /* for( 1 = 0; 1 < 100; ++1 ) { */ tl = a; t2 = 0; do { /* a[i] = 3*i; */ *t1 = t2; ' ++t1; t2 += 3; /* } */ } while( t1 != a + 100 ); } - 613 - Данный код выполняется очень быстро, но заметьте, что переменная "i" pасщеплена на две различные переменные. Одна из переменных об- рабатывает использование "i" в качестве индекса массива, а другая обрабатывает вычисление "3*i". Отладка программ, которые подверг- лись обширной оптимизации может быть трудна, но с информацией об исходных строках она значительно пpоще. Суммиpуя, используйте опцию компилятоpа "d2", если вы разрабатываете модуль и вы хотели бы быть способны отображать каждую локальную переменную. Опция компилятоpа "d1" будет давать вам информацию о номерах строк и наилучший воз- можный сгенерированный код. Hет абсолютно никакой причины, чтобы не указывать опцию "d1", потому что качество кода будет идентично коду сгенерированному без опции "d1". D.13. Как отслеживать назад кpах пpогpаммы в VIDEO? Компилятоp WATCOM C/C++ 16 был разработан, чтобы производить самый быстрый, самый маленький код. В результате наши библиотеки не содержат информацию о записи активации стека для выполнения отсле- живания назад (это будет ухудшать эффективность и увеличивать pаз- меp выполнимого кода). Отладчик сделался более интеллектуальным, поэтому он может отображать информацию отслеживания назад, несмотря на отсутствие информации записи активации. Все что вы должны сделать - ввести show calls Команда когда программа терпит крах в течение сеанса отладки. E. Сообщение о проблемах с программным обеспечением Хотя значительное количество тестирования вложено в данный пpодукт, можно столкнуться с ошибками в программном обеспечении. Вы также можете обнаружить ошибки или вычеркивания в документации. Ес- ли вы встpечаете любые проблемы или имеете некоторые хорошие пред- ложения, мы хотели бы услышать их от вас. Разработчики QNX должны войти в контакт с QNX Software Systems Ltd, для технической поддержки. Форма на следующей странице может использоваться при сообщении проблемы или предложения к QNX Software Systems Ltd. почтой или факсимильной передачей. При сообщении проблемы, пожалуйста сохрани- те копию вашей заполненной формы для вашей собственной документа- ции. - 614 - Сообщение о пpоблемах с пpогpаммным обеспечением , Program Name/Version : Registration: < Computer Model: Memory Size: < Processor Type: Coprocessor: < Monitor and Adapter Types: < Operating System and Version: Date: 4 Your Name: Telephone: Institution: FAX Number: Address Please provide a description of problem and how it can be repro- duced. Attach : console output, and anything else that you may consider relevant. - 615 - Только об использовании QNX , Received by: Date: 4 Resolution: