Основная причина, по которой используется ассемблер в Linux - это написание очень небольших по размеру программ, которые не зависят от системных библиотек. Такие программы особенно нужны для встраиваемых систем, где объемы запоминающих устройств обычно невелики.
GAS - это сокращение от GNU Assembler. Поскольку GAS был разработан для поддержки 32-битных компиляторов Unix, он использует стандартный синтаксис AT&T, который несколько отличается от обычного ассемблера DOS. Основные отличия синтаксиса GAS от синтаксиса Intel:
mov eax,edx
(передать содержимое регистра edx в регистр eax) будет выглядеть в GAS как
mov %edx,%eax
.
movl %edx,%eax
. Однако, gas не требует соблюдения строгого синтаксиса
AT&T, так что суффикс необязателен, если размер может быть определен для
регистрового операнда, либо по умолчанию принимается 32-bit.
addl $5,%eax
(добавить константу 5 к регистру %eax).
movl $foo,%eax
помещает адрес переменной foo в регистр %eax, а
movl foo,%eax
помещает в %eax содержимое переменной foo.
Индексация выполняется с помощью заключения индексного регистра в скобки,
например, in testb $0x80,17(%ebp)
(проверить установку старшего бита
в байте по смещению 17 от ячейки, указанной %ebp).
Примечание: Существует несколько программ, которые могут помочь Вам преобразовать исходный код для ассемблеров AT&T и Intel; некоторые из них способны на преобразование в двух направлениях.
Ассемблер NASM разрабатывается в рамках The Netwide Assembler project, и представляет собой мощный ассемблер на базе i386, написанный на C, который построен по модульному принципу и обеспечивает поддержку практически вссех известных синтаксисов и форматов объектных файлов.
Используется синтаксис Intel. Поддерживается обработка макроопределений.
Среди поддерживаемых форматов объектных файлов есть bin, aout, coff, elf, as86, obj (DOS), win32, rdf (собственный формат). Кроме того, NASM поставляется с дизассемблером NDISASM.
Как и для GAS, для NASM существует несколько программ для проебразования синтаксиса.
В качестве примера здесь приводятся две программы на ассемблере. Программы написаны с учетом того, что Linux является 32-битной системой, работает в защищенном режиме, имеет плоскую модель памяти, и использует для исполняемых файлов формат ELF.
Программа обычно делится на разделы: .text - для программного кода (только для чтения), .data - для записи данных (чтение-запись), .bss - для неинициализируемых данных (чтение-запись); могут также присутствовать и другие стандартные разделы, а также разделы, определенные пользователем. В программе должен присутствовать как минимум раздел .text.
Пример для NASM (hello.asm)
section .data ; описание раздела
msg db "Hello, world!",0xa ; выводимая строка
len equ $ - msg ; длина строки
section .text ; описание раздела
; нам нужно передать точку входа компоновщику или
global _start ; загрузчику ELF. Обычно они распознают _start по умолчанию.
; Используйте ld -e foo, чтобы переопределить ее.
_start:
; записываем строку в стандартный вывод
mov edx,len ; третий аргумент: длина строки
mov ecx,msg ; второй аргумент: указатель на строку
mov ebx,1 ; первый аргумент: дескриптор файла (stdout)
mov eax,4 ; номер системного вызова (sys_write)
int 0x80 ; обращение к ядру
; и выходим
mov ebx,0 ; первый аргумент: код возврата
mov eax,1 ; номер системного вызова (sys_exit)
int 0x80 ; обращение к ядру
Пример для GAS (hello.S)
.data # описание раздела
msg:
.string "Hello, world!\n" # выводимая строка
len = . - msg # длина строки
.text # описание раздела
# нам нужно передать точку входа компоновщику или
global _start # загрузчику ELF. Обычно они распознают _start по умолчанию.
# Используйте ld -e foo, чтобы переопределить ее.
_start:
# записываем строку в стандартный вывод
movl $len,%edx # третий аргумент: длина строки
movl $msg,%ecx # второй аргумент: указатель на строку
movl $1,%ebx # первый аргумент: дескриптор файла (stdout)
movl $4,%eax # номер системного вызова (sys_write)
int $0x80 # обращение к ядру
# и выходим
movl $0,%ebx # первый аргумент: код возврата
movl $1,%eax # номер системного вызова (sys_exit)
int $0x80 # обращение к ядру
Основные опции ассемблера GAS:
--defsym sym=value
Определяет символом sym величину value перед разбором входного файла. value должно быть целой константой. Как и в C, префикс 0x определяет шестнадцатиричное число, а префикс 0 - восьмеричное.
--help
Выводит список опций командной строки.
-I dir
Добавить каталог dir в список поиска для директив `.include'.
-o objfile
Имя объектного файла для вывода из `as'.
-R
Распознавать вложенные в код разделы данных.
--no-warn
Опускать сообщения о предупреждениях.
--fatal-warnings
Рассматривать предупреждения как ошибки.
-h
Вывод информации об опциях и поддерживаемых форматах выходных файлов nasm.
-a
Ассемблировать файл без предварительного препроцессинга.
-e
Выполнить препроцессинг входного файла и вывести результат в stdout (или указанный файл-приемник), но без ассемблирования.
-M
Вывести в stdout зависимости в стиле make-файла.
-E filename
Перенаправлять сообщения об ошибках в файл filename. Опция предназначена для операционных систем, в которых stderr нельзя перенаправить.
-f format
Определить формат выходного файла. Форматы включают в себя bin для плоских двоичных файлов, и aout или elf для создания объектных фалов типа Linux a.out и ELF, соответственно.
-o outfile
Определить точное имя выходного файла, переопределив имя по умолчанию.
-l listfile
Перенаправить листинг ассемблера в указанный файл, в котором с правой стороны будет выведен исходный текст (а также текст включаемых файлов и расширенные макросы), а с левой стороны - сгенерированный код в шестнадцатиричном формате.
-s
Выводить сообщения об ошибках в файл стандартного вывода.
-w[+-]foo
Подключить или отключить некоторые классы предупреждающих сообщений, например, -w+orphan-labels или -w-macro-params, чтобы, соответственно, разрешить сообщения о метках в пустой строке или отключить сообщения о неверном количестве параметров в вызовах макросов.
-I directory
Добавить каталог в путь поиска включаемых файлов.