(Недопустимая команда для выбранного в настоящий момент про- цессора (процессоров))
Строка программы содержит команду, которая не может быть ас- семблирована текущим процессором. Например:
.8086 PUSH 1234h ; занесение в стек непосредственного ; операнда для процессора 8086 не ; допускается
При ассемблировании исходного файла с помощью Турбо Ассемб- лера по умолчанию будут разрешены команды процессора 8086. Если желательно использовать расширенные мнемоники команд, определен- ные для процессоров 186/286/386, то должна быть указана одна из директив, разрешающих использование этих команд (Р186, Р286, Р386).
(Недопустимый локальный параметр)
В директиве LOCAL внутри макроопределения указан параметр, не являющийся допустимым именем идентификатора. Например:
X MACRO LOCAL 123 ; это не идентификатор ENDM
(Недопустимый префикс для локальных имен идентификаторов)
В директиве LOCALS специфицируется недопустимый префикс для локальных имен идентификаторов. Например:
LOCALS XYZ ; ошибка: допускается только 2 символа
Префикс локальных идентификаторов должен состоять ровно из двух символов и представлять собой допустимое имя идентификатора. Например, допустимыми являются следующие комбинации: __, @@ (по умолчанию для локальных имен идентификаторов используется префикс @ @).
(Недопустимый параметр макрокоманды)
В директиве MACRO для формального параметра макрокоманды указано недопустимое имя идентификатора. Например:
X MACRO 123 ; недопустимый формальный параметр ENDM
(Недопустима ссылка на память)
Операнд команды содержит ссылку на адрес памяти, что недо- пустимо для данного операнда. Например:
mov [bx],BYTE PTR A ; ошибка: недопустима пересылка ; из памяти в память
В данной команде оба операнда представляют собой адреса па- мяти, что недопустимо в команде mov. В командах семейства процес- соров 80х86 только один из операндов может ссылаться на адрес па- мяти.
(Недопустимое число)
Число содержит один или более символов, недопустимых для чи- сел данного формата. Например:
Z = 0ABCGH
Здесь G - недопустимый символ для шестнадцатиричных чисел.
(Недопустимый начальный адрес)
Указан адрес, недопустимый для установки текущего сегментно- го адреса ($). Допускается указывать константу, выражение, ис- пользующее счетчика адреса ($), или имя идентификатора из текуще- го сегмента.
(Недопустимое переопределение в структуре)
Попытка инициализировать элемент структуры, определенный с помощью операции DUP. Инициализировать можно только те члены, ко- торые были объявлены без использования операции DUP.
(Недопустимое переопределение регистра)
В ссылке на сегмент перед двоеточием был указан регистр, не являющийся сегментным регистром. К сегментным регистрам относятся следующие регистры: CS, DS, ES, SS, а также FS и GS для процессо- ра 80386. Например:
mov dx:XYZ,1 ; DX не является сегментным регистром
(Недопустимое основание системы счисления)
В директиве .RADIX в качестве основания системы счисления указано недопустимое число. Например:
.RADIX 7 ; неверно
Основанием системы счисления могут быть следующие числа: 2, 8, 10 и 16. Это число интерпретируется как десятичное, независимо от текущего умолчания для основания системы счисления.
(Недопустимый регистр в инструкции)
В качестве источника в инструкции SETFIELD и GETFIELD ис- пользован недопустимый регистр.
(Недопустимо указание множителя для регистра)
Попытка умножить регистр на какое-либо число, что является недопустимой операцией. Например:
mov ax * 3,1
Единственный случай, когда допускается умножение регистра на константное выражение - это при определении масштабного индексно- го операнда для процессора 80386.
(Недопустимый сегментный адрес)
Это сообщение об ошибке выдается, если для позиционирования сегмента указывается значение адреса, превышающее 65535. Напри- мер:
F00 SEGMENT AT 12345h
(Недопустимо использование константы)
В выражении используется константа там, где использование константы недопустимо. Например:
mov bx+4,5
(Недопустимо использование регистра)
В выражении указывается имя регистра там, где использование регистра недопустимо. Например:
X = 4 shl ax ; в операции SHL нельзя указывать регистры
(Недопустимо использование сегментного регистра)
В выражении или команде указывается имя сегментного регистра там, где использование сегментного регистра недопустимо. Напри- мер:
ADD SS,4 ; в команде ADD нельзя указывать ; сегментные регистры
(В директиве USES указан недопустимый регистр)
Указан недопустимый регистр в командах PUSH и POP при входе и выходе из процедуры. Допустимы следующие регистры:
AX CX DS ES BX DI DX SI
Если директивой .386 или .386Р разрешены команды процессора 80386, то можно указывать 32-битовые эквиваленты перечисленных выше сегментов.
(Недопустимый идентификатор версии)
Эта ошибка происходит, когда в параметре /U или в операторе VERSION выбирается недопустимая версия.
(Недопустимый идентификатор предупреждающего сообщения)
Введен неверный трехсимвольный идентификатор предупреждающе- го сообщения. Список всех допустимых идентификаторов предупрежда- ющих сообщений приведен в Главе 2.
Имена идентификаторов представляют собой сочетание букв (в верхнем и нижнем регистре), цифр и специальных символов. Имена идентификаторов не могут начинаться с цифры. Турбо Ассемблер мо- жет интерпретировать имена идентификаторов с различием регистра символов или без него. Различимостью регистра символов можно уп- равлять с помощью параметров командной строки Турбо Ассемблера /ML, /MU и /MX.
Имена идентификаторов могут иметь в длину до 255 символов. По умолчанию имена идентификаторов являются значащими до 32 сим- волов. Для изменения числа значащих символов в имени идентифика- тора вы можете использовать параметр командной строки /MV.
Примечание: Об использовании параметров командной строки рассказывается в Главе 2.
В имени идентификатора можно использовать символ подчеркива- ния (_), знак вопроса (?), знак доллара ($) и символ @. В режиме MASM (и только в нем) в качестве первого символа имени вы можете использовать точку (.). Однако легко спутать точку в начале иден- тификатора с операцией точки (которая используется для выделения элемента структуры), поэтому лучше не использовать ее в именах идентификаторов.
Турбо Ассемблер обычно выводит два информационных сообщения. Во-первых, всегда выдается информационное сообщение непосредс- твенно перед началом ассемблирования пользовательского исходного файла (или файлов). Кроме того, выдается информационное сообщение по окончании ассемблирования каждого файла. Пример информационно- го сообщения, выдаваемого при запуске Турбо Ассемблера:
Turbo Assembler Version 3.0 Copyright(C) 1991 Borland International Assembling file: TEST.ASM
(Турбо Ассемблер, версия 3.0, продукт фирмы Borland, 1991г.)
По окончании ассемблирования исходного файла выдается сооб- щение с краткой характеристикой процесса ассемблирования. Это со- общение выглядит следующим образом:
Error messages: None Warning messages: None Passes: 1 Remaining memory: 279K
(Сообщения об ошибках: Нет Проходов: 1 Предупреждающие сообщения: Нет Осталось памяти: 279Кб)
Подавить все информационные сообщения можно с помощью пара- метра командной строки /T. Информационные сообщения подавляются только в случае отсутствия ошибок в процессе ассемблирования. При наличии ошибок параметр /T никакого влияния не имеет: стандартные информационные сообщения будут выданы в начале и в конце процесса ассемблирования.
Вы можете использовать любое выражение, при вычисление кото- рого получается число, умещающееся в экземпляре перечислимого ти- па данных, например:
ETYPE ? ; неинициализированный экземпляр ETYPE FOO ; инициализированный экземпляр, ; значение FOO ETYPE 255 ; число вне ENUM также подходит
Инициализированные экземпляры структуры несколько более сложны, чем неинициализированные. Когда вы определяете структуру, вам нужно определить используемое по умолчанию начальное значение для каждого ее элемента. (В качестве начального значения можно использовать ключевое слово ?, которое указывает, что конкретного начального значения сохранять не следует.) Когда вы создаете эк- земпляр структуры, его можно создать с использованием значений по умолчанию или переопределяемых значений. Простейший инициализиро- ванный экземпляр структуры содержит просто заданные в определении начальные значения. Например:
ASTRUC {}
что эквивалентно следующему:
DB "xyz" DW 1 DD 2
Фигурные скобки ({}) представляет нулевой инициализатор для структуры. Значение-инициализатор определяет, что элементы (если они имеются) должны иметь начальные значения, которые следует пе- реопределить, и какими новыми значениями, если вы выделяете дан- ные для экземпляра структуры. Инициализатор в виде фигурных ско- бок имеет следующий синтаксис:
{ [имя_элемента = значение [,имя_элемента.]] }
где "имя_элемента" - это имя элемента структуры или объединения, а "значение" - это то значение, которое вы хотите присвоить эле- менту в данном экземпляре. Чтобы указать Турбо Ассемблеру, что для элемента нужно использовать начальное значение из определения структуры или объединения, задайте нулевое значение. Значение ? показывает, что этот элемент инициализировать не нужно. Турбо Ас- семблер присваивает всем элементам, которые не указываются в ини- циализаторе, начальное значение из определения структуры или объ- единения, например:
ASTRUC {C=2,D=?}
эквивалентно следующему:
DB "xyz" DW 2 DD ?
Вы можете использовать инициализатор в виде фигурных скобок для задания значения любого элемента структуры или объединения, даже если он находится во вложенной структуре или объединении.
Объединения отличаются от структур, поскольку элементы в объединении перекрывают друг друга. Будьте аккуратны, когда вы инициализируете экземпляр структуры, поскольку если несколько элементов перекрывают друг друга, Турбо Ассемблер допускает, что- бы в экземпляре только один элемент имел инициализирующее значе- ние. Например:
Когда вы определяете таблицу, нужно задать начальное значе- ние для всех ее элементов. Простейший инициализированный экземп- ляр таблицы содержит просто заданные в определении начальные данные, например:
TTYPE {}
что эквивалентно следующему:
DW MoveRtn DD MsgRtn DW DoneRtn
Фигурные скобки ({}) представляют нулевое инициализирующее значение. Значение инициализатора определяет, что элементы (если они есть) имеют начальное значение, которое нужно переопределить, и каким именно новым значением его требуется переопределить при выделении данных для экземпляра таблицы.
Инициализатор записи в фигурных скобках имеет следующий син- таксис:
{[имя_элемента = выражение [,имя_элемента = выражение.]]}
где "имя_элемента" - это имя элемента таблицы, а "выражение" - это значение, которое вы хотите определить для элемента в данном экземпляре. Пустое значение указывает, что вы будете использовать начальное значение элемента из определения таблицы. Значение ? эквивалентно нулю. Турбо Ассемблер устанавливает для всех элемен- тов, которые не указываются в инициализаторе, начальное значение, заданное в определении таблицы. Например:
TTYPE {MoveProc=MoveRtn2,DoneProc=?}
что эквивалентно следующему:
DW MoveRtn2 DD MsgRtn DW ?
При определении записи для некоторых или всех полей записи нужно задавать начальное значение. (Турбо Ассемблер предполагает, что все не заданные значения равны 0.) Простейший инициализиро- ванный экземпляр записи содержит просто заданное в определении начальное поле данных, например:
MYREC {}
что эквивалентно следующему:
DW (4 SHL 6) + (0 SHL 4) + (15 SHL 0) ; SHL - это операция сдвига влево для выражений
Фигурные скобки ({}) представляют нулевое инициализирующее значение записи. Значение инициализатора определяет, что началь- ное значение нужно переопределить, и каким именно новым значением его требуется переопределить (если вы выделяете данные для эк- земпляра записи).
Инициализатор записи в фигурных скобках имеет следующий син- таксис:
{ [имя_поля = выражение [,имя_поля = выражение.]] }
где "имя_поля" - это имя поля записи, а "выражение" - это значе- ние, которое вы хотите определить для поля в данном экземпляре. Пустое значение указывает, что вы будете использовать начальное значение поля из определения записи. Значение ? эквивалентно ну- лю. Турбо Ассемблер устанавливает для всех полей, которые не ука- зываются в инициализаторе, начальное значение, заданное в опреде- лении записи. Например:
MYREC {VEL=2,SZE=?}
эквивалентно следующему:
DW (2 SHL 6) + (0 SHL 4) + (0 SHL 0)
Альтернативным методом инициализации экземпляров записи является использование угловых скобок (<>). В этом случае скобка- ми ограничивается инициализатор. Значения инициализатора являются неименованными, но располагаются в том же порядке, что и соот- ветствующие поля в определении записи. Данный инициализатор имеет следующий синтаксис:
<[выражение [,выражение.]]>
где "выражение" представляет нужное значение поля соответствующей записи в определении записи. Пустое значение указывает, что вы будете использовать начальное значение из определения записи. Ключевое слово ? указывает, что это поле должно быть равно 0. Например:
MYREC <,2,?>
эквивалентно следующему:
DW (4 SHL 6) + (2 SHL 4) + (0 SHL 0)
Если вы задаете меньше значений, чем имеется полей в записи, Турбо Ассемблер завершает экземпляр, используя для оставшихся по- лей начальные значения из определения записи.
MYREC <1> ; то же, что MYREC <1,,>
Чтобы вы могли вызывать виртуальные методы, простой реализа- ции таблицы виртуальных методов недостаточно. Каждый объект с виртуальными методами включает в свои структуры данных указатель на таблицу виртуальных методов. Когда вы создаете экземпляр объ- екта этот указатель нужно инициализировать. Для этой цели можно использовать директиву TBLINST.
Инициализируйте указатель таблицы виртуальных методов в ме- тоде init следующим образом:
; Инициализация объекта связанного списка ; Это метод "init" ; Этот метод должен быть статическим. list_init PROC PASCAL FAR ARG @@list:dword USES dx,bx lds bx,@@list ; -- По адресу ds:bx инициализировать таблицу виртуаль- ; ных методов. TBLINIT ds:bx ; -- Инициализировать данные объекта ;; << Здесь инициализируются все данные объекта >> ret ENDP
Примечание: Заметим, что метод init должен быть стати- ческим, так как виртуальный метод экземпляра объекта вы вы- зывать не можете, пока не инициализирован указатель таблицы виртуальных методов.
(Возможно сокращение длины команды, если явно указать тип имени)
Из-за наличия ссылки вперед на имя идентификатора генерируе- мый код содержит дополнительные команды NOP. Для того чтобы сок- ратить код можно убрать ссылку вперед либо явно указать тип сим- волического имени. Например:
jmp X ; для этой команды будет выдано предупреждающее ; сообщение jmp SHORT X ; не будет выдано предупреждающего сообщения Х:
На одной строке вы можете задать несколько инструкций PUSH и POP. Например:
PUSH ax PUSH bx PUSH cx POP cx POP bx POP ax
можно записать как:
PUSH ax bx cx POP cx bx ax
Чтобы Турбо Ассемблер распознавал наличие нескольких операн- дов в этих инструкциях, нужно чтобы любой операнд не мог рассмат- риваться как часть соседнего операнда, например инструкция:
PUSH foo [bx]
может привести к непредвиденному результату, поскольку foo,[bx] и foo[bx] являются допустимыми выражениями. Чтобы эта инструкция стала определенней, можно использовать круглые или квадратные скобки, например:
PUSH [foo] [bx]
Инструкция GETFIELD извлекает данные из поля записи. Логика ее работы противоположна инструкции SETFIELD. Она имеет следующий синтаксис:
GETFIELD имя_поля регистр_приемник, регистр/память_источник
где "имя_поля" и "регистр_приемник" работают так же, как в опера- ции SETFIELD. "Регистр/память_источник" можно использовать также, как "регистр_источник" в операции SETFIELD, например:
FOO RECORD R0:1,R1:4,R2:3,R3:1 . . . GETFIELD F1 AX,BL ; рабочим регистром является BX GETFIELD F1 AX,BH ; недопустимо!
Примечание: Операция GETFIELD уничтожает все содержи- мое рабочего регистра.
Операция GETFIELD извлекает значение поля, обнаруженное в регистре-источнике или по адресу памяти, и устанавливает в это значение соответствующую часть регистра-приемника. На другие ре- гистры (кроме рабочего) и флаги процессора эта инструкция не вли- яет.
Чтобы выполнить свою функцию, инструкция GETFIELD генерирует эффективную и расширенную последовательность инструкций MOV, XCHG, ROL и ROR.
(Не хватает памяти для обработки командной строки)
Командная строка занимает более 64К, либо для ее обработки не хватает имеющейся памяти. Следует упростить командную строку либо запустить Турбо Ассемблер при наличии большего объема памя- ти.
(Внутренняя ошибка)
Это сообщение не должно выдаваться при нормальной работе Турбо Ассемблера. Сделайте копию файлов, вызвавших появление этой ошибки, и сообщите в отдел технического обслуживания фирмы Borland.
(Недопустимая командная строка)
Неверен формат командной строки, с помощью которой запуска- ется Турбо Ассемблер. Например, в команде:
NASM, MYFILE
не указан исходный файл, который должен ассемблироваться. См. Главу 2, где дается подробное описание командной строки.
(Недопустимая модель памяти)
В директиве .MODEL для модели памяти указано недопустимое ключевое слово. Например:
.Model GIGANTIC
Для обозначения моделей памяти допустимы следующие ключевые слова: TINY, SMALL, COMPACT, MEDIUM, LARGE и HUGE.
(Недопустимый номер после _)
Верно указан идентификатор параметра, однако неверно специ- фицирован числовой параметр после нее. См. Главу 2, где описаны параметры командной строки.
(Недопустимый операнд(ы) для данной команды)
В команде указана недопустимая комбинация операндов. Напри- мер:
FADD ST(2), ST(3)
В команде FADD только на один стековый регистр можно ссы- латься по имени, другой операнд должен быть вершиной стека.
Первый и наиболее часто используемый метод доступа к пара- метрам, передаваемым из Турбо Паскаля в Турбо Ассемблер, заключа- ется в том, чтобы использовать для адресации к стеку регистр BP. Например:
CODE SEGMENT ASSUME CS:CODE MyProc PROC FAR ; procedure MyProc(i,j : integer); PUBLIC MyProc j EQU WORD PTR [bp+6] ; j находится над сохраненным BP ; и адресом возврата i EQU WORD PTR [bp+8] ; i располагается над j push bp ; нужно сохранить BP вызывающей ; программы mov bp,sp ; BP теперь указывает на вершину ; стека mov ax,i ; адресуемся к i через BP . . .
При вычислении смешений в стеке параметров, к которым мы об- ращаемся таким образом, нужно помнить, что 2 байта используются для сохраненного регистра BP.
Обратите внимание на использование в данном примере присваи- ваний. Они позволяют сделать программу более понятной. У них есть только один недостаток: поскольку для выполнения такого рода при- сваиваний можно использовать только директиву EQU (а не =), в данной исходном файле Турбо Ассемблера вы не сможете переопреде- лить идентификаторы i и j. Один из способов обойти это заключает- ся в том, чтобы использовать более описательные имена параметров, чтобы они не повторялись, либо можно ассемблировать каждую подп- рограмму Ассемблера отдельно.
Второй способ доступа к параметрам состоит в использовании для получения этих параметров другого базового или индексного ре- гистра (BX, SI или DI). Нужно однако помнить, что по умолчанию сегментным регистром для них является регистр DS, а не SS. Поэ- тому для их использования вам придется применять префикс переоп- ределения сегмента.
Приведем пример использования для получения параметров ре- гистра BX:
CODE SEGMENT ASSUME CS:CODE MyProc PROC FAR ; procedure MyProc(i,j : integer); PUBLIC MyProc j EQU WORD PTR SS:[BX+4] ; j находится над сохраненным ; BP и адресом возврата i EQU WORD PTR SS:[bp+8] ; i располагается над j mov bx,sp ; BX теперь указывает на вершину ; стека mov ax,i ; адресуемся к i через BX . . .
В тех программах, где нет большого числа ссылок на парамет- ры, такой метод позволяет сэкономить время и место. Почему? Пото- му, что в отличие от BP, регистр BX не требуется восстанавливать в конце программы.
При желании вы можете использовать в ассемблерных функциях неисправленные имена, не пытаясь выяснить, как должны выглядеть правленные. Использование нескорректированных имен защитит ваши ассемблерные функции от возможных изменений алгоритма в будущем. Borland С++ позволяет определять в программах С++ стандартные имена функций С++, как в следующем примере:
extern "C" { int add(int *a, int b); }
Любые функции, объявленные внутри фигурных скобок, получат имена в стиле языка Си. Ниже показаны соответствующие определения в ассемблерном модуле:
public _add _add proc
Объявление ассемблерной функции в блоке extern "C" позволит вам избежать проблем со "откорректированными именами". При этом улучшится и читаемость кода.
После того, как вы определите структуру или объединение, ин- формацию о структуре и объединении можно получить различными пу- тями. Для получения информации с помощью выражений Турбо Ассемб- лера вы можете использовать имена типа данных структуры или объ- единения. Более подробно об этом рассказывается в Главе 5.
Турбо Паскаль генерирует файлы .EXE, которые могут загру- жаться в память компьютера РС по любому доступному адресу. Пос- кольку в программе заранее неизвестно, куда будет загружен данный сегмент программы, компоновщик указывает загрузчику DOS.EXE, что нужно при загрузке скорректировать в программе все ссылки на сег- менты. После выполнения этих корректировок все ссылки на сегменты (такие, как CODE или DATA) будут содержать корректные значения.
Ваша программа на Турбо Ассемблере может использовать это средство для получения адресов объектов во время выполнения. Предположим, например, что в вашей программе требуется изменить значение регистра DS, но вы не хотите сохранять в цикле исходное содержимое стека или перемещать эти значения во временную об- ласть. Вместо этого вы можете использовать операцию Турбо Ассем- блера SEG:
. . . mov ax,SEG DATA ; получить фактический ; адрес глобального значения ; DS Турбо Паскаля mov ds,ax ; поместить его в DS для ; использования Турбо ; Паскалем . . .
Когда ваша программа будет загружаться, DOS поместит коррек- тное значение SEG DATA прямо в поле промежуточного операнда инст- рукции MOV. Это наиболее быстрый путь перезагрузки сегментного регистра.
Данный метод нужно также использовать, чтобы программы обс- луживания прерываний сохраняли информацию в глобальном сегменте данных Турбо Паскаля. Регистр DS не обязательно во время прерыва- ния содержит значение DS Турбо Паскаля, но для получения доступа к переменным и типизованным константам Турбо Паскаля можно ис- пользовать указанную выше последовательность.
Стандартные инструкции PUSH и POP не могут сохранять в стеке дальние указатели, которые требуют 4 байт в процессорах 8086, 80186 и 80286 и 6 байт в процессоре 80386.
Турбо Ассемблер допускает указание в инструкциях PUSH и POP операнда-указателя размером DWORD для процессора 8086, 80186 и 80286 и QWORD для процессора 80386. Когда обнаруживаются такие инструкции, Турбо Ассемблер генерирует инструкции PUSH и POP для двух частей операнда.
Символ & в теле макрокоманды имеет специальное значение. В общем случае & отделяет имя формального аргумента от окружающего текста, благодаря чему Турбо Ассемблер может распознавать его при подстановке. Если, например, имеется следующее тело макрокоманды:
sym&foo: DB 'It is &foo time'
и если вы при вызове данной макрокоманды присвоите foo текстовую строку party, то фактическим включаемым в модуль текст будет сле- дующее:
symparty: DB 'It is party time'
В качестве другого примера можно привести следующий:
foo&sym: DB 'We are in O&foo&o'
Если вы при вызове данной макрокоманды присвоите foo тексто- вую строку hi, то фактическим включаемым в модуль текст будет следующее:
hisym: DB 'We are in Ohio'
Приведем правила для символа &:
- вне заключенных в кавычки строк символ & используется как разделитель;
- внутри заключенной в кавычки строки и после двоеточия, ко- торое не находится в заключенной в кавычки строке в режиме Ideal, символ & должен предшествовать формальному аргумен- ту (чтобы этот аргумент мог распознаваться);
- при расширении макрокоманды Турбо Ассемблер удаляет один символ & из группы таких символов.
Последний пункт дает возможность помещать внутри макрокоманд макроопределения, требующие символа &. Турбо Ассемблер будет уда- лять только один символ & из группы.
Включаемые файлы позволяют вам использовать один и тот же блок кода в разных местах программы, включать этот блок в нес- кольких исходных модулях или уменьшить объем программы без необ- ходимости создания нескольких компонуемых модулей. Использование директивы INCLUDE указывает Турбо Ассемблеру, что нужно найти за- данный файл на диске и ассемблировать его, как если бы он был частью исходной программы.
Примечание: Допускается вложенность директив INCLUDE на любую глубину.
Синтаксис режима Ideal:
INCLUDE "имя_файла"
Синтаксис режима MASM:
INCLUDE имя_файла
где в имени файла может задаваться дисковод, каталог или расшире- ние. Если каталог или дисковод в имени файла не указываются, то Турбо Ассемблер сначала ищет файлы в каталогах, заданных в пара- метре командной строки /i, а затем в текущем каталоге.
Исправления
На стp. 333 в Приложении D, "Утилиты," говорится, что спра- вочное средство Турбо ассемблера называется TASMHELP. Вы можете использовать TASMHELP как описывается в данном руководстве только если установите Турбо ассемблер в каталоге, отличном от Borland C ++. В противном случае следует использовать утилиту THELP, кото- рая модифицирована таким образом, что может обращаться к множест- ву справочных файлов с помощью меню.
Утилиту THELP можно использовать следующим образом:
1) После установки Borland C++ и Турбо ассемблера вызовите THELP в ответ на подсказку DOS.
2) Чтобы вывести меню доступных справочных файлоа, нажмите клавиши ALT-F.
3) Для доступа к справочной информации по Турбо ассемблеру выберите файл TASM.TAH.
Назад | Содержание
Для изменения текущего используемого по умолчанию основания вы можете использовать директивы RADIX или .RADIX. В режиме Ideal используется следующий синтаксис:
RADIX выражение
а в режиме MASM:
.RADIX выражение
где "выражение" должно принимать значение 2 (двоичное), 8 (вось- меричное), 10 (десятичное) или 16 (шестнадцатиричное). Турбо Ас- семблер предполагает, что во время обработки директивы RADIX те- кущим основанием по умолчанию является основание 10.
Начальный и завершающий код процедур работает с регистрами, указывающими на стек. В процессоре 80386 или 80486 сегменты могут быть 16- или 32-разрядными. Таким образом, перед генерацией кор- ректного начального и завершающего кода Турбо Ассемблеру нужно знать корректный размер стека.
Если вы выбираете стандартную модель с помощью директивы MODEL, размер стека выбирается автоматически.
В Турбо Ассемблере предусмотрены директивы, которые могут установить или переопределить используемый по умолчанию при гене- рации начального и завершающего кода размер стека. Список этих директив приведен в следующей таблице:
Директивы модификации размера стека Таблица 7.10 -----------------------T----------------------------------------¬ ¦ Директива ¦ Значение ¦ +----------------------+----------------------------------------+ ¦ SMALLSTACK ¦ Указывает, что стек 16-разрядный. ¦ ¦ ¦ ¦ ¦ LARGESTACK ¦ Указывает, что стек 32-разрядный. ¦ L----------------------+-----------------------------------------
Назад | Содержание | Вперед
Порядок сегментов в каждом модуле определяет начальное раз- мещение сегментов в программе компоновщиком. В MASM 1.0 и 2.0 сегменты передавались компоновщику в алфавитном порядке. В Турбо Ассемблере предусмотрены директивы (только в режиме MASM), кото- рые позволяют воспроизвести это поведение.
Заметим, что данные директивы действуют так же, как парамет- ры командной строки /A и /S.
Эффективная генерация кода означает, что Турбо Ассемблер мо- жет определить, что можно использовать различные инструкции более эффективно, чем вы это делаете. Например, в некоторых случаях можно заменить инструкцию LEA более короткой и быстрой инструкци- ей MOV:
LEA AX,lval
можно заменить на:
MOV AX,OFFSET lval
Турбо Ассемблер предусматривает директивы, которые позволяют вам использовать эффективную генерацию кода. Эти директивы описа- ны в следующей таблице:
Директивы эффективной генерации кода Таблица 13.1 ------------------T----------------------------------------------¬ ¦ Директива ¦ Значение ¦ +-----------------+----------------------------------------------+ ¦ SMART ¦ Разрешает генерацию эффективного кода. ¦ ¦ ¦ ¦ ¦ NOSMART ¦ Запрещает генерацию эффективного кода. ¦ L-----------------+-----------------------------------------------
По умолчанию генерация эффективного кода разрешена. Однако на генерацию эффективного кода влияют не только директивы SMART и NOSMART, но и директива VERSION.
Примечание: О директиве VERSION подробнее рассказыва- ется в Главе 3.
Генерация эффективного кода влияет на следующие ситуации ге- нерации кода:
- Замена инструкции LEA инструкцией MOV, если операндом инс- трукции LEA является простой адрес.
- Где это возможно, выполняется генерация булевских инструк- ций со знаком,. Например, AND AX,+02 вместо AND AX,0002.
- Замена инструкции CALL FAR xxxx комбинацией инструкций PUSH CS, CALL NEAR xxxx, где целевой адрес xxxx использует тот же регистр CS.
Использование эффективных инструкций облегчает написание эф- фективного кода. Некоторые стандартные инструкции Intel также расширены таким образом, чтобы расширить их возможности и облег- чить использование. Они обсуждаются в следующих разделах.
Фирма Borland предлагает вам множество услуг, которые позво- лят ответить на вопросы о данном программном продукте. Убедитесь, что вы послали регистрационную карту. Для зарегистрированных пользователей обеспечивается техническое сопровождение, кроме то-
го, они могут получать информацию обо всех изменениях и дополне- ниях к продукту.
В следующем списке содержатся все ключевые слова директив Турбо Ассемблера. Ключевые слова группируются по версиям Турбо Ассемблера, в которых они вводились.
Следующие ключевые слова были введены в Турбо Ассемблере версии 1.0.
Ключевые слова Турбо Ассемблера 1.0 (VERSION T100) Таблица B.1 ----------------------------------------------------------------¬ ¦ % (1) %NOLIST JZ SETNLE ¦ ¦ .186 (M) NOLOCALS LAHF SETNO ¦ ¦ .286 (M) NOMASM51 LDS SETNP ¦ ¦ .286C (M) %NOMACS LEA SETNS ¦ ¦ .286P (M) NOMULTERRS LES SETNZ ¦ ¦ .287 (M) NOSMART LOCK SETO ¦ ¦ .386 (M) %NOSYMS LODS SETP ¦ ¦ .386C (M) %NOTRUNCS LODSB SETPE ¦ ¦ .386P (M) NOWARN LODSW SETPO ¦ ¦ .387 (M) ORG LOOP SETS ¦ ¦ .486 (M) %OUT (1) LOOPE SETZ ¦ ¦ .486C (M) P186 LOOPNE SHLD ¦ ¦ .486P (M) P286 LOOPNZ SHRD ¦ ¦ .8086 (M) P286N LOOPZ STOSD ¦ ¦ .8087 (M) P286P MOV LOOPW ¦ ¦ : (2) P287 MOVS LOOPWE ¦ ¦ = (2) P286 MOVSB LOOPWNE ¦ ¦ ALIGN P386N MOVSW LOOPWNZ ¦ ¦ .ALPHA P386P MUL LOOPWZ ¦ ¦ ARG P387 NEG F2XM1 ¦ ¦ ASSUME P486 NOP FABS ¦ ¦ %BI P486N NOT FADD ¦ ¦ .CODE (M) P8086 OR FADDP ¦ ¦ .CODESEG P8087 OUT FBLD ¦ ¦ COMM (10) PAGE POP FBSTP ¦ ¦ COMMENT (1) %PAGESIZE PUSH FCHS ¦ ¦ %CONDS %PCNT PUSHF FCLEX ¦ ¦ CONST PNO87 RCL FCOM ¦ ¦ .CONST (M) %POPLCTL RCR FCOMP ¦ ¦ .CREF (M) PROC (2) REP FCOMPP ¦ ¦ %CREF %PUSHLCTL REPE FCOS ¦ ¦ %CREFALL PUBLIC (1) REPNE FDECSTP ¦ ¦ %CREFREF PURGE REPNZ FDISI ¦ ¦ %CREFUREF QUIRKS REPZ FDIV ¦ ¦ %CTLS .RADIX (M) RET FDIVP ¦ ¦ .DATA (M) RADIX RETF FDIVR ¦ ¦ .DATA? (M) RECORD (2) RETN FDIVRP ¦ ¦ DATASEG REPT (1) ROL FENI ¦ ¦ DB .SALL (M) ROL FFREE ¦ ¦ DD SEGMENT (2) SAHF FIADD ¦ ¦ %DEPTH .SEQ (M) SAL FICOM ¦ ¦ DF (2) .SFCOND (M) SAR FICOMP ¦ ¦ DISPLAY SMART SBB FIDIV ¦ ¦ DOSSEG .STACK (M) SCAS FIDIVR ¦ ¦ DP (2) .STARTUP (M) SCASB FILD ¦ ¦ DQ (2) STRUC (2) SCASW FIMUL ¦ ¦ DT (2) SUBTTL (1) SHL FINCSTP ¦ ¦ DW (2) %SUBTTL [Р SHR FINIT ¦ ¦ ELSE (1) %SYMS STC FIST ¦ ¦ ELSEIF (1) %TABSIZE STD FISTP ¦ ¦ ELSEIF1 (1) %TEXT STI FISUB ¦ ¦ ELSEIF2 (1) .TFCOND (M) STOS FISUBR ¦ ¦ ELSEIFB (1) TITLE (1) STOSB FLD ¦ ¦ ELSEIFDEF (1) %TITLE STOSW FLDCTW ¦ ¦ ELSEIFDIF (1) %TRUNC SUB FLDENV ¦ ¦ ELSEIFDIFI (1) UDATASEG TEST FLDLG2 ¦ ¦ ELSEIFE (1) UFARDATA WAIT FLDLN2 ¦ ¦ ELSEIFIDN (1) UNION (2) WBINV FLDL2E ¦ ¦ ELSEIFIDNI (1) USES XCHG FLDL2T ¦ ¦ ELSEIFNB (1) WARN XLAT FLDPI ¦ ¦ ELSEIFNDEF (1) .XALL (M) XLATB FLDZ ¦ ¦ EMUL .XCREF (M) SOR FMUL ¦ ¦ END .XLIST (M) BOUND FMULP ¦ ¦ ENDIF (1) USECS ENTER FNCLEX ¦ ¦ ENDM USEDS INS FNDSI ¦ ¦ ENDP (2) USESS INSB FNENI ¦ ¦ ENDS (2) USEES INSW FNINIT ¦ ¦ EQU (2) USEFS LEAVE FNOP ¦ ¦ .ERR (1) (M) USEFS OUTS FNSAVE ¦ ¦ ERR CATSTR (2) OUTSB FNSTCW ¦ ¦ .ERR1 (1) (M) INSTR (2) OUTSW FNSTENV ¦ ¦ .ERR2 (1) (M) SIZESTR (2) POPA FNSTSW ¦ ¦ .ERRB (1) (M) SUBSTR (2) PUSHA FPATAN ¦ ¦ .ERRDEF (1) (M) AAA ARPL FPREM ¦ ¦ .ERRDIF (1) (M) AAD CTLS FPTAN ¦ ¦ .ERRDIFI (1) (M) AAM LAR FRNDINT ¦ ¦ .ERRE (1) (M) AAS LGDT FRSTOR ¦ ¦ .ERRIDN (1) (M) ADC LIDT FSAVE ¦ ¦ ERRIF ADD LLDT FSCALE ¦ ¦ .ERRDIF (1) (M) AND LMSW FSQRT ¦ ¦ .ERRDIFI (1) (M) ARPL LSL FST ¦ ¦ .ERRE (1) (M) BSF LTR FSTCW ¦ ¦ .ERRIDN (1) (M) BSR SGDT FSTENV ¦ ¦ ERRIF BSWAP SIDT FSTP ¦ ¦ ERRIF1 BT SLDT FSTSW ¦ ¦ ERRIF2 BTC SMSW FSTSW ¦ ¦ ERRIFB BT STR FSUB ¦ ¦ ERRIFDEF BTR VERR FSUBP ¦ ¦ ERRIFDIF BTS VERW FSUBR ¦ ¦ ERRIFDIFI CALL BSF FSUBRP ¦ ¦ ERRIFE CBW BSR FTST ¦ ¦ ERRIFDIDN CDQ BT FUCOM ¦ ¦ ERRIFDIDNI CLC BTC FUCOMP ¦ ¦ ERRIFNB CLD BTR FUCOMPP ¦ ¦ ERRIFNDEF CLI BTS FWAIT ¦ ¦ .ERRIFNB (1) (M) CLTS CDQ FXAM ¦ ¦ .ERRIFDEF (1) (M) CMC CMPSD FXCH ¦ ¦ .ERRNZ (1) (M) CMP CWDE FXTRACT ¦ ¦ .EVEN CMPS INSD FYL2X ¦ ¦ EVENDATA CMPS IRETD FYL2XP1 ¦ ¦ EXITM CMPXCHG IJECXZ FSETPM ¦ ¦ EXTRN (1) CWD LPS FPCOS ¦ ¦ .FARDATA CWDE LGS FPREM1 ¦ ¦ FARDATA DAA LODSD FPSIN ¦ ¦ .FARDATA (M) DAS LOOPD FPSINCOS¦ ¦ .FARDATA? (M) DEC LOOPDE FUCOM ¦ ¦ GLOBAL (1) DIV LOOPDNE FUCOMP ¦ ¦ GROUP (2) ESC LOOPDNZ FUCOMPP ¦ ¦ %INCL HLT LOOPDZ ¦ ¦ IDEAL IDIV LSS ¦ ¦ IF (1) IMUL MOVSD ¦ ¦ IF1 (1) IN MOVSX ¦ ¦ IF2 (1) INC MOVZX ¦ ¦ IFb (1) INS OUTSD ¦ ¦ IFDEF (1) INT POPAD ¦ ¦ IFDIFI (1) INVO POPFD ¦ ¦ IFE (1) IRET PUSHAD ¦ ¦ IFIDN (1) JA PUSHFD ¦ ¦ FIDNI (1) JAE SCASD ¦ ¦ IFNB (1) JB SETA ¦ ¦ IFNDEF (1) JBT SETAE ¦ ¦ %INCTL (1) JCXZ SETB ¦ ¦ INCLUD (1) JE SETBE ¦ ¦ INCLUDELIB (1) JG SETC ¦ ¦ IRP (1) JGT OUTSD ¦ ¦ IRPC (1) JL POPAD ¦ ¦ JUMPS JLE POPFD ¦ ¦ LABEL (2) JNA PUSHAD ¦ ¦ .LALL (M) JNAE PUSHFD ¦ ¦ .LFCOND (M) JNB SCASD ¦ ¦ %LINUM JNBE SETA ¦ ¦ %LIST JNC SETAE ¦ ¦ .LIST (M) JNE SETB ¦ ¦ LOCAL JNG SETBE ¦ ¦ LOCALS JNGE SETC ¦ ¦ MASM JNL SETE ¦ ¦ %MACS JNLE SETG ¦ ¦ MACRO (2) JNO SETGE ¦ ¦ MODEL JNP SETL ¦ ¦ .MODEL (M) JNC SETLE ¦ ¦ MULTERRS JNP SETNA ¦ ¦ NAME (1) JNS SETNAE ¦ ¦ %NEWPAGE JNZ SETNB ¦ ¦ %NOCONDS JO SETNBE ¦ ¦ %NNOCREF JP SETNC ¦ ¦ %NOCTLS JPE SETNE ¦ ¦ NOEMUL JPO SETNG ¦ ¦ %NOINCL JS SETNGE ¦ ¦ NOJUMPS JUMP SETNL ¦ L----------------------------------------------------------------
В данном разделе приведен полный перечень всех ключевых слов Турбо Ассемблера. Значение в скобках после ключевых слов указыва- ют их приоритет (1 или 2) в режиме MASM. Приоритет для ключевых слов указан только, если он имеет значение 1 или 2. Для всех дру- гих ключевых слов подразумевается приоритет 3. Турбо Ассемблер распознает ключевые слова только в том случае, если он находит их. В режиме MASM ключевые слова приоритета 1 или 3 всегда нахо- дятся в первой позиции, а ключевые слова приоритета 2 - во второй позиции. Символ M после ключевого слово указывает, что оно допус- тимо только для режима MASM, а I показывает ключевое слово, дос- тупное только в режиме Ideal. Если буква не указана, то ключевые слова работают в обоих режимах. Номер после ключевого слова пока- зывает приоритет.
Часто может встречаться ситуация, когда необходимо вызвать метод порождающего объекта из процедуры метода порожденного объ- екта. Для этого также можно использовать оператор CALL.METHOD.
Аналогично инструкции CALL.METHOD вы можете использовать расширение инструкции JMP с ключевым словом METHOD. Эта инструк- ция обеспечивает оптимальную рекурсию. См. Главу 13, где об инс- трукциях CALL.METHOD и JMP.METHOD рассказывается подробнее.