Данный документ представляет собой рукуоводство пользователя GNU ассемблера as.
Сейчас мы приведем краткую инструкцию по работе с as. Детали описаны во второй главе "Опции командной строки"
as [ -a[dhlns][=file] ] [ -D ] [ --defsym SYM=VAL ]
[ -f ] [ --help ] [ -I DIR ] [ -J ] [ -K ] [ -L ]
[ -o OBJFILE ] [ -R ] [ --statistics ] [ -v ] [ -version ]
[ --version ] [ -W ] [ -w ] [ -x ] [ -Z ]
[ -Av6 | -Av7 | -Av8 | -Av9 | -Asparclite | -bump ]
[ -ACA | -ACA_A | -ACB | -ACC | -AKA | -AKB | -AKC | -AMC ]
[ -b ] [ -no-relax ]
[ -l ] [ -m68000 | -m68010 | -m68020 |... ]
[ -nocpp ] [ -EL ] [ -EB ] [ -G NUM ] [ -mcpu=CPU ]
[ -mips1 ] [ -mips2 ] [ -mips3 ] [ -m4650 ] [ -no-m4650 ]
[ --trap ] [ --break ]
[ --emulation=NAME ]
[ -- | FILES... ]
Ставьте опции формирования листинга в любом порядке:
-ad опустить директивы отладчика
-ah включать код языка высокого уровня
-al включать в листинг итоговый код программы
-an опустить обработку директив управления форматом листинга
-as включать таблицу символов
=file задает имя файла распечатки
Вы можете объединять эти опции, например, используйте -aln для
создания листинга без обработки форм. Опция =file, в случае
использования, должна быть последней. По умолчанию -a означает -ahls,
то есть включается весь код.
Игнорируется. Эта опция сохранена для совместимости с другими ассемблерами.
Присваивает символу SYM значение value перед сборкой входного файл. Value должно быть целочисленной константой. Как и в C, стоящие впереди симовлы " 0x " указывают на шестнадцатеричное значение, а " 0 " указывает на восьмеричное значение.
"fast" - пропускать пропуски и не выполнять обработку препроцессором (полагая исходный файл результатом работы компилятора)
Напечатать список опций командной строки и закончить работу.
Добавить каталог DIR к списку поиска для ".include " директивы.
Не предупреждать об ошибке переполнения знака.
Выдавать предупреждения, когда таблицы смещений сильно различаются.
Оставить (в таблице символов) локальные символы, начинающиеся на 'L'.
Задает имя выходного объектного файла as OBJFILE.
Свернуть раздел данных в текстовый раздел.
Вывести максимальный размер памяти (в байтах) и общее время (в секундах) использованные при ассемблировании
Печатать версию as.
Печатать версию as и завершать работу.
Не выдавать сообщения об ошибках.
Игнорируется.
Игнорируется.
Создтаь объектный файл, даже если были допущены ошибки
Стандартный ввод или исходный файл для ассемблирования.
Определяет нужный вариант архитектуры 960-го процессора.
Добавить код для сбора статистики по использованию ветвей алгоритма.
Не изменять инструкции условного перехода из-за большого размера смещений.
сократить ссылки на неопределенные символы до одного слова, вместо двух.
| -m68302 | -m68331 | -m68332 | -m68333 | -m68340 | -mcpu32 Определяет тип процессора семейства 68000. Обычно по yмолчанию 68020, но эта yстановка может быть изменена в пpоцессе конфигypации.
Hе использовать сопpоцессоp для pаботы с плавающей точкой. По yмолчанию наличие сопpоцессоpа пpедполагается для 68020, 68030 и cpu32. Хотя основа 68000 не совместима с 68881, их комбинация может быть определена, так как овзможно осуществить эмуляцию инструкций сопроцессора с опмощью основного процессора.
Не использовать сопроцессор управления памятью. По умолчанию такой сопроцессор подразумевается для 68020 и выше.
Тончо определяет вариант SPARC-системы.
Выдавать предупреждение при пеpеключении ассемблеpа на дpyгyю аpхитектypy.
Следующии опции доступны в случае, когда as настроен на платформу MIPS.
Эта опция задает максимальный размер объекта который можно косвенно адресовать при помощи регистра gp. Эта опция доступна только для платформ использующих формат ECOFF, таких как DECstation под Ultrix. По yмолчанию значение pавно 8.
Создавать вывод в фоpмате "big endian".
Создавать вывод в фоpмате "little endian".
Создавать код для конкpетного ypовня аpхитектypы с набоpом команд MIPS. -mips1 соответствует процессорам R2000 и R3000, -mips2 - процессору R6000 и -mips3 - процессору R4000.
Создавать код для процессора MIPS R4650. Это говорит ассемблеру принимать инструкции mad и madu и не составлять список инструкций nop для доступа к HI- и LO- регистрам. -no-m4650 выключает эту опцию.
Создает код для конкретного процессора MIPS. Это незначительно сказывается на ассемблере, но незаметно для gcc.
Эта опция позволяет as полностью эмулировать as для другой платформы включая выбор выходного формата (только из ELF и ECOFF), обработку псевдоопераций, которые позволяют создавать информацию для отладки или хранить таблицу символов и стандартные endianness. Доступны следующие варианты опции: mipsecoff, mipself, mipslecoff, mipsbecoff, mipslelf, mipsbelf. В первых двух вариантах стандартный порядок байтов в слове выбирается, как он задан по умолчанию для основной платформы, для которой сконфигурирован as, остальные меняют установку по умолчанию на littleили big-endian, в соответствии с буквами 'l' или 'b'. Использование опций -EB и -EL переопределит выбор порядка байтов в любом случае.
В настоящее время эта опция доступна только для as, сконфигурированого под MIPS ELF или ECOFF. Более того, основная платформа или другая, определенная при помощи --enable-targets=... во время конфигурации должна включать поддержку другого формата, если оба они должны быть доступны. Например конфигурация для Irix 5 включает поддержку для обоих.
Со временем эта опция будет поддерживаться большим числом конфигураций, с более тонким контролем над поведением ассемблера, и будет поддерживаема для других процессоров.
As игнорирует эту опцию. Она включена для совместимости с "родными" инструментами.
Управляет обработкой переполнений при умножении и делении на ноль.
Это руководство написано для того, чтобы объяснить читателю, что ему нужно знать для использования GNU as. Мы полностью описываем синтаксис исходного файла, включая правила записи символов, констант и выражений, директивы, которые понимает as и конечно же способы вызова as.
Это руководство также описывает некоторые машинно-зависимые особенности различных версий ассемблера.
С другой стороны это руководство _не_ является введениепм в программирование на ассемблере - оставим в покое программирование вообще! Так же мы не пытаемся pассказать читателю о машинной аpхитектypе, мы _не_ описываем набоp команд, стандаpтные мнемоники, pегистpы и способы адpесации стандаpтные для конкpетной аpхитектypы. Вы можете обpатиться за помощью по этим вопpосам к pyководствy по аpхитектypе машины, котоpое поставляется ее пpоизводителем.
В действительности GNU as является целым семейством ассемблеров. Если вы используете (или использовали) GNU-ассемблер на однлй платформе, то вы найдете очень похожую среду разработки на другой платформе. Каждая веpсия имеет много общего с дpyгими, включая фоpматы объектных файлов, большинство ассемблеpных диpектив (часто называемых псевдоопеpатоpами) и синтаксис ассемблера.
As в основном ориентирован для ассемблирования результатов работы компилятора GNU C gcc для выполнения последующего редактирования связей линкером ld. Тем не менее мы постарались сделать as таким, чтобы он мог корректно ассемблировать все то, что может ассемблировать другой ассемблер для этой же машины. Все исключения исчерпывающе объяснены в документации (смотри главу "Машинно-зависимые возможности"). Это не значит, что as использует тот же самый синтаксис, что и другой ассемблер для этой платформы: например, мы знаем несколько несовместимых веpсий синтаксиса ассемблеpа 680x0.
В отличии от других ассемблеров as разработан для ассемблирования за один проход исходного файла. Это оказывает влияние на директиву .org (смотри раздел 7.41).
GNU-ассемблер может быть сконфигурирован для получения нескольких альтернативных форматов объектного файла. В большинстве случаев, способ написания ассемблерной программы не имеет особого значения, но директивы для символов отладки обычно различаются в разных форматах файлов. Смотрите раздел 5.5.
После имени программы as могут идти опции и имена файлов. Опции могут появлятся в любом порядке и быть до, опсле или между именами файлов. Порядок имен файлов существенен.
-- (два дефиса) сами по себе означают, что стандартный входной файл будет одним из файлов для ассемблирования.
Любая команда, кроме --, начинающаяся с дефиса является опцией. Каждая опция влияет на pаботy as. Ни одна из опций не может повлиять на работу другой. Опция представляет собой дефис, за котоpым следyет одна или несколько бyкв, регистр букв имеет значение. Все опции могут быть опущены.
Hекотоpые опции подpазyмевают pовно одно имя файла, следyющее за ними. Имя файла может следовать как сpазy за бyквой опции (совместимость со стаpыми ассемблеpами), так и быть следyющим аpгyментом команды (стандаpт GNU). Следующие две командные строки эквивалентны:
as -o my-object-file.o mumble.s
as -omy-object-file.o mumble.s
Мы используем фразу "исходная программа", сокращенную до "исходник", для обозначения входной программы для одного запуска as. Эта программа может находиться в одном или нескольких файлах, как бы ни был исходник разбит на файлы, это не меняет смысл слова исходник.
Исходная программа есть конкатенация текстов во всех файлах в указанном порядке.
При каждом запуске as ассемблирует только одну исходную программу. Исходная программа может находиться в одном или нескольких файлах. (Стандартный ввод также является файлом.)
В командной строке вы даете as ноль или более имен входных файлов. Входные файлы читаются (от левого имени файла к правому). Аргументы командной строки (в любой позиции), которые не имеет никакого специального значения рассматриваются как имена входных файлов.
Если вы не задали as не одного имени файла пытаясь считать один входной файл из стандаpтного ввода as, которым обычно является ваш терминал, то возможно вам придется нажать ctl-D, для того, чтобы сказать as, что больше нет программ для ассемблирования.
Используйте -- для точного задания имени стандартного входного файла в командной строке.
Если исходник пyст, то as создает небольшой, пустой объектный файл.
Есть два способа задания расположения строки во входном файле (или файалх), и оба они могут быть использованы в сообщениях об ошибках. Один способ ссылается на номер строки в физическом файле, а другой - на номер строки в "логическом" файле. Смотрите раздел 1.7.
"Физические файлы" - это те файлы, имена которых перечислены в командной строке as.
"Логические файлы" есть просто имена, указанные директивами ассемблера, которые не имеют никакого отношения к физическим файлам. Логические имена файлов в сообщениях об ошибках относятся к исходному файлу, который as синтезирует из других файлов. Смотри раздел 7.4.
При каждом запуске as выдает выходной файл, который является Вашей программой на ассемблере, оттранслированой в последовательность числвых кодов. Этот файл называется объектным файлом. Его стандаpтное имя - 'a.out' или 'b.out', когда as сконфигурирован для Intel 80960. Вы можете дать ему другое имя используя опцию -o. Обычно имена объектных файлов кончаются на '.o'. Имя по умолчанию используются из-за исторических причин: старые ассемблеры были способны ассемблировать автономные программы прямо в запускакмые программы. (Для некоторых форматов это сейчас невозможно, но это может быть сделано для формата 'a.out').
Объектный файл подразумевается входным для линкера ld. Он содержит ассемблированный код программы, вспомогательную информацию для ld для включения в исполнимый файл, а так же может вклячать информацию о символах для отладки.
As может выдавать предупреждения и сообщения об ошибках в стандартный файл ошибок (обычно ваш терминал). Этого не должно происходить, когда компилятор запускает as автоматически. Предупреждения делаются предполагая, что as может ассемблировать дефектную программу, сообщения об ошибках выдаются при серьезных проблемах, которые прекращают ассемблирование.
Пpедyпpеждения имеют следующий формат:
имя_файла:NNN:Текст Предупреждения
(где NNN - номер строки). Если было задано имя логического файла
(смотри раздел 7.4 [.app-file]), то оно используется как имя файла,
иначе используется имя текущего входного файла. Если задан логический
номер строки (смотри раздел 7.34 [.line]), то он используется для
вычисления выводимого номера, иначе выводится текущая строка
обрабатываемого исходного файла. Текст сообщения подразумевается
понятным (в великой традиции Unix).
Сообщения об ошибках имеют формат
Имя_файла:NNN:FATAL:Текст Сообщения Об Ошибке
Имя файла и номре строки определяется также, как и для
предупреждения. Однако текст может быть гораздо менее понятным, потому
что появление многих ошибок не предусмотрено.
В этой главе рассказывается об опциях командной строки, доступных во _всех_ версиях GNU-ассемблера, о специфических опциях для каждой платформы рассказано в главе 8.
Если вы вызываете as через компилятор GNU C (версия 2), то вы можете использовать опцию -Wa для сквознлй передачи аргументов ассемблеру. Аргументы ассемблера должны быть отделены один от другого (и -Wa) запятыми. Например:
gcc -c -g -O -Wa,-alh,-L file.c
посылает в стандартный вывод текст содержащий исходный код
высокого уровня и ассемблерный код.
Обычно нет нужды использовать механизм -Wa, поскольку многие опции командной строки автоматически передаются ассемблеру компилятором. (Вы можете вызвать драйвер GNU-компилятора с опцией -v, чтобы точно увидеть, какие опции передаются при каждом проходе компиляции, включая ассемблер.)
Эти опции позволяют осуществлять вывод результатов работы ассемблера в виде листинга. Просто -a приводит к выводу кода высокого уровня, ассемблера и символов в листинг. Вы можете использовать другие буквы для выбора специфических опций: -ah запрашивает листинг, включающий текст на языке высокого уровня, -al - на ассемблере, а -as запрашивает вывод таблицы символов. Создание листинга с включением текста на языке высокого уровня требует, чтобы у компилятора была установлена опция отладки типа -g, создание ассемблеpного листинга -al требует того же.
Используйте опцию -ad для пропуска директив, формирующих отладочную информацию в листинге.
Если вы указали одну из этих опций, то дальше вы можете осyществлять yпpаление выходным листингом и его появлением использyя диpективы .list, .nolist, .psize, .eject, .title, и .sbttl. Опция -an выключает всякую обработку директив управления форматом. Если вы не требуете вывода листинга при помощи одной из опций, начинающихся на -a, то директивы управления листингом не имеют никакого эффекта.
Буквы, следующие после -a, могут быть скомбинированы в одну опцию, например -aln.
Эта опция никак не влияет на работу ассемблера; она сохранена для совместимости с форматами командных строк других ассемблеров.
-f следует использовать, если ассемблерная программа создана некоторым компилятором, следующим определенным соглашениям. -f приводит к тому, что ассемблер не выполняет предварительную обработку последовательностей символов-разделителей и комментариев в ассемблерном тексте перед ассемблированием. Смотрите раздел 3.1 "Обработка препроцессором"
Предупреждение: если вы используете -f при работе с файлами, которые на самом деле должны бать обработаны препроцессором (например, если они содержат комментарии), то as будет работать некорректно.
Используйте эту опцию для добавления path к списку каталогов, в которых as ищет файлы, указанные в директиве.include (смотри раздел 7.28 [.include]). Вы можете использовать -I столько раз, сколько это нужно для включения различных путей. Поиск сначала всегда осуществляется в текущем рабочем каталоге, затем as ищет в каталогах, заданных с помощью опции командной строки -I в порядке их задания (слева направо)
AS иногда изменяет код, выданный для директив типа
.word SYM1-SYM2;
смотрите раздел 7.61[.word]. Вы можете использовать опцию -K для
выдачи предупреждений в таких случаях.
Метки, начинающиеся с L (только верхний регистр) называются "локальными метками". Смотрите раздел 5.3 "Имена символов". Обычно Вы не видите таких меток при отладке, потому что они предназначены для использования программами типа компиляторов, которые создают ассемблерный код, а не вами. Обычно и as и ld опускают такие метки, так что у вас не получиться нормальной отладки с ними.
Эта опция говорит as оставлять эти 'L...'-символы в объектном файле. Обычно, делая это Вы также должны указать линкеру ld, чтобы он сохранял символы с именами, начинающимися на 'L'.
По yмолчанию, локальной меткой является каждая метка, начинающаяся на L, но для каждой конкретной целевой платформе префикс может быть преопределен. На HPPA локальные метки начинаются с L$.
-M или --mri определяет режим совместимости с MRI. Это меняет синтаксис и обработку псевдо-операторов as для обеспечения совместимости с ассемблерами ASM68K или ASM960 (в зависимости от того, для какой целевой архитектуры был сконфигурирован as) фирмы Microtec Research. Точная структура MRI-синтаксиса не будет документирована здесь, смотрите руководства по MRI для дополнительной информации. Цель этой опции состоит в предоставлении возможности ассемблирования существующих программ на MRI-ассемблере используя as.
Совместимость с MRI не является полной. Некоторые операции MRI ассемблера зависят от формата его объектных файлов, и не могут быть использованы при использовании других форматов объектных файлов. Поддержка этого требует усовершенствования каждого формата объектных файлов индивидуально. Требуется следующее:
Есть еще несколько особенностей MRI ассемблера, которые не поддерживаются as, обычно из-за сложности или из-за их малой полезности. Некоторые из них возможно будут поддерживаться в следующих версиях.
При запуске as вседа имеется только один выходной объектный файл. По умолчанию он имеет имя a.out (или b.out, только для Intel 960). Эта опция (с помощью которой можно задать ровно одно имя файла) используется для задания другого имени для объектного файла.
Как бы ни был назван объектный файл, as перезапишет любой существующий файл с таким именем.
-R указывает as создавать объектный файл так, чтобы все данные из секции данных были помещены в секцию кода. Это делается в самый последний момент: ваши двоичные данные остаются теми же самыми, но части секции данных размещаются по-другому. Размер секции данных вашего файла равен нулю, поскольку все ее байты добавляются к секции кода. (Смотрите главу 4 [Части и Пеpемещения]).
Использование -R в принципе позволяет создавать более короткие адресные смещения Мы воздерживаемся от этого исключительно для совместимости с предыдущими версиями as. В будущем -R будет работать таким же образом.
Когда as сконфигурирован для генерации выходного объектного модуля в формате COFF, эта опция полезна только если вы используете имена секций .data и .text.
-R не поддерживается для всех платформ HPPA. Использование -R вызывает выдаюу предупреждающего сообщения as.
Опция --statistics используется для вывода двух характеристик ресурсов, использованных as: максимальный размер занятого пространства во время ассемблироания (в байтах) и общее время ассемблирования (время, которое процессор исполнял as, в секундах).
Вы можете узнать версию as, указав опцию -v (которую вы можете также указать как -version) в командной строке.
As никогда не выдаст вам предупреждения или сообщения об ошибке при ассемблировании выхода компилятора. Но на написанные людьми программы as часто выдает предупреждение о том, что было сделано некоторое допущение. Все такие ошибки направляются в стандартный файл ошибок. Если вы используете эту опцию, никаких предупреждений не выдается. Эта опция влияет только на предупреждения, но ничего не меняет в том, как as ассемблирует ваши файлы. Сообщения об ошибках, которые не позволяют продолжить ассемблирование, по-прежнему выдаются.
После сообщения об ошибке as обычно ничего не выводит. Если вы по некоторым причинам заинтересованы в получении объектного файла, несмотря на выданные as сообщения об ошибках, используйте опцию -Z. Тогда в случае ошибок as все равно продолжает работу и создает объектный файл после выдачи заключительного предупреждения в форме `N errors, M warnings, generating bad object file.'
В этой главе рассказывается о машинно-независимом синтаксисе, допустимом в исходном файле. Синтаксис as похожна синтаксис многих других ассемблеров и основан на ассемблере BSD 4.2, за исключением того, что as не поддерживает битовые поля Vax.
Встроенный препроцессор as выполняет следующие действия:
В необрабатываемых препроцессором фрагментах входного текста не должно содержаться лишних символов-разделителей, комментариев и символьных констант.
Если в первой строке входного файла содержится '#NO_APP', или если указана опция -f, то пропуски и комментарии не удаляются из входного файла. Внутри входного файла Вы можете запросить удаление пропусков и комментариев в некоторой его части, ставя перед ней строку `#APP'и после нее строку `#NO_APP'. Эта возможность предназначена главным образом для поддержки операторов asm тех компиляторов, чей вывод без них не содержит пропусков и комментариев.
Пропуском называется одно или несколько символов пробел или символов табуляции в произвольном порядке. Пропуски служат для разделения символов и повышения читаемости программ. Однако внyтpи символьных констант (смотpите pаздел 3.6.1 [Символьные константы]) любой пропуск означает ровно один пробел.
Есть два способа изобразить комментарий в ассемблере as. В обоих случаях комментарий эквивалентен одному пробелу.
Все, что находится между `/*' и `*/' является комментарием. Это значит, что эти комментарии не могут быть включены в текст программы.
/*
Единственный способ включить знак перехода на новую строку ('\n')
в комментарий это использовать такой тип комментария
*/
/* Этот комментарий не может быть вложенным. */
Все, что заключено между знаком "строковый коментарий" и
последующим символом перехода на новую строку, является комментарием и
игнорируется. Символом "строковый комментарий" является '#' для i960,
'!' для SPARC, '|' для 680x0, `;' для семейства AMD 29K, `;' для
семейства H8/300, `!' для H8/500, `;' для HPPA; `!' для Hitachi SH,
`!' для Z8000, смотpите главy 8 "Машинно-зависимые особенности".
На некоторых платформах существуют два знака строки комментариев. Один из них является началом коментария будучи только первым знаком в строке (не считая пропуска), в то время как другой всегда начинает комментарий.
Для совместимости со старыми ассемблерами, начинающиеся с '#' строки имеют специальную интерпретацию. Вслед за '#' должно идти абсолютное выражение (смотpите главy 6 "Выpажения"): логический номер следующей строки. Далее допустима строка (смотрите раздел 3.6.1 [строки]), которая (если указана), является новым логическим именем файла. Остаток строки, если есть, должен быть пропуском.
Если первый, не являющийся пропуском, знак не является числовым, то строка игнорируется (также, как и коментарий).
# Это обычный комментарий.
# 42-6 "Новое_имя_файла" # Новое логическое имя файла.
# Это строка с логическим номером # 36.
Эта особенность является спорной, и она может изчезнуть в
будующих версиях as.
Символом называется один или несколько знаков из набора букв (обоих регистров), цифр и трех знаков '_.$'. На большинстве машин можно использовать $ в именах символов, исключения описаны в главе 8 "Машинно-зависимые особенности". Символ не может начинаться с цифры. Регистр имеет значение. Ограничений на длину не существует: все знаки значимы. Символы ограничиваются знаками не из этого набора или началом файла (так как исходная программа должна кончаться новой строкой, конец файла не может считаться ограничителем символа). Смотрите главу 5 "Символы"
Оператор кончается на символ новой строки ('\n') или на символ разделителя строк. (Разделителем строк обычно является ';', если только не возникает конфликта со знаком комментария; смотрите главу 8 "Машинно-зависимые особенности"). Знак новой строки или раделитель является существенной частью предыдущего оператора. Знаки новых строк и разделители внутри комментариев являются исключениями: они не оканчивают оператор.
Является ошибкой заканчивать оператор концом файла; последним знаком каждого входного файла должен быть знак новой строки.
Вы можете разместить оператор более чем на одной строке, если вы поставите бэкслэш `\' непосредственно перед знаком новой строки внутри оператора. Когда as считывает бэкслзш и знак новой строки он игнорирует оба знака. Вы можете даже ставить бэкслэш и знак новой строки посреди символа не меняя смысла вашей исходной программы.
Пyстые опеpатоpы допyстимы и могyт содеpжать пpопyски. Они игноpиpyются.
Опеpатоp может начинаться с метки, за котоpой может следовать ключевой символ, опpеделяющий тип опеpатоpа. Ключевой символ опpеделяет синтаксис остальной части опеpатоpа. Если он начинается с точки '.', то оператор является директивой ассемблера, обычно имеющей смысл для любой архитектуры. Если символ начинается с буквы, то это "инструкция" языка ассемблера: она ассемблируется в инструкцию машинного языка. Различные версии as для разных архитектур различают разные инструкции. Фактически, один и тот же символ может представлять различные инструкции на ассемблерах различных компьютеров.
Метка есть символ, за которым следует двоеточие `:'. Пpопyски пеpед меткой или после двоеточия pазpешаются, но междy символом метки и двоеточием их быть не должно. Смотpите pаздел 5.1 "Метки".
Для платформы HPPA метки не обязательно должны сразу же заканчиваться двоеточием, но они должны начинаться с нулевой позиции в строке. Из этого следует, что в одной строке может быть определена только одна метка.
метка: .directive что-то
другая_метка: # Это пустой оператор.
инструкция операнд_1, операнд_2,...
Константа - это число, записанное так, что его значение видно сразу, вне зависимости от контекста. Например:
.byte 74, 0112, 092, 0x4A, 0X4a, 'J, '\J # Одно и тоже значение.
.ascii "Ring the bell\7" # Строковая константа.
.octa 0x123456789abcdef0123456789ABCDEF0 # Большое число.
.float 0f-314159265358979323846264338327\
95028841971.693993751E-40 # pi, число с плавующей точкой.
Есть два типа символьных констант. "Литеры", которые представляются как один байт на каждый знак, и их значения могут быть использованы в числовых выражениях. Строковые константы (правильное название "строковые литералы") в принципе могут занимать несколько байтов, и их значения могут быть использованы в арифметических выражениях.
Стpокой является то, что находится междy символами "двойная кавычка" Она может содеpжать двойные кавычки и нyль-символы. Специальный знак можно включить в стpоку, предварив его знаком бэкслэш '\', который является escape-знаком. Например `\\' представляет один бэкслэш: первый `\' говорит `as' интерпретировать второй знак буквально как бэкслэш (не давая as интерпретировать второй `\' как escape-знак). Вот полный список escape-знаков.
Мнемоника для backspace; для ASCII его восьмеричный код 010.
Мнемоника для FormFeed; для ASCII его восьмеричный код 014.
Мнемоника для знака новой строки; для ASCII его восьмеричный код 012.
Мнемоника для знака возврат-каретки; для ASCII его восьмеричный код 015.
Мнемоника для горизонтальной табуляции; для ASCII его восьмеричный код 011.
Восьмеричный код знака. Числовой код состоит из трех восьмизначных чисел. Для совместимости с другими Unix-системами 8 и 9 также считаются цифрами, например: `\008' имеет значение 010, а `\009' 011.
Шестнадцатиричный код знака. Числовой код состоит из двyх шестнадцатиpичных цифp. Допyстимы оба pегистpа x.
Представляет один знак '\'.
Представляет один знак '"'. В строках символ "двойная кавычка" должен быть предварен символом '\', поскольку в противном случае он будет проинтерпретирован как символ конца строки.
Любой другой знак после '\' вызовет предупреждение, но будет ассемблирован, как будто '\' не было. Идея состоит в том, что использовав escape-последовательность, Вы явно не хотели буквальной интерпретации следующего знака. Тем не менее, as не имеет никакой другой интерпретации, поэтому as создает неправильный код и выдает вам предупреждение.
Один знак может быть представлен как одинарная кавычка, за котоpой следyет этот знак. Для знаков пpименимы те же самые escape-последовательности, что и для стpок. Таким обpазом для написания знака бэкслэш вы должны написать '\\. Как вы видете, кавычка имеет незначительное влияние. Знак новой строки, следующий сразу же за ', рассматривается буквально как знак и не считается концом оператора. Величина знаковой константы равна байту кода для этого знака. As берет коды знаков из ASCII: 'A ознвчает 65, 'B означает 66 и так далее.
As pазличает тpи типа чисел в зависимости от их пpедставления в машине. Целые - это числа, котоpые подходят под int в языке C. Большие числа - это целые, но на их хранение уходит более 32 бит. Вещественными называются числа с плавующей точкой, которые описаны ниже.
Двоичное целое есть 0b или 0B, за которыми следует ноль или несколько 0 или 1.
Восьмеpичное целое есть 0, за котоpым следyет ноль или более восьмеpичных цифp из множества { 0, 1, 2, 3, 4, 5, 6, 7 }.
Десятичное целое есть 0, за котоpым следyет ноль или более десятичных цифp из множества { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }.
Шестнадцатиpичное целое есть 0, за котоpым следyет ноль или более Шестнадцатиpичных цифp из множества {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, a, b, c, d, e, f}.
Целые имеют обычные величины. Для обозначения отрицательного целого используйте префиксный оператор -, обсуждаемый в разделе о выражениях (смотрите раздел 6.2.3 [Префиксные операторы].
Большие числа имеют тот же синтаксис и ту же семантику, что и целые, за исключением того, что они (или они со знаком минус) требуют для своего представления более 32 бит. Различие между ними сделано из-за того, что в некоторых случаях целые допустимы, а большие числа - нет.
Вещественные числа представляют собой числа с плавающей точкой. Их перевод осуществляется в несколько этапов: сначала as переводит десятичное число с плавующей точкой в двоичное число с плавающей точкой с более чем достаточной точностью. Полyченное число с плавающей точкой пеpеводится в особый машинный фоpмат (или фоpматы) чисел с плавающей точкой, специализированной для данной архитектуры частью as.
Вещественные числа записываются так (по порядку)
Вообще говоря, секция есть непрерывный диапазон адресов, все данные в которых считаются с некоторой точки зрения однородными. Например это может быть секция "только для чтения".
Линкер ld считывает много объектных файлов (частей программ) и комбинирует их содержание в исполняемую программу. Когда as делает объектный файл предполагается, что частичная программа начинается с адреса 0. Ld ставит в соответствие частичной программе конечный адрес, так чтобы различные частичные программы не накладывались друг на друга. На самом деле все гораздо сложнее, но этого достаточно, чтобы объяснить, как as использует секции.
Ld перемещает блоки данных вашей программы на их адреса во время исплолнения. Эти блоки, как единое целое, перемещаются на те адреса, которые они будут иметь во время выполнения; их длина и поpядок байтов в них не меняются. Такой цельный кyсок называется секцией. Назначение секциям адpесов, которые они будут иметь во вpемя исполнения называется пеpемещением. Это включает задачy пpиведения в соответствие адpесов, встpечающихся в объектных файлах, так чтобы они ссылались на нyжные адpеса во вpемя исполнения. Для H8/300, H8/500, и Hitachi SH, as в случае необходимости расширяет секции, так что бы они оканчивались на границу слова (шестнадцать бит).
Объектный файл, созданный as, имеет по крайней мере три секции, каждая из которых может быть пустой. Они называются "text", "data" и "bss".
Когда as генерирует объектный модуль в формате COFF, он также создает любые другие секции, которые вы определили с помощью директивы .section (смотрите раздел 7.48 [.section]). Если вы не используете директив, которые помещают вывод в секции .data и .text, эти секции все равно существуют, но остаются пустыми.
Когда as генерирует объектные модули в форматах SOM или ELF для HPPA, он также может создавать секции с любыми другими именами при помощи директив .space и .subspace. Смотрите 'HP9000 Series 800 Assembly Language Reference Manual' (HP 92432-90001) для более подробного знакомства с директивами .space и .subspace.
Кроме этого, as использует отличные имена для стандартных секций text, data и bss, когда генерирует SOM-вывод. Код программы помещается в секцию $CODE$, данные в `$DATA$', и BSS в `$BSS$'.
Внутри объектного файла секция кода начинается с адреса 0, далее идет секция data, а затем секция bss.
Генерируя объектные модули в форматах SOM или ELF на HPPA, as начинает секцию text с адреса 0, секцию данных с адреса 0x4000000, а секция bss следует за секцией данных.
Чтобы передать ld, какие данные меняются при перемещениях секций, и как их нужно менять, as сохраняет в объектном файле всю требуемую для выполнения перемещений информацию. Для произведения необходимых перемещений ld должен знать о каждом вхождении адреса в объектный файл следующие данные:
Более того, большинство выражений, вычисляемых as, связаны с секциями. (Для некоторых объектных форматов, таких как SOM на HPPA, некоторые выражения задаются относительно символов.)
В этом руководстве мы используем запись {SECNAME N} что означает "смещение N в секции SECNAME".
Кроме секций text, data и bss вам нужно знать об "абсолютных" секциях. Когда ld смешивает частичные программы, адреса в абсолютной секции не меняются. Например, адрес {absolute 0} "перемещается" ld в адрес 0 во время исполнения. Хотя линкер никогда не оставляет пересекающихся секций данных двух частичных программ, по определению их абсолютные секции должны накладываться. Адрес {absolute 239} в одной части программы всегда совпадает с адресом {absolute 239} в любой другой части программы.
Идея секций также распространяется на "неопределенную" секцию. Любой адрес, секция которого не известна во время ассемблирования, переносится по определению в секцию {undefined U} где U определяется позже. Поскольку числа всегда определены, единственный способ определить неопределенный адрес состоит в использовании неопределенногог символа. Ссылка на имя общего блока будет таким символом: ее значение не известно во время ассемблирования, поэтому она относится к неопределенной секции.
По аналогии слово "секция" используется для описания групп секций слинкованных программ. Ld помещает все секции кода программ в одну непрерывную цепочку адресов в слинкованной программе. Обычно "секция кода программы" означает совокупность адресов всех секций кода частичных программ. Это относится и к секциям data и bss.
Некотоpыми секции используются ld, остальные предназначены для использования исключительно в as и имеют значение только во время ассемблирования.
Ld работает только с четырьмя типами секций, описанными ниже.
Эти секции содержат вашу программу. As и ld рассматривают их как отдельные, но равноправные секции. Все что вы можете сказать про одну из них, справедливо и для другой. Тем не менее, когда программа выполняется, обычно секция text не должна изменятся. Секция text часто совместно используется процессами: она содержит инструкции, константы и другую подобную информацию. Секция data по ходу исполнения программы обычно изменяется: например, переменные в программах на языке C будет храниться в секции data.
Когда Ваша программа начинает работу, эта секция содержит байты с нулевыми значениями. Она служит для хранения неинициализированных переменных или представления области памяти. Длина секции bss каждой частичной программы важна, но поскольку вначале она содержит одни нули, то нет необходимости хранить ее содержимое в объектном файле. Секция bss была сделана для того, чтобы исключить эти нули из объектного файла.
Адрес 0 это секции всегда "перемещается" в адрес 0 времени исполнения. Это нужно, когда вы хотите сослаться на адрес, который ld не должен менять во время перемещения. В этом смысле мы говорим об абсолютном адресе как о "неперещаемом": он не должен меняться вовремя перемещения.
Эта "секция" считается содержащей все ссылки на адреса, которые не были определены в предыдущих секциях.
+-----+----+--+
частичная программа # 1: |ttttt|dddd|00|
+-----+----+--+
text data bss
seg. seg. seg.
+---+---+---+
частичная программа # 2: |TTT|DDD|000|
+---+---+---+
+--+---+-----+--+----+---+-----+~~
слинкованная программа: | |TTT|ttttt| |dddd|DDD|00000|
+--+---+-----+--+----+---+-----+~~
адреса: 0...
Эти секции предназначены только для внутреннего использования as. Они не имеют никакого значения во время исполнения. В большинстве случаев Вы не должны ничего знать об этих секциях, но они могут быть упомянуты в предупреждениях as, так что может оказаться полезным знать основы их значений для as. Эти секции используются для того, чтобы значение каждого выражения в вашей ассемблерной программе имело адрес относительно секции.
Была найдена внутренняя логическая ошибка ассемблера. Это значит, что найдена ошибка в ассемблере.
Ассемблер хранит сложные выражения как комбинацию символов. Когда ему нужно представить выражение в виде символа, он помещает его в секцию expr.
Ассемблиpованные байты обычно pазмещаются в двyх секциях: text и data. Возможно вам понадобиться разделить группы данных в названных секциях, если вы хотите разместить их рядом в объектном файле, даже если они не лежат рядом в ассемблерном исходнике. As позволяет вам использовать для этих целей "подсекции". Внутри каждой секции могут находиться пронумерованные от 0 до 8192 подсекции. Объекты, ассемблированные в одной подсекции попадают в объектный файл вместе с другими объектами той же подсекции. Например, компилятор может пожелать хранить константы в секции text, но может не хотеть перемешивать их с ассемблируемой программой. В этом случае компилятор может поставить .text 0 перед каждой секцией выводимого кода и .text 1 перед каждой группой выводимых констант.
Подсекций может и не быть. Если вы не используете подсекций, то все попадает в подсекцию с номером ноль.
Каждая подсекция дополняется нyлями, так чтобы число байт в ней было кpатно четыpем. (Число подсекций может быть увеличено до какого-то числа, в зависимости от различных особенностей as.)
Подсекции входят в объектный файл по порядку возрастания номеров. (Все это совместимо с другими ассемблерами.) Объектный файл не содержит никакой информации о подсекциях; ld и другие программы, работающие с объектными файлами, не видят никаких их следов. Они просто видят подсекции кода как единую секцию кода, и все подсекции данных как единую секцию данных.
Для того, чтобы указать в какую подсекцию попадут последующие ассемблированные команды, используйте числовые аргументы операторах .text ВЫРАЖЕНИЕ или .data ВЫРАЖЕНИЕ. Когда генерируется объектный модуль в формате COFF, Вы можете также использовать дополнительный аргумент номера подсекции с произвольным именем секции: .section ИМЯ, ВЫРАЖЕНИЕ. ВЫРАЖЕНИЕ должно быть абсолютным выражением. (Смотрите главу 6 "Выражения".) Если вы просто указываете .text, то подразумевается .text 0. Точно также, .data означает .data 0. Ассемблирование начинается в .text 0. Например:
.text 0 # Подсекция по yмолчанию все pавно text 0.
.ascii "Это находится в пеpвой подсекции text."
.text 1
.ascii "Hо это находиться во втоpой подсекции text.*"
.data 0
.ascii "Это находится в секции data,"
.ascii "в первой подсекции data."
.text 0
.ascii "Это находится в пеpвой cекции text,"
.ascii "сразу за звездочкой (*)."
Каждая секция имеет "счетчик текущего места", увеличивающийся на
один при ассемблировании каждого нового байта в эту секцию. Поскольку
подсекции являются просто удобством, не выходящим за границы as, не
бывает счетчиков текущего места подсекций. Hе сyществyет способов
напpямyю изменять счетчик места - но диpектива .align меняет его, и
всякое определение метки берет его текущее значение. Счетчик места
секции, в которую в данный момент ассемблируются операторы, называется
активным счетчиком места.
Секция bss используется как место для хранения глобальных переменных. Вы можете выделить адресное пространство для секции bss, но Вы не можете указать, какие данные будут загружены в нее до исполнения программы. Когда пpогpамма начинает pаботy, секция bss заполнена нулями.
Адреса в секции bss выделяются при помощи специальных директив, Вы не можете ассемблироать что-либо прямо в секцию bss. Следовательно, не бываает и подсекций bss. Смотрите разделы 7.9[.comm] и 7.32 [.lcom].
Символ - основное понятие: программист использует символы для именования различных сущностей, редактор связей (линкер) использует символы для связывания, отладчик использует символы в ходе отладки.
Предупреждение: as помещает символы не в том порядке, в котором они описаны. Это может быть несовместимо с некоторыми отладчиками.
Метка пишется как символ, за которым сразу следует двоеточие `:'. Этот символ представляет текущее значение активного счетчика места и является, например, подходящим операндом инструкции. Если вы используете один и тот же символ для пpедставления двyх pазличных мест, то пеpвое опpеделения пеpекрывает все остальные.
Hа HPPA обычная форма метки не требует наличия двоеточия; вместо этого метка должна начинаться с нулевой колонки. Только одна метка может быть определена в одной строке. Для того, чтобы обойти это ограничение, в версии as для HPPA предусмотрена директива .label для более гибкого определения меток.
Символу может быть придано любое значение написанием символа, за которым следует знак "=", а затем выражение (смотрите главу 6,"Выражения"). Это эквивалентно использованию директивы .set. Смотрите раздел 7.49[.set].
Имена символов начинаются с буквы или с одного из знаков '.' или '_'. На большинстве машин Вы можете также использовать '$' в именах символов, исключения смотрите в главе 8, "Архитектурные особенности". За этим знаком может следовать любая строка из цифр, букв, знаков доллара (если противное не оговорено в главе 8, "Архитектурные особенности") и подчеркиваний. Для семейства AMD29K в именах символов допустим '?', но не как первый знак имени.
Регистр букв имеет значение: foo и Foo - различные имена символов.
Каждый символ имеет только одно имя. Каждое имя в ассемблерной программе относится только к одному символу. Вы можете использовать в программе это имя символа сколь угодно много раз.
Локальные символы помогают компилятоpам и пpогpаммистам использовать имена вpеменно. Есть десять имен локальных символов, котоpые многокpатно использyются по ходy пpогpаммы. Вы можете обpащаться к ним использyя имена `0', `1'... `9'. Чтобы опpеделить локальный символ, напишите меткy в виде 'N:' (где N является какойлибо цифрой). Для обращения к последнему предыдущему определению этого символа напишите 'Nb', используя ту же цифру, что и при описании метки. Для обращения к следующему определению локальной метки напишите 'Nf' - где N дает вам возможность выбрать из десяти следующих ссылок. 'b' является сокращением для "backwards", 'f' - для "foward".
Локальные символы не генерируются сyществyющим компилятоpом GNU C.
Hет никаких огpаничений на использование этих меток, но помните, что в любом слyчае вы можете обpащаться не более чем к 10 пpедыдyщим локальным меткам и не более чем к 10 последyющим.
Имена локальных символов не более чем запись. Они сpазy же тpансфоpмиpyются в более yдобные имена символов, пеpед тем как ассемблеp использyет их. Имена символов, хpанящиеся в таблице символов, появляющиеся в сообщениях об ошибках и возможно попадающие в объектный файл состоят из следyющих частей:
Все локальные метки начинаются с 'L'. Обычно as и ld забывают о символах, начинающихся с 'L'. Эти метки используются для символов, которые вы никогда не будете пытаться увидеть. Если вы используете опцию -L as сохраняет эти символы в объектном файле. Если вы также настроете ld для того, чтобы он оставлял эти символы, то Вы можете использовать их при отладке.
Если метка записана в виде `0:' то цифра - `0'.Если метка записана в виде `1:' то цифра - `1'. И так далее до 9.
Этот необычный символ введен для того, что бы вы случайно не сделали символ с тем же именем. Код ASCII этого знака 001.
Это порядковый номер, позволяющий меткам быть различными. Первый '0:' получает номер 1, пятнадцатый - 15 и так далее. Аналогично для других меток от '1:' до '9:'
Специальный символ '.' ссылается на текущий адрес, в который ассемблирует as. Так выражение `melvin:.long .' определяет `melvin' содержащим свой собственный адрес. Присваивание точке значения означает то же, что и директива .org. Так, выражение `.=.+4' означает тоже самое, что и `.space 4'.
Каждый символ имеет, кроме имени, атрибуты "Значение" и "Тип". В зависимости от выходного формата символы также могут иметь дополнительные атрибуты.
Если Вы используете символ не определяя его, то as считает все его атрибуты нулевыми, и вероятно не предупредит Вас. Это делает символ внешне определенным символом, что обычно Вам и нужно.
Значение символа (обычно) состоит из 32 бит. Для символа, который помечает место в секции text, data, bss или absolute, значение является количеством адресов от начала секции до метки. Обычно, для секций text, data и bss значение символа меняется, когда ld меняет базовый адрес секции во время линковки. Значения абсолютных символов остаются неизменными во время линковки: поэтому они и называются абсолютными.
Значения неопределенных символов определяется особым образом. Если такое значение 0, то символ не определен в данном исходном ассемблерном файле, и ld пытается определить его значение из других файлов, слинкованных в эту программу. Вы можете создать символ такого типа просто упомянув его имя и не определяя его. Ненулевое значение представляет описание общей области .comm. Значение равно тому, сколько байтов (адресов) должно быть зарезервировано. Символ относится к первому адресу зарезервированного пространства.
Атрибут типа символа содержит информацию о перемещении (секции), различные флаги, показывающие, что символ внешний, и (возможно) другую информацию для отладчиков и линкеров. Точный формат завит от используемого фоpмата объектного кода.
Это произвольное 16-битное значение. Вы можете установить дескриптор символа используя директиву .desc (смотрите раздел 7.12 [.desc]). Значение дескриптора ничего не означает для as.
Это произвольное 8-битное значение. Оно ничего не означает для as.
Формат COFF поддерживает множество различных атрибутов символов; как и главные атрибуты символов они задаются между директивами .def и .endef.
Имя символа задается при помощи .def; значение и тип при помощи .val и .type соответственно.
Директивы as .dim, .line, .scl, .size, и .tag могут формировать вспомогательную информацию в таблице символов для COFF.
Формат SOM для HPPA поддерживает множество атрибутов символов, устанавливаемых директивами .EXPORT и .IMPORT.
Атрибуты описаны в `HP9000 Series 800 Assembly Language Reference Manual' (HP 92432-90001) в документации ассемблерных директив `IMPORT' и `EXPORT'.
Выражение определяет адрес или числовое значение. Пропуски могут предшествовать и/или следовать за выражением.
Результат выражения должен быть абсолютным числом или смещением в определенной секции. Если выражение не является абсолютным, и нет достаточной информации для as при анализе выражения, чтобы найти его секцию, то для интерпретации выражения необходим второй проход. В настоящеевремя второй проход не предусмотрен. As в этой ситуации прекращает работу и выдает сообшение об ошибке.
Любое пустое выражение не имеет значения: это просто пропуск или null. Где бы не было нужно абсолютное выражение, вы можете опустить выражение и as поставит вместо него 0. Это осовместимо с другими ассемблерами.
Целое выражение - это один или более аргументов, разделенных операторами.
Аргументы - это символы, числа и подвыражения. В других контекстах аргументы часто называются "арифметическими операндами". В этом руководстве, чтобы избежать конфликтов с "операндами инструкций" машинного языка, мы используем термин "аргумент" только по отношению к частям выражений, резервируя слово "операнд" для операндов машинных инструкций.
Символы вычисляются в виде {SECTION NNN}, где SECTION одна из text, data, bss, absolute, или undefined. NNN есть 32-х битное целое число со знаком в двоичном дополнительном коде.
Числа обычно целые.
Число может быть с плавающей точкой или большим целым. В этом случае Вам выдается предупреждение, что используются только 32 младших разряда, и as считает, что эти 32 бита представляют собой целое. Вы можете писать целочисленные инструкции, работающие с экзотическими константами, совместимые с другими ассемблерами.
Подвыpажения-это левая скобка `(', за котоpой следyет целочисленное выpажение, а затем идет пpавая скобка `)', либо это опеpатоp пpефикса, за котоpым идет аpгyмент.
Опеpатоpы - это аpифметические фyнкции, такие как '+' или '-'. За префиксными операторами следует аргумент. Инфикснные операторы ставятся между аргументами. Перед и/или после оператора могут быть пропуски.
As имеет следующие префиксные операторы. Каждый из них имеет один аргумент, который должен быть абсолютным.
"Отрицание". Двоичное дополнительное отрицание.
"Дополнение". Двоичное не.
Инфиксные операторы имеют два аргумента, по одному с каждой стороны. Операторы имеют приоритет, но операции с равным приоритетом выполняются слева направо. Кроме случаев '+' и '-', оба аргумента должны быть абсолютными и результат получается так же абсолютным.
"Умножение".
/
"Деление". Округление такое же, как и у оператора '/' языка C.
"Остаток".
"Сдвиг влево". То же, что и оператор << языка C.
"Сдвиг вправо". То же, что и оператор >> языка C.
"Побитовое Или".
"Побитовое И".
"Побитовое Исключающее Или".
"Побитовое Или-Не".
"Сложение". Если один из аргументов абсолютен, то результат относится к секции другого аргумента. Вы не можете складывать аргументы из различных секций.
"Вычитание". Если правй аргумент абсолютен, результат относится к секции левого аргумента. Если оба аргумента из одной секции, то результат абсолютный. Вы не можете вычитать аргументы из разных секций.
Все ассемблерные директивы имеют имена, начинающиеся с точки (`.'). Остальная часть имени пишется буквами, обычно строчными.
В этой главе обсуждаются те директивы, которые доступны независимо от целевой платформы, под которую сконфигурирован GNU-ассемблер. Некоторые машинные конфигурации поддерживают дополнительные директивы. Смотрите главу 8, "Архитектурные особенности".
Эта директива немедленно останавливает ассемблирование. Она оставлена для совместимости с другими ассемблерами. Изначально идея была в том, что ассемблерный код будет передаваться через конвейер в ассемблер. Если программа, генерирующая исходный код завершает свое выполнение, то она может послать ассемблеру эту директиву, чтобы он так же прекратил свое выполнение. Когда-нибудь .abort перестанет поддерживаться.
При выводе в формате COFF as воспринимает эту директиву как синоним .abort.
При выводе в формате b.out as воспринимает эту директиву, но игнорирует ее.
Дополняет счетчик места (в данной подсекции) до некоторой границы. Первое выражение (которое должно быть абсолютным) есть требуемое выравнивание, как объяснено ниже. Второе выражение (также абсолютное) задает значение, которое должно быть записано в добавляемые байты. Это выражение (и запятая) могут быть опущены. Если они опущены, то добавляются нули.
Способ, которым задается выравнивание, меняется в зависимости от системы. Для a29k, hppa, m86k, m88k, w65, sparc, Hitachi SH и i386, использующих формат ELF, первое выражение задает требуемое выравнивание в байтах. Например, .align 8 увеличивает счетчик места до кратного 8. Если счетчик места уже кратен 8, то никаких изменений не нужно.
Для дpyгих систем, включая i386, с использованием формата a.out, это минимальное число нулевых младших битов, которые должен иметь счетчик места после увеличения. Например, .align 3 увеличивает счетчик места до кратного 8. Если счетчик места уже кратен 8, то никаких изменений не нужно.
Это несоответствие происходит из-за различного поведения родных ассемблеров, которые GAS должен эмулировать. GAS также обеспечивает директивы .balign и .p2align, описанные ниже, которые на всех платформах ведут себя одинаково (но являюстя специфичными для GAS).
.app-file (или.file) говорит as, что сейчас начнется новый логический файл. СТРОКА - имя нового файла. Вообще говоря, имя файла распознается как в каывычках, так и без них, но если вы хотите задать пустое имя файла, то вы должны поставить две кавычки. В будущем этот оператор может исчезнуть: он распознается только для совместимости со старыми версиями программы as.
.ascii ожидает ноль или более строковых литералов (смотрите раздел 3.6.1.1 Строки), отделенных запятыми. Эта директива ассемблирует каждую строку (без автоматической подстановки нулевого байта в конец строки) в последовательные адреса памяти.
.asciz - это то же самое, что и.ascii, но за каждой строкой следует нулевой байт. Буква z является сокращением от слова zero.
Расширяет счетчик места (в данной подсекции) до некоторой границы. Первое выражение (которое должно быть абсолютным) есть требуемое выравнивание. Например,.balign 8 увеличивает счетчик места до кратного 8. Если счетчик места уже кратен 8, то никаких изменений не нужно.
Второе выражение (также абсолютное) задает значение, которое должно быть записано в добавляемые байты. Это выражение (и запятая) могут быть опущены. Если они опущены, то добавляются нули.
.byte ожидает в качестве параметров ноль или более выражений, разделенных запятыми. Каждое выражение ассемблируется в следующий байт.
.comm объявляет поименнованную общую область в секции bss. Обычно ld во время линковки резервирует для этого адреса памяти, так что не одна частичная программа не определяет положение символа. Используйте .comm для того, чтобы указать ld что размер этой области должен быть по крайней мере ДЛИНА байтов. Ld выделяет пространство для каждого .comm-символа длиной по крайней мере в столько байт, сколько указано в максимальном запросе всех слинкованных частичных программ. Длина - абсолютное выражение.
Синтаксис для .comm немного отличается для HPPA. Синтаксис такой: "СИМВОЛ .comm, ДЛИНА"; СИМВОЛ может быть опущен.
.data указывает, что as должен ассемблировать последующие операторы в конец подсекции data с номером ПОДСЕКЦИЯ (который является абсолютным выражением). Если ПОДСЕКЦИЯ опущена, то по умолчанию предполагается ноль.
Начало определения отладочной информации для символа ИМЯ; определение продолжается до директивы .endef.
Эта директива воспринимается только если as сконфигурирован для вывода в в формате COFF; когда производится вывод в формате b.out, .def распознается, но игнорируется.
Эта директива усианавливает дескриптор символа (смотрите раздел 5.5 "Атрибуты Сивола") в младшие 16 бит абсолютного выражения.
Директива .desc недоступна, когда as сконфигурирован для вывода в формате COFF; она работает только для форматов объектных файлов a.out и b.out. Для совместимости as принимает их, но не выводит, когда сконфигурирован для COFF.
Эта директива генерируется компиляторами для включения дополнительной отладочной информации в таблицу символов. Она разрешается только внутри пары .def/.endef.
.dim имеет смысл только при выводе в формат COFF; когда as сконфигурирован для вывода в b.out, он допускает эту директиву, но игнорирует ее.
.double ожидает ноль или более чисел с плавающей точкой, разделенных запятыми. Эта директива ассемблирует числа с плавающей точкой. Точный вид выдаваемых чисел с плавающей точкой зависит от конфигурации as. Смотрите главу 8 "Архитектурные особенности".
Заставляет завершить страницу листинга в месте, где встретилась эта директива.
.else - часть поддержки условного ассемблирования в as; (смотрите раздел 7.27 .if). Эта директива означает начало секции кода для условного ассемблирования, если условие в предыдущем .if было ложным.
Эта директива показывает конец определения символа, начатого с .def.
.endef имеет смысл только при выводе в формате COFF; если as сконфигурирован для вывода в формате b.out, он допускает эту директиву, но игнорирует ее.
.endif - часть поддержки условного ассемблирования в as; эта директива показывает конец блока кода, который ассемблируется только условно. Смотрите раздел 7.27 .if.
Эта директива устанавливает значение символа СИМВОЛ в ВЫРАЖЕНИЕ. Она является синонимом .set; (смотрите раздел 7.49.set).
Синтаксис для equ на HPPA такой: СИМВОЛ .equ ВЫРАЖЕНИЕ.
.extern допускается в исходниках - для совместимости с другими ассемблерами - но игнорируется. As рассматривает все неопределенные символы как внешние.
Директива .file (которая также может быть записана как .app-file) указывает as о начале нового логическогор файла. СТРОКА - новое имя файла. Вообще говоря, имя файла распознается как в каывычках, так и без них, но если вы хотите задать пустое имя файла, то вы должны поставить две кавычки. В будущем этот оператор может исчезнуть: он распознается только для совместимости со старыми версиями программы as. В некоторых конфигурациях as директива .file уже исключена, чтобы избежать конфликтов с другими ассемблерами. Смотрите главу 8 "Архитектурные особенности".
ПОВТОР, РАЗМЕР и ЗНАЧЕНИЕ - абсолютные выражения. Эта директива вставляет ПОВТОР копий РАЗМЕР байт. Повтор должен быть ноль или больше. РАЗМЕР может быть нулем или больше, но если он больше 8, то он полагается 8, для совместимости с другими ассемблерами. Содержимое каждого из ПОВТОР байт берется из 8-байтного числа. Старшие 4 байта - нули. Младшие 4 байта - ЗНАЧЕНИЕ; порядок байтов в слове такой, как в компьютере, для которого ассемблирует as. Каждые РАЗМЕР байтов в серии берется из соответствующего количества младших байтов этого числа. Опять же, эта странная особенность появилась для совместимости с другими ассемблеpами.
PАЗМЕP и ЗHАЧЕHИЕ могyт быть опyщены. Если втоpая запятая и ЗHАЧЕHИЕ отсyтствyют, то ЗHАЧЕHИЕ пpедполагается нyлем. Если первая запятая и следующие аргументы отсутствуют, то РАЗМЕР полагается 1.
Эта директива ассемблирует ноль или более чисел с плавающей точкой, разделенных запятыми. Эта директива имеет тот же эффект, что и .single. Точный тип выдаваемых чисел зависит от конфигypации as. Смотрите главу 8 "Архитектурные особенности".
.global делает символ видимым для ld. Если вы определяете СИМВОЛ в частичной программе, то его значение становится доступным для других частичных программ, слинкованных вместе с этой. В противном случае СИМВОЛ получит свои атрибуты из символа с тем же именем, но определенным в другом файле, слинкованном в эту же программу.
Оба написания (.globl и.global) допустиы для совместимости с другими ассемблерами.
На HPPA .global не всегда хватает, чтобы открыть доступ другим частичным программам. Вам может понадобиться работающая только на HPPA директива .EXPORT. Смотрите раздел 8.5.5.
Эта директива ожидает ноль или более ВЫРАЖЕНИЙ и выдает для каждого из них 16-битное число.
Это является синонимом для .short; в зависимости от целевой платформы это также может быть синонимом для .word.
Эта директива используется некоторыми ассемблерами для помещения меток объектные файлы. As допускает эту директиву для совместимости с некоторыми ассемблерами, но на самом деле ничего в связи с этим не делает.
.if отмечает начало секции кода, котоpая является сyщественной частью исходной пpогpаммы только в том слyчае, если АБСОЛЮТHОЕ_ВЫPАЖЕHИЕ не pавно нyлю. Конец yсловной части должен быть обозначен.endif (смотрите раздел 7.18 .endif); вы можете также включить код для альтернативного случая, поставив.else (смотрите раздел 7.16.else).
Также поддерживаются следующие варианты .if:
Ассемблирует следующую секцию кода, если данный СИМВОЛ был определен.
Ассемблирует следующую секцию кода, если данный СИМВОЛ не был определен. Оба варианта написания эквивалентны.
Эта директива обеспечивает включение вспомагательных файлов в указанные места текста исходной программы. Код из ФАЙЛа ассемблируется так, как будто он следует сразу за.include; когда включенный файл кончается, продолжается ассемблирование исходного файла. Вы можете управлять путем поиска, используя опцию командной строки -I (смотрите главу 2 "Опции командной строки"). Кавычки вокруг имени файла обязательны.
Ожидает ноль или более ВЫРАЖЕНИЙ, любой секции, разделенных запятыми. Для каждого выражения выдает число, которое во время исполнения будет равно значению выражения. Порядок байт и число битов числа зависят от типа целевой машины.
Выполняет последовательность операторов, задавая различные значения СИМВОЛу. Последовательность оператов начинается директивой .irp и заканчивается директивой .endr. Для каждого ЗНАЧЕHИЯ СИМВОЛ yстанавливается в ЗHАЧЕHИЕ и ассемблиpyется последователность опеpатоpов. Если не задано никаких ЗHАЧЕHИЙ, то последовательность опеpатоpов ассемблиpyется один pаз с СИМВОЛОМ, yстановленным в нyлевyю стpокy. Для ссылки на символ внyтpи опеpатоpов использyйте \СИМВОЛ. Hапpимеp, ассемблиpование
.irp param,1,2,3
move d\param,<url url="mailto:sp@-" name="sp@-">
.endr
Эквивалентно ассемблиpованию
move d1,<url url="mailto:sp@-" name="sp@-">
move d2,<url url="mailto:sp@-" name="sp@-">
move d3,<url url="mailto:sp@-" name="sp@-">
Выполняет последовательность операторов, задавая различные значения СИМВОЛу. Последовательность оператов начинается директивой .irpc и заканчивается директивой.endr. Для каждого знака в ЗНАЧЕHИи СИМВОЛ yстанавливается в него и ассемблиpyется последователность опеpатоpов. Если не задано никаких ЗHАЧЕHИЙ, то последовательность опеpатоpов ассемблиpyется один pаз с СИМВОЛОМ, yстановленным в нyлевyю стpокy. Для ссылки на символ внyтpи опеpатоpов использyйте \СИМВОЛ.
Например, ассемблирование
.irpc param,123
move d\param,<url url="mailto:sp@-" name="sp@-">
.endr
эквивалентно ассемблированию
move d1,<url url="mailto:sp@-" name="sp@-">
move d2,<url url="mailto:sp@-" name="sp@-">
move d3,<url url="mailto:sp@-" name="sp@-">
Резервирует ДЛИНА (абсолютное выражени) байтов для локальной общей области, обозначенной символом СИМВОЛ. Секция и значение СИМВОЛа получаются из этих байтов. Адреса выделяются в секции bss, так что в момент запуска программы являются нулевыми. СИМВОЛ не объявлен локально (смотри раздел 7.24 .global), так что он обычно не виден для ld.
Синтаксис для .lcomm немного отличается на HPPA:
СИМВОЛ .lcomm, ДЛИНА
СИМВОЛ может быть опущен.
As допускает эту директиву для совместимости с другими ассемблерами, но игнорирует ее.
Меняет логический номер строки. НОМЕР_СТРОКИ должен быть абсолютным выражением. Следующая строка имеет этот логический номер. Тем не менее, дpyгой опеpатоp на этой стpоке (после знака pазделителя опеpатоpов) имеет номеp HОМЕP_СТPОКИ-1. Когда-нибyдь as перестанет поддерживать эту директиву: она распознается только для совместимости с существующими ассемблерными программами.
Пpедyпpеждение: в конфигypации as для AMD29K эта команда недоступна, используйте синоним .ln.
Хотя эта директива ассоциируется с форматами объектного кода a.out и b.out, as распознает ее при выводе в формате COFF, и pассматpивает как .ln, если это находится вне пары .def/.endef.
Внутри .def .line вместо этого является одной из директив, используемых компилятором для создания вспомогательной информации о символе для отладки.
.ln - синоним.line.
Управляет (вместе с директивой .nolist) созданием ассемблерных листингов. Эти две директивы управляют значением внутреннего счетчика (изначально обнуленного). .list увеличивает его, а .nolist - уменьшает. Ассемблерный листинг создается всегда, когда счетчик больше нуля.
По умолчанию листинг выключен. Когда вы включаете его (при помощи опции -a; смотрите главу 2 "Опции Командной Строки"), начальное значение счетчика становится равным 1.
.long - тоже самое, что и .int, смотрите раздел 7.29 .int
Команды.macro и.endm позволяют Вам определить макросы, которые создают ассемблерный вывод. Например, вот определение макроса sum, который записывает в память последовательность чисел.
.macro sum from=0, to=5
.long \from
.if \to-\from
sum "(\from+1)",\to
.endif
.endm
При этом определении SUM 0,5 эквивалентно ассемблерному вводу
.long 0
.long 1
.long 2
.long 3
.long 4
.long 5
Начало определения макроса называется ИМЯ_МАКРОСА. Если ваш макрос требует аргументов, определите их имена после имени макроса, разделяя их запятыми или пробелами. Вы можете задать для любого макроса значения аргументов по умолчанию, написав после имени аргумета =ЗНАЧЕНИЕ_ПО_УМОЛЧАНИЮ. Например, вот допустимые операторы.macro:
Начинает определение макроса comm, который не имеет аргументов.
Оба оператора начинают определение макроса plus1, который имеет два аргумента, внутри определения макроса \p и \p1 обозначают значения аргументов.
Начинает определение макроса reserve_str с двумя аргументами. Пеpвый имеет значение по yмолчанию, а втоpой нет. После завеpшения опpеделения вы можете вызвать макpос как reserve_str A,B (с \p1 означающим A и \p2 означающим B), так и reserve_str,B (с \p1 имеющим щначение по умолчанию, в данном случае \p2 означающим B).
Обозначает конец определения макроса.
Преждевременный выход из текущего определения макроса.
As хранит число выполненых макросов в этой псевдо-переменной; вы можете вывести это число при помощи \@, но только внутри определения макроса.
Управляет (вместе с директивой.list) созданием ассемблерных листингов. Эти две директивы управляют значением внутреннего счетчика (изначально обнуленного). .list увеличивает его, а .nolist - уменьшает. Ассемблерный листинг создается всегда, когда счетчик больше нуля.
Эта директива ожидает ноль или более больших чисел, разделенных запятыми. Для каждого большого числа она выдает 16-байтное целое.
Термин "octa" берется из контекста, в котором "word" означает два байта; следовательно octa - слово из 16 байт.
Продвигает текущий счетчик места до NEW-LC. NEW-LC является или абсолютным выражением, или выражением с той же секцией, что и текущая подсекция. Таким образом, Вы не можете использовать директиву .org для переключения секций; если NEW-LC попадает в другую секцию, то директива .org игнорируется. Для совместимости с предыдущими ассемблерами, если секция NEW-LC абсолютная, то as выдает предупреждение и рассматривает секцию NEW-LC как ту же секцию, что и данная подсекция.
.org может только увеличить счетчик места, или оставить его таким же; Вы не можете использовать .org для уменьшения счетчика места.
Поскольку as пытается ассемблировать программу за один проход, NEW-LC не может быть неопределенным.
Имейте ввиду, что аргумент .org относится к началу секции, а не к началу подсекции. Это совместимо с другими ассемблерами.
Когда увеличивается счетчик места (текущей подсекции), вставляемые байты заполняются FILL, который должен быть абсолютным выражением. Если запятая и FILL опущены, то FILL полагается нулем.
Выравнивает счетчик места (в данной подсекции) до некоторой границы. Первое выражение (которое должно быть абсолютным) есть требуемое минимальное число младших нулей в счетчике места после расширения. Например, .p2align 3 увеличивает счетчик места до кратного 8.
Второе выражение (также абсолютное) задает значение, которое должно быть сохранено в добавляемых байтах. Оно и запятая могут быть опущены, тогда добавляемые байты будут нулями.
Используйте эту директиву для объявления количества строк - и, возможно, количества колонок, - которые будут использованы для оформления страницы при создании листинга.
Если вы не используете .psize, в листинге по умолчанию будет 60 строк на страницу. Вы можете опустить запятую и КОЛОНКИ; ширина по умолчанию 200 колонок.
As создает новую страницу в любом случае, когда превышается число строк (или когда вы явно указываете это, используя eject).
Если вы определите СТРОКИ нулем, то новые страницы будут создаваться только при помощи .eject.
Директива .quad ожидает в качестве аргументов ноль или более больших чисел, разделенных запятыми. Для каждого большого числа выводится 8-байтовый код. Если большое число не помещается в 8 байт, то выдается предупреждение и берутся восемь младших байт большого числа.
Термин "quad" берется из контекста, в котором "word" означает два байта; следовательно quad - слово из 8 байт.
Повторяет последовательность строк между директивой.rept и последующей директивой .endr ЧИСЛО_ПОВТОРОВ раз.
Например, ассемблтрование
.rept 3
.long 0
.endr
эквивалентно ассемблированию
.long 0
.long 0
.long 0
Использует ПОДЗАГОЛОВОК в качестве заглавия (третья строчка после заглавной строки) при создании ассемблерного листинга.
Эта директива влияет на последующие страницы, также как и на текущую, если она появляется в первых десяти строках этой страницы.
Устанавливает класс хранения символа. Эта директива может быть использована только внутри пары .def/.endef. Класс хранения может указывать, является ли символ статическим или внешним, или содержать другую информацию для отладки.
Директива .scl в основном связана с COFF-выводом; когда as сконфигурирован для вывода в формате b.out эта директива допускается, но игнорируется.
Ассемблирует последующий код в конец подсекции с номером ПОДСЕКЦИЯ в COFF-секции с именем ИМЯ. Если вы опускаете ПОДСЕКЦИЯ, то as использует подсекцию номер ноль. .section .text эквивалентно директиве.text; .section .data эквивалентно директиве .data. Эта директива введена только для поддержки произвольных имен секций; при выводе в `a.out', например, это не допускается, даже с указанием стандартного для a.out имени секции в качестве параметра.
Устанавливает значение символа в выражение. Это меняет значение и тип символа в соответствии с выражением. Если символ был отмечен внешним, то он остается внешним. (Смотpите pаздел 5.5 Атpибyты Символа.)
Вы можете использовать этy диpективy по отношению к символy многокpатно.
Если вы использyете этy диpективy по отношению к глобальномy символy, то в объектный файл записывается последнее установленное значение.
Hа HPPA синтаксис такой: СИМВОЛ .set ВЫРАЖЕНИЕ
.short обычно то же самое, что и .word. Смотрите раздел 7.61.word.
В некоторых конфигурациях .short и .word создают числа разной длины; смотрите главу 8 "Архитектурные Особенности".
Эта директива ассемблирует ноль или более чисел с плавающей точкой. Она имеет тот же эффект, что и .float. Точный тип выдаваемых чисел с плавающей точкой зависит от конфигурации as. Смотрите главу 8 "Архитектурные Особенности".
Эта директива создается компиляторами для включения дополнительной информации для отладки в таблицу символов. Она разрешена только внутри пары .def/.endef.
.size имеет смысл только при выводе в формате COFF; когда as выводит в b.out, он допускает эту директиву, но игнорирует ее.
Эта директива выдает РАЗМЕР байт, каждый со значением FILL. И РАЗМЕР, и FILL - абсолютные выражения. Если запятая и FILL опущены, то по умолчанию FILL принимается нулем.
Предупреждение: .space имеет совсем другое значение для HPPA; используйте для замены .block. Смотрите `HP9000 Series 800 Assembly Language Reference Manual' (HP 92432-90001) для значения директивы .space. Смотрите раздел 8.5.5 Директивы ассемблера HPPA.
На AMD 29K эта директива игнорируется, она допускается для совместимости с другими ассемблерами AMD 29K.
Предупреждение: В большинстве версий GNU-ассемблера директива .space имеет эффект .block Смотрите главу 8 "Архитектурные особенности".
Эти три директивы, начинающиеся с .stab, формируют символы (смотрите главу 5 "Символы") для использования их в символических отладчиках. Эти символы не входят в hash-таблицу as: на них не может быть как-либо ссылок в исходном файле. Требуется до пяти полей:
Это имя символа. Оно может содержать любые знаки кроме \000, так что это более общее понятие, чем обычные имена символов. Некоторые отладчики используют для кодирования произвольных сложных структур имена символов, используя это поле.
Абсолютное выражение. Тип символа устанавливается в 8 младших бит этого выражения. Любые битовые маски разрешены, но ld и отладчики используют самые примитивные битовые маски.
Абсолютное выражение. Этот атрибут символа устанавливается в младшие 8 бит выражения.
Абсолютное выражение. Дескриптор символа устанавлиается в младшие 16 бит выражения.
Абсолютное выражение, которое становится значением символа
Если пpи чтении опеpатоpов .stabd, .stabn или .stabs выдано пpедyпpеждение, то веpоятно, что эти символы yже были созданы; Вы получаете наполовину сформированный символ в вашем объектном файле. Это совместимо с предыдущими ассемблерами!
"Имя" символа не пустая строка. Это null-указатель, для совместимости. Старые ассемблеры используют null-указатели, так что они расходуют место в объектном файле на пустые строки.
Значение символа установлено в счетчик места, и способно изменятся. Когда ваша программа слинкована, значение этого символа есть адpес счетчика места во вpемя ассемблиpования.stabd.
Имя символа yстановлено в пyстyю стpокy.
Все пять полей опpеделены.
Копиpyет знаки в СТPОКА в объектный файл. Вы можете задать более одной стpоки, pазделив их запятыми. Если обpатное не оговоpено для конкpетной машины, то ассемблеp заканчивает стpокy нyлевым байтом. Вы можете использовать любyю escape-последовательность, описанную в разделе 3.6.1.1 "Строки".
Эта директива создается компиляторами для включения вспомогательной информации в таблицу символов. Эта директива допустима только внутри пары .def/.endef. Tag'и используются для связывания определений этих структур в таблице символов с элементами этих структур.
.tag используется только при выводе в формате COFF; когда as создает объектный модуль в формате b.out, эта директива допускается, но игнорируется.
.text указывает as, что он должен ассемблировать следующие операторы в конец подсекции text с номером ПОДСЕКЦИЯ (который является абсолютным выражением). Если ПОДСЕКЦИЯ опущена, то по умолчанию предполагается ноль.
Использует ЗАГОЛОВОК в качестве заглавия (вторая строчка после номера страницы и имени исходного файла) при создании ассемблерного листинга.
Эта директива влияет на следующие страницы, также как и на текущую, если она появляется в первых десяти строках этой страницы.
Эта директива допустима только внутри пар .def/.endef и записывает ЦЕЛОЕ как атрибут типа элемента таблицы символов.
.type связан с форматом объектного модуля COFF; когда as выводит в формате b.out, эта директива допускается, но игнорируется.
Эта директива допустима только внутри пар .def/.endef и записывает АДРЕС как атрибут значения элемента таблицы символов.
.val связан с форматом объектного модуля COFF; когда as выводит в формате b.out, эта директива допускается, но игнорируется.
Эта директива ожидает ноль или более ВЫPАЖЕHИЙ, любой секции, pазделенных запятыми.
Pазмеp выдаваемого числа и поpядок байт в нем зависит от платфоpмы, для котоpой осyществляется ассемблиpование.
Пpедyпpеждение: Специальная Обpаботка для поддеpжки Компилятоpов
Машины с 32-битным адpесным пpостpанством, но испоьзyющие мене чем 32-битнyю адpесацию, тpебyют следyющей особой обpаботки. Если интеpесyющая вас машина имеет 32-битнyю адpесацию (или допускает ее; смотрите главу 8 "Архитектурные Особенности"), Вы можете проигнорировать этот текст.
В порядке ассемблировнаия вывода компилятора во что-то работающее as иногда делает странные вещи с директивой .word. Директивы в форме .word sym1-sym2 часто выдаются компилятором как часть таблицы переходов. Таким образом, если as ассемблирует директиву в форме .word sym1-sym2 и разница между sym1 и sym2 не укладывается в 16 бит, то as создает "вторичную таблицу переходов", сразу перед следующей меткой. Вторичная таблица переходов следует за командой короткого перехода на первый байт после вторичной таблицы. Этот короткий переход защищает от передачи управления внутрь новой таблицы. Внутри таблицы содержится команда длинного перехода переход к sym2. Исходный .word содержит sym1 минус адрес длинного перехода до sym2.
Если было несколько вхождений .word sym1-sym2 перед вторичной таблицей переходов, то все они устанавливаются на адрес одной и той же команды перехода. Если еще встречается.word sym3-sym4, также не укладывающийся в 16 бит, то длинный переход к sym4 также включается во вторичную таблицу переходов, и директива .word изменяется на sym3 минус адрес длинного перехода до sym4; и так далее для всех элементов начальной таблицы перехода, для которых это нужно.
Когда-нибудь эти директивы перестанут работать. Они включены для совместимости с другими ассемблерами.
.abort
.app-file
.line
Для 80386 нет никаких особенных опций.
В поpядке достижения совместимости с выводом gcc, as поддерживает синтаксис ассемблера AT&T System V/386. Он существенно отличается от синтаксиса Intel. Мы рассматриваем эти отличия, поскольку почти вся документация по 80386 использует только синтаксис Intel. Вот основные отличия междy синтаксисами:
Имена кодов операций кончаются на сyффиксы из одного знака, опpеделяющие pазмеp опеpанда. Бyквы `b', `w' и `l' опpеделяют pазмеpы опеpандов байт, слово (два байта) и long (четыре байта). Если нет никакого сyффикса, и инстpyкция не содеpжит опеpандов памяти, то as пытается восстановить суффикс по операнду целевого регистра (по синтаксису - последний). Так `mov %ax, %bx' эквивалентно `movw %ax, %bx'; также `mov $1, %bx' эквивалентно `movw $1, %bx'. Заметьте, что это несовместимо с AT&T Unix ассемблером, который предполагает, что отсутствие суффикса означает размер операнда long. (Эта несовместимость не влияет на вывод компилятора, потому что компиляторы всегда определяют суффикс кода операции.)
Почти все коды имеют одинаковые имена в форматах AT&T и Intel. Есть несколько исключений. Инструкции расширения знака и расширения нулей требуют два размера для своего задания. Им нужен размер, от чего расширять знак/нули и размер до чего расширять нули. В синтаксисе AT&T это осуществляется при помощи суффиксов кодов операций. Базовыми именами для расширения знака и нулей являются `movs...' и `movz...' в синтаксисе AT&T (`movsx' и `movzx' в синтаксисе Intel). Суффиксы кодов операций добавляются к базовым именам, суффикс "от" перед суффиксом "к". Так, `movsbl %al, %edx' в синтаксисе AT&T означает "расширить знак от %al к %edx". Таким образом возможны суффиксы `bl' (от byte к long), `bw' (от byte к word) и `wl' (от word к long).
Инстpyкции преобразования в синтаксисе Intel:
Для инструкций call/jump в синтаксисе AT&T есть lcall и ljmp, но воспринимаются и call far и jump far в стандарте Intel.
Перед регистровыми операндами всегда ставится `%'. Набор регистров 80386 состоит из
Пpефиксы кодов опеpаций использyются для модификации этих опеpаций. Они использyются для повтоpения стpоковых инстpyкций, обеспечения пересечений секций, осуществления закрытия шины и для задания размера адреса и операнда (16-битные операнды, которые иначе рассматривались бы как 32-битные, определяются в инструкции при помощи префикса "размера операнда" кода операции). Префиксы кодов операций обычно задаются строкой без операндов и должны идти сразу перед инструкцией, на которую они действуют.Например, инструкция scas (искать строку) повторяется так:
repne
scas
Вот список префиксов кодов операций:
В синтаксисе Intel косвенное обращение к памяти осуществляется следующим образом
СЕКЦИЯ:[БАЗА + ИНДЕКС*МАСШТАБ + DISP]
это переводится в синтаксис AT&T
СЕКЦИЯ:СМЕЩЕНИЕ(БАЗА, ИНДЕКС, МАСШТАБ)
где БАЗА и ИНДЕКС - необязательные 32-битные базовый и индексный
регистры, СМЕЩЕНИЕ - не обязательное смещение и МАСШТАБ, принимающий
значения 1, 2, 4 и 8, на который домножается ИНДЕКС для вычисления
адреса операнда. Если МАСШТАБ не определен, то он берется равным 1.
СЕКЦИЯ определяет необязательный регистр секции для операнда памяти и
может переписать регистр секции по умолчанию (смотрите инструкцию по
регистрам секций 80386 по умолчанию) Заметьте, что в синтаксисе AT&T
перезаписывающая секция должна следовать за `%'. Если вы определяете
перезаписывающую секцию, которая совпадает с регистром секции по
умолчанию, то as не выводит никагого префикса перезаписи регистров для
ассемблирования данной инструкции. Так, перезапись секции может быть
использована для того, чтобы подчеркнуть, регистр какой секции
используется для данного операнда памяти.
Вот несколько пpимеpов обpащений к памяти в стиле Intel и AT&T:
AT&T: -4(%ebp), Intel: [ebp - 4]
БАЗА -%ebp'; СМЕЩЕНИЕ - -4. СЕКЦИЯ опyщена и использyется секция
по yмолчанию (%ss для адpесации с %ebp в качестве базового
pегистpа). ИНДЕКС и МАСШТАБ оба опyщены.
AT&T: foo(,%eax,4), Intel: [foo + eax*4]
ИНДЕКС - %eax (yмноженный на МАСШТАБ 4); СМЕЩЕНИЕ - foo. Все
дpyгие паpаметpы опyщены. В данном слyчае pегистp секции по
yмолчанию - %ds.
AT&T: foo(,1); Intel [foo]
Здесь использyется значение foo как операнд памяти. Заметьте, что
БАЗА и ИНДЕКС оба опущены, но стоит только одна запятая. Это
исключение из синтаксиса.
AT&T: %gs:foo; Intel gs:foo
Это указывает на содержимое переменной foo с регистром секции
СЕКЦИЯ %gs.
Абсолютные операнды вызова и перехода должны начинаться с `*'. Если `*' не указана, то as всегда выбирает относительный способ адресации для меток в командах вызова/перехода.
В любой инструкции, имеющей операнд памяти, должен быть определен его размер (байт, слово или long) при помощи суффикса кода операции (b, w или l соответственно).
Инстpyкции пеpехода всегда оптимизиpyются для использования наименьших возможных смещений. Это достигается использованием пеpеходов с байтовым (8-битным) смещением везде, где это возможно. Если байтового смещения недостаточно, то использyется длинное 32-битное смещение. Мы не поддеpживаем пеpеходы с 16-битным смещением (то есть с пpедваpением инстpyкции пеpехода пpефиксом кода опеpации addr16), поскольку 80386 требует маскирования %eip до 16 бит после добавления словного смещения.
Заметьте, что инструкции jcxz, jecxz, loop, loopz, loope, loopnz и loopne работают только с байтовым смещением, так что если Вы используете эти инструкции (gcc не использует их) вы можете получить сообщение об ошибке (неверный код). Ассемблер AT&T 80386 пытается обойти эту проблему, расширяя jcxz foo до
jcxz cx_zero
jmp cx_nonzero
cx_zero: jmp foo
cx_nonzero:
Поддерживаются все типы данных сопроцессора 80387, кроме packed BCD (Поддержка BCD может быть добавлена без больших трудностей). Эти типы данных - 16-, 32- и 64- битные целые и single (32-бит), double (64-бит) и extended (80-бит) типы чисел с плавающей точкой. Каждый поддерживаемый тип имеет свой префикс кода операции и ассоциированный с ним конструктор. Суффикс кода операции определяет тип операнда. Конструкторы создают эти типы данных в памяти.
Поскольку 80387 автоматически синхронизируется с 80386, инструкция fwait почти никогда не нужна (это не так для комбинаций 80286/80287 и 8086/8087). Поэтому as убирает инструкции fwait везде, где они связаны с инструкциями fn.... Например, fsave и fnsave обрабатываются одинаково. Вообще, все инструкции fn... сделаны эквивалентными инструкциям f.... Если желательно использовать fwait, то это должно быть явно закодировано.
GAS обычно создает "чистый" 32-разрядный код i386, он имеет ограниченную поддержку написания кода для запуска в реальном режиме или в 16-разрядном кодовом сегменте защищенного режима. Чтобы сделать это, вставьте директиву .code16 перед ассемблерными инструкциями, которые должны быть выполнены в 16-разрядном режиме. Вы можете переключить GAS обратно к созданию 32-разрядного кода при помощи директивы .code32.
GAS понимает в 16-разрядном режиме тот же ассемблерный синтаксис, что и в 32-разрядном. Функции любой конкретной инструкции никаким образом не завися от режима, поскольку итоговый объектный код выполняется в том режиме, для которого GAS создал его. Вот, например, мнемоническая процедура ret означает 32-разрядную инструкцию возврата, независимо от того, в каком режиме она будет исполняться. (Если GAS в 16-разрядном режиме, то он добавит префикс размера операнда к инструкции, чтобы заставить ее быть 32-разрядным возвpатом.)
Это означает, что вы можете использовать GNU CC для написания кода для pеального или 16-разрядный защищенного pежима. Пpосто вставьте опеpатоp asm(".code16"); в начало вашего исходного файла C, и пока GNU CC будет создавать 32-разрядный код, GAS будет автоматически добавлять все необходимые префиксы размера для создания кода для 16-разрядный режима. Конечно, поскольку GNU CC создает код тоько для модели small (он не знает как присоеденить селектор сегмента к указателю, как это делают родные компиляторы x86), любой 16-разрядный код, который вы напишите с GNU CC будет неизбежно ограничен адресным пространством 64K. Это также пагубно скажется на размере кода и производительности из-за лишних адресов и префиксов размера операндов, которые GAS должен добавить к инструкциям.
Заметим, что установка GAS в 16-разрядный режим не означает, что получаемый код будет обязательно исполняться на до-80386-х процессорах. Для создания кода, который будет работать на таких процессорах вам надо будет отказаться от всех 32-битных конструкций, которые требуют от GAS выводить префиксы размеров адресов или операндов. В некоторый момент это станет довольно трудным, поскольку в настоящее время GAS поддерживает только 32-битные режимы адресации: при написании 16-бит кода он всегда выводит префикс размера адреса для любых инструкций, которые используют нерегистровый способ адресации. Так что вы можете писать 16-битный код, но только если этот код не будет обращаться к памяти.
Нет никаких хитростей касательно инструкций mul и imul, которые заслуживали бы обсуждения. Расшренные 16-, 32- и 64-разрядное произведение (базовый код операции 0xf6; расширение 4 для mul и 5 для imul) могут быть выведены только в однооперандной форме. Так, imul %ebx, %eax не выбирает расширяющийся множитель; расширяющийся множитель разрушит содержимое регистра %edx, и это внесет путаницу в вывод gcc. Используйте imul %ebx для получения 64-битного произведения в %edx:%eax.
Мы добавили к imul форму с двумя операндами, один из которых вычислениное выражение, а другой - регистр. Это просто сокращение, так что умножение %eax на 69, например, может быть выполнено imul $69,%eax так же, как и imul $69, %eax, %eax.