Категории
Самые читаемые
Лучшие книги » Компьютеры и Интернет » Базы данных » Flat Assembler 1.64. Мануал программера - Tomasz Grysztar

Flat Assembler 1.64. Мануал программера - Tomasz Grysztar

Читать онлайн Flat Assembler 1.64. Мануал программера - Tomasz Grysztar

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 2 3 4 5 6 7 8 9 10
Перейти на страницу:

virtual

 align 16

 a = $ — $$

end virtual

db a dup 0

Константа «a» определяется как разница между адресом после выравнивания и адресом блока «virtual» (смотрите предыдущий параграф), то есть она равна размеру требуемого пространства выравнивания.

«display» во время ассемблирования показывает сообщение. За ней должны следовать строка в кавычках или значения байтов, разделенные запятыми. Директива может быть использована для показа значений некоторых констант, например:

bits = 16

display 'Current offset is 0x'

repeat bits/4

 d = '0' + $ shr (bits-%*4) and 0Fh

 if d> '9'

  d = d + 'A'-'9'-1

 end if

 display d

end repeat

display 13,10

Этот блок директив рассчитывает четыре цифры 16-битного значения и конвертирует их в знаки для показа. Помните что это не будет работать, если адреса в текущем адресном пространстве перемещаемы (как это может быть с объектным форматом вывода и форматом PE), так как таким образом могут быть использованы только абсолютные значения. Абсолютное значение может быть получено вычислением относительного адреса, например «$-$$» или «rva $» в случае формата PE.

2.2.5 Множественные проходы

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

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

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

Если в коде встречается директива «display», фактически отображаются только сообщения, созданные в последний совершённый проход. В случае, если ассемблер остановился из-за ошибки, эти сообщения могут отражать спрогнозированные значения, которые еще не разрешены правильно.

Разрешение иногда может не создаться и в таких случаях ассемблер никогда не сумеет создать правильные прогнозы — по этой причине существует предел количества походов, и когда ассемблер исчерпает этот лимит, он остановится отобразит сообщение, что невозможно сгенерировать корректный вывод. Рассмотрим следующий пример:

if ~ defined alpha

 alpha:

end if

Если оператор «defined» выдает значение истина, если выражение, следующее за ним, в этом месте может быть вычислено, что в данном случае означает, что метка «alpha» где-то определена. Но блок выше определяет эту метку только, если значение, данное оператором «defined» ложь, что ведет к противоречию и делает невозможным разрешить такой код. Если, обрабатывая директиву «if» ассемблер должен прогнозировать, будет ли где-нибудь определена метка «alpha» (этого делать не приходится только если метка уже определена раньше), то какой бы ни был прогноз, всегда происходит противоположное. Поэтому ассемблирование остановится, если только метка «alpha» не определена где-то в коде перед вышеуказанным блоком — в этом случае, как уже было отмечено прогнозирование не требуется и блок просто будет пропущен.

Предыдущий пример может быть создан как попытка определить метку, только если этого все ещё не сделано. Эти строк неправильны, поскольку оператор «defined» проверяет определена ли метка где-либо вообще, и это включает определение внутри этого условного блока. Однако есть способ обойти эту проблему:

if ~ defined alpha | defined @f

 alpha:

 @@:

end if

«@f» это всегда та же метка, что ближайший следующий за ним символ «@@», поэтому предыдущий пример значит то же, как если бы вместо анонимной метки было определено любое уникальное имя. Если метка «alpha» ещё не определена, ассемблер спрогнозирует значение «defined alpha» как ложь, это будет однако значить, что будут определены обе метки. Но на следующем проходе ассемблер спрогнозирует, что определены обе метки, что заставит определить их вновь — так прогноз будет совпадать с результатом и процесс ассемблиования придет к правильному решению. Анонимная метка выступает здесь как маркер того, что метка «alpha» определена в этом месте.

Из этого примера вы можете заключить, что прогноз для оператора «defined» очень прямолинейный — метка прогнозируется как определенная только если она была определена в предыдущий проход (а если она была определена в текущий проход, прогноз не требуется). То же самое относится к оператору «used». Однако прогнозы для значений меток не так просты и вам никогда не следует полагать, что ассемблер работает таким способом.

2.3 Директивы препроцессора

Все директивы препроцессора выполняются перед основным ассемблированием, и таким образом директивы управления на них никак не влияют. В это время также удаляются все комментарии.

2.3.1 Включение файлов-исходников

«include» включает указанный файл-исходник туда, где эта директива используется. За ней должно следовать в кавычках имя файла, который должен быть включен, например:

include 'macros.inc'

Весь включенный файл обрабатывается препроцессором перед обработкой строк, следующих за содержащей директиву «include». Нет предела для количества включаемых файлов, пока они умещаются в память.

Путь, заключенный в скобки, может содержать окружающие переменные, заключенные в знаки «%», они будут заменены на их значения внутри пути. Знаки «» и «/» трактуются как разделители пути. Если не указан абсолютный путь, сначала файл ищется в директории, содержащей файл, в который он включается, и, далее, если его там нет, в директории, содержащей главный файл-исходник (указанный в командной строке). Эти правила так же относятся к путям, которые указываются в директиве «file».

2.3.2 Символьные константы

Символьные константы отличаются от числовых констант тем, что перед процессом ассемблирования они заменяются на их значения во всех строках кода, следующих за их определением, и все может стать их значением.

Определение символьных констант состоит из имени константы, за которой следует директива «equ». Все, что следует за этой директивой, станет значением константы. Если значение символьной константы содержит другие символьные константы, они заменяются на их значения перед присвоением значения новой константе. Например:

d equ dword

NULL equ d 0

d equ edx

После этих трех определений значение «NULL» будет «dword 0», а значение «d» будет «edx». Так, например, «push NULL» будет сассемблировано как «push dword 0», а «push d» как «push edx». А, например, в такой строке:

d equ d,eax

константе «d» будет присвоено новое значение «edx,eax». Таким образом могут определяться растущие списки символов.

«restore» позволяет присвоить назад предыдущее значение переопределенной константы. За ней должно следовать одно или больше имен символьных констант, разделенных запятыми. Так, «restore d» после предыдущего переопределения вернет константе значение «edx», следующее применение этой директивы вернет ей значение «dword», а ещё одно применение восстановит первоначальное значение, как будто такая константа не определялась. Если не константа с заданным именем не определена, то «restore» не вызовет ошибку, а будет просто проигнорирована.

1 2 3 4 5 6 7 8 9 10
Перейти на страницу:
На этой странице вы можете бесплатно скачать Flat Assembler 1.64. Мануал программера - Tomasz Grysztar торрент бесплатно.
Комментарии