Interested Article - NASM
- 2020-12-02
- 1
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 .
NASM успешно конкурирует со стандартным в Linux- и многих других UNIX-системах ассемблером gas . Считается, что качество документации у NASM выше, чем у gas. Кроме того, ассемблер gas по умолчанию использует AT&T-синтаксис , ориентированный на процессоры не от Intel, в то время как NASM использует вариант традиционного для x86-ассемблеров Intel-синтаксиса ; Intel-синтаксис используется всеми ассемблерами для DOS/Windows, например, MASM , TASM , fasm .
Синтаксис языка
В NASM используется Intel-синтаксис записи инструкций. Предложение языка ассемблера NASM (строка программы) может состоять из следующих элементов:
Метка Инструкция Операнды Комментарий
Операнды разделяются между собой запятой. Перед строкой и после инструкции можно использовать любое количество пробельных символов. Комментарий начинается с точки с запятой, а концом комментария считается конец строки. В качестве инструкции может использоваться команда или псевдокоманда (директива компилятора). Если строка очень длинная, то её можно перенести на следующую, используя обратный слеш
\
подобно тому, как это делается в языке
Си
.
Компиляция и компоновка
NASM компилирует программы под различные операционные системы в пределах x86-совместимых процессоров. Находясь в одной операционной системе, можно беспрепятственно откомпилировать исполняемый файл для другой. В общем встроенные средства NASM позволяет компилировать не только программы, но и файлы с любым содержимым. Также мощный макро-препроцессор значительно расширяет возможности для программирования.
Компиляция программ в NASM состоит из двух этапов. Первый — ассемблирование , второй — компоновка . На этапе ассемблирования создаётся объектный код. В нём содержится машинный код программы и данные, в соответствии с исходным кодом , но идентификаторы (переменные, символы) пока не привязаны к адресам памяти. На этапе компоновки из одного или нескольких объектных модулей создаётся исполняемый файл (программа). Операция компоновки связывает идентификаторы, определённые в основной программе, с идентификаторами, определёнными в остальных модулях, после чего всем идентификаторам даются окончательные адреса памяти или обеспечивается их динамическое выделение.
Для компоновки объектных файлов в исполняемые в Windows можно использовать свободный бесплатно распространяемый компоновщик alink (для 64-битных программ компоновщик GoLink), а в Linux — компоновщик ld, который есть в любой версии этой операционной системы.
Для ассемблирования файла нужно ввести следующую команду:
nasm -f format filename -o output
Инструкции перехода
Компилятор обрабатывает текст программы в несколько проходов, благодаря чему можно инструкции перехода размещать до объявления соответствующих меток.
В командах условного и безусловного (
jmp
) переходов используется по умолчанию ближний тип переходов —
near
. Поэтому при возможности короткого перехода, чтобы не завысить размер программы на лишний байт, необходимо специально указать тип перехода
short
. С версии 0.98.09b были добавлены опции оптимизации
-Ox
, которые позволяют автоматически оптимизировать размер инструкций перехода
, в более ранних версиях или без таких опций минимальный размер программы можно получить только ручной модификацией исходного кода.
Формат выходных файлов
NASM поддерживает множество форматов выходных файлов, среди них :
- bin — файл произвольного формата, определяемого только исходным кодом . Пригоден как для файлов данных, так и для модулей с исполняемыми кодами — например, системных загрузчиков, образов ПЗУ , модулей операционных систем , драйверов .SYS в MS-DOS или исполняемых файлов .COM .
- obj — объектный модуль в формате , совместимый с 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 и .
Формат выходного файла можно задать с помощью ключа командной строки -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
- — набор системных утилит для операционных систем BSD, UnixWare, Solaris и AtheOS .
- Проект — операционная система на ассемблере NASM (сейчас на стадии разработки).
Примечания
- — 2006.
- The Netwide Assembler: NASM . Официальный сайт. — «NASM, is an 80x86 and x86-64 assembler». Дата обращения: 14 июля 2010. Архивировано из 18 февраля 2012 года.
- . Дата обращения: 14 июля 2010. 16 августа 2011 года.
- ↑ . Дата обращения: 17 июля 2010. Архивировано из 20 июля 2009 года.
- ↑ Рэндолл Хайд. (англ.) . Дата обращения: 18 июля 2010. Архивировано из 18 февраля 2012 года.
-
Поддержка Intel-синтаксиса, вызываемого через специальную директиву
.intel_syntax
, появилась в gas-2.10; см. (англ.) . Дата обращения: 18 июля 2010. Архивировано из 18 февраля 2012 года. - . The Netwide Assembler: NASM. Appendix C: NASM Version History . Официальный сайт. Дата обращения: 18 июля 2010. Архивировано из 18 февраля 2012 года.
- . The Netwide Assembler: NASM . Официальный сайт. Дата обращения: 14 июля 2010. Архивировано из 18 февраля 2012 года.
- . Дата обращения: 10 февраля 2022. 10 февраля 2022 года.
- . Дата обращения: 5 июля 2010. 20 октября 2011 года.
Литература
- Рудольф Марек. Ассемблер на примерах. Базовый курс. — СПб. : Наука и техника, 2005. — 240 с. — ISBN 5-94387-232-9 .
- А. В. Столяров. . — М. : МАКС Пресс, 2011. — 188 с. — ISBN 978-5-317-03627-0 .
Ссылки
- 2020-12-02
- 1