NASM

NASM
Логотип программы NASM
Тип компилятор
Авторы Simon Tatham, Julian Hall
Разработчики H. Peter Anvin, Jim Kukunas, Cyrill Gorcunov, Frank B. Kotler
Написана на Си[1]
Операционные системы Linux, Mac OS, Windows, DOS, KolibriOS, BSD
Первый выпуск 1996
Аппаратные платформы x86, x86_64
Последняя версия 2.16.03 (17 апреля 2024)
Репозиторий github.com/netwide-assem…
Лицензия LGPL, с версии 2.07 — упрощённая лицензия BSD
Сайт nasm.us

NASM (Netwide Assembler) — свободный (LGPL и лицензия BSD) ассемблер для архитектуры Intel x86. Используется для написания 16-, 32- и 64-разрядных программ.

История

NASM был создан Саймоном Тэтхемом совместно с Юлианом Холлом и в настоящее время развивается небольшой командой разработчиков на SourceForge.net. Первоначально он был выпущен согласно своей собственной лицензии, но позже эта лицензия была заменена на GNU LGPL после множества проблем, вызванных выбором лицензии. Начиная с версии 2.07 лицензия заменена на «упрощённую BSD» (BSD из 2 пунктов).

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 позволяет компилировать не только программы, но и файлы с любым содержимым. Также мощный макро-препроцессор значительно расширяет возможности для программирования.

Компиляция программ в 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-битного кода, совместимый с Win32- и Win64-компиляторами Microsoft.
  • aout — объектный модуль в варианте формата a.out, использовавшегося в ранних Linux-системах.
  • aoutb — версия формата a.out для BSD-совместимых операционных систем.
  • coff — объектный модуль в формате COFF, совместимом с компоновщиком из DJGPP.
  • elf32 и elf64 — объектный модуль в форматах ELF32 и ELF64, используемых в Linux и Unix System V, включая Solaris x86, UnixWare и SCO Unix.

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

Примеры программы «Hello, world!» под разные ОС

Примеры программы Hello, world!, которая выводит соответствующее сообщение и завершается.

Под операционную систему Linux
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
Под операционную систему Linux (x64)
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
Под операционную систему DOS
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,'$'
Под операционную систему Windows (obj)
%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
Под операционную систему Windows x64 (obj)
; 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

Под операционную систему FreeBSD
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
Под операционную систему KolibriOS[9]
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 (сейчас на стадии разработки).

Примечания

  1. The nasm Open Source Project on Open Hub: Languages Page — 2006.
  2. 1.1 What Is NASM?  (неопр.) The Netwide Assembler: NASM. Официальный сайт. — «NASM, is an 80x86 and x86-64 assembler». Дата обращения: 14 июля 2010. Архивировано из оригинала 18 февраля 2012 года.
  3. Ассемблеры для Linux: Сравнение GAS и NASM  (неопр.). Дата обращения: 14 июля 2010. Архивировано 16 августа 2011 года.
  4. 1 2 Использование ассемблера NASM в Windows  (неопр.). Дата обращения: 17 июля 2010. Архивировано из оригинала 20 июля 2009 года.
  5. 1 2 Рэндолл Хайд. Which Assembler is the Best? (англ.). Дата обращения: 18 июля 2010. Архивировано из оригинала 18 февраля 2012 года.
  6. Поддержка Intel-синтаксиса, вызываемого через специальную директиву .intel_syntax, появилась в gas-2.10; см. gas/NEWS (англ.). Дата обращения: 18 июля 2010. Архивировано из оригинала 18 февраля 2012 года.
  7. 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 года.
  8. Chapter 7: Output Formats  (неопр.). The Netwide Assembler: NASM. Официальный сайт. Дата обращения: 14 июля 2010. Архивировано из оригинала 18 февраля 2012 года.
  9. Использование различных компиляторов в КолибриОС  (неопр.). Дата обращения: 10 февраля 2022. Архивировано 10 февраля 2022 года.
  10. Операционная система на ассемблере 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)
Перейти к шаблону «Ассемблеры»
IDE
Трансляторы
Форматы синтаксиса