Продолжая использовать наш сайт, вы даете согласие на обработку файлов cookie, которые обеспечивают правильную работу сайта. Благодаря им мы улучшаем сайт!
Принять и закрыть

Читать, слущать книги онлайн бесплатно!

Электронная Литература.

Бесплатная онлайн библиотека.

Читать: Flat Assembler 1.64. Мануал программера - Tomasz Grysztar на бесплатной онлайн библиотеке Э-Лит


Помоги проекту - поделись книгой:

 mov cx,count

 rep movsb

end if

Эти две инструкции будут ассемблированы только если константа «count» больше нуля. Следующий пример показывает более комплексную условную структуру:

if count & ~ count mod 4

 mov cx,count/4

 rep movsd

else if count>4

 mov cx,count/4

 rep movsd

 mov cx,count mod 4

 rep movsb

else

 mov cx,count

 rep movsb

end if

Первый блок инструкций ассеблируется, если константа «count» не равна нулю и кратна четырем, если это условие не выполняется, оценивается второе логическое условие, следующее за «else if», и если оно верно, ассемблируется второй блок инструкций, иначе ассемблируется последний блок, который следует за строкой, содержащей только «else».

Также есть операторы, которые позволяют сравнивать значения, которые представляют собой последовательности символов. «eq» проверяет такие значения на тождественность. Оператор «in» проверяет, принадлежит ли данное значение к списку значений, следующему за оператором. Список должен быть заключен между символами «<» и «>», а его члены должны быть разделены запятыми. Символы считаются одинаковыми, если они имеют одно и то же значение для ассемблера — например, «pword» и «fword» для ассемблера одинаковы поэтому не различаются вышеуказанными операторами. Так же «16 eq 10h» является истиной, однако «16 eq 10+4» нет.

Оператор «eqtype» имеют ли сравниваемые значения одинаковую структуру, и принадлежат ли структурные элементы одному типу. Различаемые типы включают в себя числовые выражения, строки, заключенные в кавычки, значения с плавающей точкой, адресные выражения (выражения в квадратных скобках или предваренные оператором «ptr»), мнемоники инструкций, регистры, операторы размера, операторы перехода и операторы типа кода. И каждый из специальных символов, действующих как разделители, такой как запятая или двоеточие, это отдельный тип сам по себе. Например, два значения, каждое из которых состоит из имени регистра и числового выражения, разделенных запятой, будут распознаны как один тип, независимо от вида регистра и сложности числового выражения; за исключением строк, заключенных в кавычки и значений с плавающей точкой, которые относятся к специальным видом числовых выражений и распознаются как разные типы. Поэтому условие «eax,16 eqtype fs,3+7» является истиной, но «eax,16 eqtype eax,1.6» — ложь.

2.2.2 Повторение блоков инструкций

«times» повторяет одну инструкцию указанное количество раз. За ней должно следовать числовое выражение, определяющее количество повторений, и инструкция, которую нужно повторять (опционально для того, чтобы отделить число и инструкцию, можно использовать двоеточие). Специальный символ «%», использующийся внутри инструкции, эквивалентен номеру текущего повтора. Например, «times 5 db %» определит пять байтов со значениями 1, 2, 3, 4, 5. Поддерживается также рекурсивное использование директивы «times», например, «times 3 times % db %» определит шесть байтов со значениями 1, 1, 2, 1, 2, 3.

«repeat» повторяет целый блок инструкций. За ней должно следовать числовое выражение, определяющее количество повторений. Инструкции для повторения предполагаются на следующих строках, а заканчиваться блок должен директивой «end repeat», например:

repeat 8

 mov byte [bx],%

 inc bx

end repeat

Сгенерированный код сохраняет байты со значениями от одного до восьми в памяти, адресованной регистром BX.

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

«break» позволяет остановить повторение раньше и продолжить ассемблирование с первой строки после «end repeat». В сочетании с директивой «if» она позволяет остановить повторение при выполнении некоторого особого условия, например:

s = x/2

repeat 100

 if x/s = s

  break

 end if

 s = (s+x/s)/2

end repeat

«while» повторяет блок инструкций, пока выполняется следующее за ней условие, определенное логическим выражением. Блок инструкций для повторения должен заканчиваться директивой «end while». Перед каждым повторением логическое выражение вычисляется и если его значение ложь, ассемблирование продолжается, начиная с первой строки после «end while». Также в этом случае символ «%» содержит номер текущего повторения. Директива «break» может быть использована для остановки этого типа цикла так же, как с директивой «repeat». Предыдущий пример может быть переписан с использованием «while» вместо «repeat» таким образом:

s = x/2

while x/s

 s

 s = (s+x/s)/2

 if % = 100

  break

 end if

end while

