NASM
NASM | |
---|---|
Тип | компилятор |
Авторы | Simon Tatham, Julian Hall |
Разработчики | H. Peter Anvin, Jim Kukunas, Cyrill Gorcunov, Frank B. Kotler |
Написана на | Си[1] |
Операционные системы | |
Первый выпуск | 1996 |
Аппаратные платформы | x86, x86_64 |
Последняя версия | 2.16.03 (17 апреля 2024) |
Репозиторий | github.com/netwide-assem… |
Лицензия |
LGPL, с версии 2.07 — упрощённая лицензия BSD |
Сайт | nasm.us |
NASM (Netwide Assembler) —
. Используется для написания 16-, 32- и 64-разрядных программ.История
NASM был создан
NASM может работать на платформах, отличных от x86, таких как SPARC и PowerPC, однако код он генерирует только для x86 и x86-64[2].
NASM успешно конкурирует со стандартным в Linux- и многих других UNIX-системах ассемблером gas.[3][4][5] Считается, что качество документации у NASM выше, чем у gas.[5] Кроме того, ассемблер gas по умолчанию[6] использует AT&T-синтаксис, ориентированный на процессоры не от Intel, в то время как NASM использует вариант традиционного для x86-ассемблеров Intel-синтаксиса; Intel-синтаксис используется всеми ассемблерами для DOS/Windows, например, MASM, TASM, fasm.
Синтаксис языка
В NASM используется Intel-синтаксис записи инструкций. Предложение языка ассемблера NASM (строка программы) может состоять из следующих элементов:
Метка Инструкция Операнды Комментарий
Операнды разделяются между собой запятой. Перед строкой и после инструкции можно использовать любое количество пробельных символов. Комментарий начинается с точки с запятой, а концом комментария считается конец строки. В качестве инструкции может использоваться команда или псевдокоманда (директива компилятора). Если строка очень длинная, то её можно перенести на следующую, используя обратный слеш \
подобно тому, как это делается в языке Си.
Компиляция и компоновка
NASM компилирует программы под различные операционные системы в пределах x86-совместимых процессоров. Находясь в одной операционной системе, можно беспрепятственно откомпилировать исполняемый файл для другой. В общем встроенные средства NASM позволяет компилировать не только программы, но и файлы с любым содержимым. Также мощный макро-препроцессор значительно расширяет возможности для программирования.
Для компоновки объектных файлов в исполняемые в Windows можно использовать свободный бесплатно распространяемый компоновщик alink[4](для 64-битных программ компоновщик GoLink), а в Linux — компоновщик ld, который есть в любой версии этой операционной системы.
Для ассемблирования файла нужно ввести следующую команду:
nasm -f format filename -o output
Инструкции перехода
Компилятор обрабатывает текст программы в несколько проходов, благодаря чему можно инструкции перехода размещать до объявления соответствующих меток.
В командах условного и безусловного (jmp
) переходов используется по умолчанию ближний тип переходов — near
. Поэтому при возможности короткого перехода, чтобы не завысить размер программы на лишний байт, необходимо специально указать тип перехода short
. С версии 0.98.09b были добавлены опции оптимизации -Ox, которые позволяют автоматически оптимизировать размер инструкций перехода[7], в более ранних версиях или без таких опций минимальный размер программы можно получить только ручной модификацией исходного кода.
Формат выходных файлов
NASM поддерживает множество форматов выходных файлов, среди них[8]:
- bin — файл произвольного формата, определяемого только исходным кодом. Пригоден как для файлов данных, так и для модулей с исполняемыми кодами — например, системных загрузчиков, образов ПЗУ, модулей операционных систем, драйверов .SYS в MS-DOS или исполняемых файлов .COM.
- obj — объектный модуль в формате OMF, совместимый с MASM и TASM.
- win32 и win64 — объектный модуль для 32- и 64-битного кода, совместимый с Win64-компиляторами Microsoft.
- aout — объектный модуль в варианте формата a.out, использовавшегося в ранних Linux-системах.
- aoutb — версия формата a.out для BSD-совместимых операционных систем.
- coff — объектный модуль в формате COFF, совместимом с компоновщиком из DJGPP.
- elf32 и elf64 — объектный модуль в форматах .
Формат выходного файла можно задать с помощью ключа командной строки -f. Форматы могут расширять синтаксис некоторых инструкций и добавлять собственные инструкции.
Примеры программы «Hello, world!» под разные ОС
Примеры программы Hello, world!, которая выводит соответствующее сообщение и завершается.
SECTION .data
msg db "Hello, world!",0xa
len equ $ - msg
SECTION .text
global _start ; the program entry point
_start:
mov eax, 4 ; 'write' syscall
mov ebx, 1 ; file descr. 1 (stdout)
mov ecx, msg ; pointer to the data
mov edx, len ; amount of data
int 0x80 ; call to the kernel
mov eax, 1 ; '_exit' syscall
mov ebx, 0 ; zero exit code (success)
int 0x80 ; call to the kernel
global _start
section .text
_start:
mov rax, 1 ; system call 1 is write
mov rdi, 1 ; file handle 1 is stdout
mov rsi, message ; address of string to output
mov rdx, 13 ; number of bytes
syscall ; invoke operating system to do the write
mov eax, 60 ; system call 60 is exit
xor rdi, rdi ; exit code 0
syscall ; invoke operating system to exit
message:
db "Hello, World", 10 ; note the newline at the end
SECTION .text
org 0x100 ; эта директива нужна только в случае .com файла, в котором нет никаких секций
mov ah, 0x9
mov dx, hello
int 0x21
mov ax, 0x4c00 ; ah == 0x4c al == 0x00
int 0x21
SECTION .data
hello DB "Hello, world!",0xd,0xa,'$'
%include 'WIN32N.INC'
EXTERN MessageBoxA
Import MessageBoxA user32.dll
EXTERN ExitProcess
Import ExitProcess kernel32.dll
SECTION CODE USE32 CLASS=CODE
..start:
push UINT MB_OK
push LPCTSTR title
push LPCTSTR banner
push HWND NULL
call [MessageBoxA]
push UINT NULL
call [ExitProcess]
SECTION DATA USE32 CLASS=DATA
banner db 'Hello, world!',0xD,0xA,0
title db 'Hello',0
; Hello.asm
EXTERN MessageBoxW
EXTERN ExitProcess
SECTION .text USE64
start:
sub rsp, 28h ; 32 bytes for Microsoft x64 calling convention "shadow space" + 8 bytes for stack aligning to 16 bytes boundry after call put on stack 8 bytes return address
xor rcx, rcx ; HWND hWnd = NULL
lea rdx, [banner] ; LPCTSTR lpText = banner
lea r8, [title] ; LPCTSTR lpCaption = title
xor r9, r9 ; UINT uType = MB_OK
call MessageBoxW ; MessageBox(hWnd, lpText, lpCaption, uType)
xor rcx, rcx ; UINT uExitCode = 0
call ExitProcess ; ExitProcess(uExitCode)
SECTION .data
banner dw __utf16__('Hello, world!'),0
title dw __utf16__('Hello!'),0
>nasm -f win64 Hello.asm
>golink Hello.obj kernel32.dll user32.dll
SECTION .data
msg db "Hello, world!",0xa
len equ $ - msg
SECTION .text
global _start ; the program entry point
_start:
push dword len
push dword msg
push dword 1 ; 1 is the file descriptor of stdout
mov eax, 4 ; 4 is the 'write' syscall
push eax ; we must leave an extra dword on the stack
int 0x80 ; call to the kernel
add esp, 16 ; clean up the stack
push dword 0 ; 0 is the exit code (success)
mov eax, 1 ; 1 is the '_exit' syscall
push eax ; extra dword on the stack
int 0x80 ; call to the kernel
; no cleanup - we will never return
bits 32
%include 'mos.inc'
section .text
MOS_HEADER01 main,image_end,memory_end,stacktop,0,0
main:
redraw:
call draw_window
wait_event:
MOS_WAITEVENT
dec eax
jz redraw
dec eax
jz key
;button pressed; we have only one button, close
MOS_EXIT
key:
;key pressed, read it and ignore
mov eax, MOS_SC_GETKEY
int 0x40
jmp wait_event
draw_window:
MOS_STARTREDRAW
xor eax, eax
mov ebx, 10*65536 + 150
mov ecx, 40*65536 + 50
mov edx, 0x33FFFFFF
mov edi, header
int 0x40 ;define&draw window
mov eax, MOS_SC_WRITETEXT
mov ebx, 30*65536 + 10
mov ecx, 0x80000000
mov edx, string
int 0x40 ;display string
MOS_ENDREDRAW
ret
section .data
header db 'HelloWorld test',0
string db 'Hello, World!',0
image_end:
section .bss
alignb 4
stack resb 1024
stacktop:
memory_end:
Известные программы, написанные на NASM
- Asmutils — набор системных утилит для операционных систем BSD, UnixWare, Solaris и AtheOS.
- Проект AsmOS[10] — операционная система на ассемблере NASM (сейчас на стадии разработки).
Примечания
- ↑ The nasm Open Source Project on Open Hub: Languages Page — 2006.
- ↑ 1.1 What Is NASM? The Netwide Assembler: NASM. Официальный сайт. — «NASM, is an 80x86 and x86-64 assembler». Дата обращения: 14 июля 2010. Архивировано из оригинала 18 февраля 2012 года.
- ↑ Ассемблеры для Linux: Сравнение GAS и NASM . Дата обращения: 14 июля 2010. Архивировано 16 августа 2011 года.
- ↑ 1 2 Использование ассемблера NASM в Windows . Дата обращения: 17 июля 2010. Архивировано из оригинала 20 июля 2009 года.
- ↑ 1 2 Рэндолл Хайд. Which Assembler is the Best? (англ.). Дата обращения: 18 июля 2010. Архивировано из оригинала 18 февраля 2012 года.
- ↑ Поддержка Intel-синтаксиса, вызываемого через специальную директиву
.intel_syntax
, появилась в gas-2.10; см. gas/NEWS (англ.). Дата обращения: 18 июля 2010. Архивировано из оригинала 18 февраля 2012 года. - ↑ C.2.33 Version 0.98.09b with John Coffman patches released 28-Oct-2001 . The Netwide Assembler: NASM. Appendix C: NASM Version History. Официальный сайт. Дата обращения: 18 июля 2010. Архивировано из оригинала 18 февраля 2012 года.
- ↑ Chapter 7: Output Formats . The Netwide Assembler: NASM. Официальный сайт. Дата обращения: 14 июля 2010. Архивировано из оригинала 18 февраля 2012 года.
- ↑ Использование различных компиляторов в КолибриОС . Дата обращения: 10 февраля 2022. Архивировано 10 февраля 2022 года.
- ↑ Операционная система на ассемблере NASM . Дата обращения: 5 июля 2010. Архивировано 20 октября 2011 года.
Литература
- Рудольф Марек. Ассемблер на примерах. Базовый курс. — СПб.: Наука и техника, 2005. — 240 с. — ISBN 5-94387-232-9.
- А. В. Столяров. Программирование на языке ассемблера NASM для ОС Unix. — М.: МАКС Пресс, 2011. — 188 с. — ISBN 978-5-317-03627-0.
Ссылки
- Официальный сайт
- Проект NASM на сайте SourceForge.net
- Расширенный ассемблер: NASM
- Введение в NASM (низкоуровневое программирование для Windows)
В статье не хватает ссылок на источники (см. рекомендации по поиску). |