Блоки, определенные с использованием «if», «repeat» и «while» могут быть вложены в любом порядке, однако и закрыты в обратном. Директива «break» всегда останавливает обработку бока, который был начат последним либо директивой «repeat», либо «while».

2.2.3 Адресные пространства

«org» устанавливает адрес, по которому следующий за ней код должен появиться в памяти. За ней должно следовать числовое выражение, указывающее адрес. Эта директива начинает новое адресное пространство, следующий код сам по себе никуда не двигается, но все метки, определенные в нем и значение символа «$» изменяются как если бы он был бы помещен по этому адресу. Тем не менее обязанность поместить во время выполнения код по правильному адресу лежит на программисте.

«load» позволяет определить константу двоичным значением, загруженным из уже сассемблированного кода. За директивой должно следовать имя константы, затем опционально оператор размера, затем оператор «from» и числовое выражение, определяющее валидный адрес в текущем адресном пространстве. Оператор размера здесь имеет необычное значение — он определяет, сколько байтов (до 8) должно быть загружено из двоичного значения константы. Если оператор размера не определен, загружается один байт (таким образом значение оказывается в пределах от 0 до 255). Загруженные данные не могут превосходить текущее смещение.

«store» может модифицировать уже сгенерированный код заменой некоторых ранее сгенерированных байтов значением, задаваемым следующим за инструкцией числовым выражением. Перед этим выражением может идти оператор размера, определяющий, насколько длинное значение оно задает, то есть сколько будет сохранено байт. Если оператор размера не задан, подразумевается длина в один байт. Далее должен следовать оператор «at» и числовое выражение, указывающее валидный адрес в текущем адресном пространстве кода. По этому адресу будет сохранено задаваемое значение. Это директива для продвинутого применения и её следует использовать осторожно.

Обе директивы «load» и «store» ограничены оперированием только в пределах текущего адресного пространства. Символ «$$» всегда равен базовому адресу в текущем адресном пространстве, а символ «$» — это адрес текущей позиции в нём, то есть эти два значения определяют границы действия директив «load» и «store».

Сочетая директивы «load» и «store» можно делать вещи, такие как шифрование некоторого из уже сгенерированного кода. Например, для шифрования всего кода, сгенерированного в текущем адресном пространстве вы можете использовать такой блок директив:

repeat $-$$

 load a byte from $$+%-1

 store byte a xor c at $$+%-1

end repeat

и каждый байт коза будет проксорен со значением, определенным константой «c».

«virtual» определяет виртуальные данные по указанному адресу. Эти данные не будут включены в файл вывода, но но метки, определенные здесь, могут использоваться в других частях кода. За этой директивой может следовать оператор «at» и числовое выражение, определяющее адрес виртуальных данных, иначе будет использован текущий адрес, что равносильно директиве «virtual at $». Инструкции определяемых данных должны быть расположены на следующих строках и заканчиваться директивой «end virtual». Блок виртуальных инструкций сам по себе независимое адресное пространство, и после того, как оно заканчивается, восстанавливается контекст предыдущего адресного пространства.

Директива «virtual» может быть использована для создания объединения нескольких переменных, например:

GDTR dp?

virtual at GDTR

 GDT_limit dw?

 GDT_address dd?

end virtual

Здесь определяются две части 48-битной переменной по адресу «GDTR».

Директива также может быть использована для определения меток некоторых структур, адресованных регистром, например:

virtual at bx

 LDT_limit dw?

 LDT_address dd?

end virtual

С таким определением инструкция «mov ax,[LDT_limit]» будет сассемблирована в «mov ax,[bx]».

Также может быть полезно объявление инструкций и значений данных внутри виртуально блока, так как директиву «load» можно использовать для загрузки в константы значений из виртуально сгенерированного кода. Эта директива должна быть использована после загружаемого кода, но до окончания виртуального блока, так как она может загружать значения только из того же адресного пространства. Например:

virtual at 0

 xor eax,eax

 and edx,eax

 load zeroq dword from 0

end virtual

Этот кусок кода определяет константу «zeroq», которая будет содержать четыре байта машинного кода инструкций, указанных внутри виртуального блока. Этот метод также может быть использован для загрузки некоторых бинарных значений из внешнего файла. Например этот код:

virtual at 0

 file 'a.txt':10h,1

 load char from 0

end virtual

загружает один байт со смещением 10h из файла «a.txt» в константу «char».

Все директивы «section», описанные в 2.4, также начинают новое адресное пространство.

2.2.4 Другие директивы

«align» выравнивает код или данные по указанной границе. За ней должно следовать числовое выражение, определяющее количество байтов, на кратность которому должен быть выровнен текущий адрес. Значение границы должно быть степенью двойки.

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

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



Поделиться книгой:

На главную
Назад