Как писать на ассемблере в 2018 году
Содержание:
- Развитие [ править ]
- Hello World (Using only Win32 system calls)[edit | edit source]
- RDOFF
- Rozvoj
- “Hello, World”–Take Three, with _WriteFile@20
- 6.5.4 elf-расширение директивы COMMON
- 6.6 aout: Объектные файлы a.out Линукс
- 6.7 aoutb: Объектные файлы a.out NetBSD/FreeBSD/OpenBSD
- 6.8 as86: Объектные файлы as86 Линукс
- 6.9 rdf: Перемещаемые динамические объектные файлы
- 3.2.5 TIMES: Повторение инструкций или данных
- 3.3 Эффективные адреса
- The Three Kinds of Operands
- 6.1.1 ORG: Начало бинарного файла
- 6.5.2 Позиционно-независимый код: Специальные символы формата elf и WRT
- Příklady sestavených programů pro různé operační systémy
- NASM — The Netwide Assembler is 80×86 assembler designed for portability and modularity.
Развитие [ править ]
Первый выпуск, версия 0.90, был выпущен в октябре 1996 года.
28 ноября 2007 года была выпущена версия 2.00, в которой добавлена поддержка расширений x86-64 . Разрабатываемые версии не загружаются на SourceForge.net ; вместо этого они регистрируются в GitHub с бинарными снимками, доступными на веб-странице проекта.
Также доступна поисковая машина для документации NASM.
В июле 2009 года, начиная с версии 2.07, NASM был выпущен под упрощенной (2 пункта) лицензией BSD. Ранее, поскольку NASM был лицензирован по LGPL , это привело к разработке Yasm, полностью переписав NASM в соответствии с Новой лицензией BSD . Yasm предлагал поддержку x86-64 раньше, чем NASM. Также добавлена поддержка синтаксиса GNU Assembler .
Hello World (Using only Win32 system calls)[edit | edit source]
In this example we are going to rewrite the hello world example using Win32 system calls. There are several major differences:
- The intermediate file will be a Microsoft Win32 (i386) object file
- We will avoid using interrupts since they may not be portable and therefore we need to bring in several calls from kernel32 DLL
global _start
extern _GetStdHandle@4
extern _WriteConsoleA@20
extern _ExitProcess@4
section .data
str: db 'hello, world',0x0D,0x0A
strLen: equ $-str
section .bss
numCharsWritten: resd 1
section .text
_start:
;
; HANDLE WINAPI GetStdHandle( _In_ DWORD nStdHandle ) ;
;
push dword -11 ; Arg1: request handle for standard output
call _GetStdHandle@4 ; Result: in eax
;
; BOOL WINAPI WriteConsole(
; _In_ HANDLE hConsoleOutput,
; _In_ const VOID *lpBuffer,
; _In_ DWORD nNumberOfCharsToWrite,
; _Out_ LPDWORD lpNumberOfCharsWritten,
; _Reserved_ LPVOID lpReserved ) ;
;
push dword ; Arg5: Unused so just use zero
push numCharsWritten ; Arg4: push pointer to numCharsWritten
push dword strLen ; Arg3: push length of output string
push str ; Arg2: push pointer to output string
push eax ; Arg1: push handle returned from _GetStdHandle
call _WriteConsoleA@20
;
; VOID WINAPI ExitProcess( _In_ UINT uExitCode ) ;
;
push dword ; Arg1: push exit code
call _ExitProcess@4
In order to assemble, link and run the program we need to do the following:
$ nasm -f win32 -g helloWorldWin32.asm $ ld -e _start helloWorldwin32.obj -lkernel32 -o helloWorldWin32.exe
In this example we use the command line option when invoking to specify the entry point for program execution. Otherwise we would have to use as the entry point rather than . This example was run under cygwin, in a Windows command prompt the link step would be different. One last note, does not behave well within a cygwin console, so in order to see output the final exe should be run within a Windows command prompt.
RDOFF
| Tarafından geliştirilmiş | Julian Hall |
|---|---|
| Biçim türü | Nesne dosya biçimi |
| İçin konteyner | Nesne kodu |
Yeniden Konumlandırılabilir Dinamik Nesne Dosyası Biçimi (RDOFF), geliştiriciler tarafından NASM’nin nesne dosyası çıktı yeteneklerinin bütünlüğünü test etmek için kullanılır. Esas olarak , çıkış sürücüsü işlev çağrılarının bir serileştirmesini ve ardından yürütülebilir kod veya verileri içeren bir bölüm dizisini içeren bir başlıktan oluşan NASM’nin dahili yapısına dayanır . Bir bağlayıcı ve yükleyici dahil formatı kullanmak için araçlar, NASM dağıtımına dahildir.
0.90 sürümü Ekim 1996’da piyasaya sürülene kadar, NASM yalnızca düz formatlı çalıştırılabilir dosyaların (örn. DOS COM dosyaları ) çıktılarını destekledi . 0.90 sürümünde, Simon Tatham bir nesne dosyası çıktı arabirimi ve yalnızca 16 bit kod için DOS .OBJ dosyaları için destek ekledi.
Bu nedenle NASM, 32 bitlik bir nesne formatından yoksundu. Bu eksikliği gidermek ve nesne-dosya arayüzünü öğrenmek için bir alıştırma olarak geliştirici Julian Hall, NASM 0.91 sürümünde yayınlanan RDOFF’un ilk sürümünü bir araya getirdi.
Bu ilk sürümden bu yana, RDOFF biçiminde bir büyük güncelleme yapıldı; bu, her başlık kaydına bir kayıt uzunluğu göstergesi ekleyerek programların biçimini tanımadıkları kayıtları atlamasına olanak tanıdı ve birden çok segmenti destekledi; RDOFF1 yalnızca üç segmenti destekler: metin , veri ve bss (başlatılmamış veriler içerir).
Rozvoj
První vydání, verze 0.90, bylo vydáno v říjnu 1996.
Dne 28. listopadu 2007 byla vydána verze 2.00 s přidáním podpory pro rozšíření x86-64 . Vývojové verze se nenahrávají na SourceForge.net ; místo toho se zkontrolují do GitHubu pomocí binárních snímků dostupných z webové stránky projektu.
K dispozici je také vyhledávač dokumentace NASM.
V červenci 2009, od verze 2.07, byl NASM vydán pod licencí BSD Simplified (2-clause). Dříve, protože NASM bylo licencováno pod LGPL , vedlo to k vývoji Yasmu, úplného přepsání NASM pod . Yasm nabídl podporu pro x86-64 dříve než NASM. Přidala také podporu syntaxe GNU Assembler .
“Hello, World”–Take Three, with _WriteFile@20
This time, we’re going to use Win32 API to directly access the console.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
global _main
extern _GetStdHandle@4
extern _WriteFile@20
extern _ExitProcess@4
section .text
_main:
; DWORD bytes;
mov ebp, esp
sub esp, 4
; hStdOut = GetstdHandle( STD_OUTPUT_HANDLE)
push -11
call _GetStdHandle@4
mov ebx, eax
; WriteFile( hstdOut, message, length(message), &bytes, 0);
push
lea eax,
push eax
push (message_end - message)
push message
push ebx
call _WriteFile@20
; ExitProcess(0)
push
call _ExitProcess@4
; never here
hlt
message:
db 'Hello, World', 10
message_end:
|
Like in the previous examples, you have to assemble, link and run. However, let me introduce another way to do all 3 in one line:
1 |
C:\work>nasm -fwin32 hellow.asm && gcc -m32 hellow.obj -o hellow.exe && hellow |
If all went well, you should see something like this:
1 2 3 |
C:\work>nasm -fwin32 hellow.asm && gcc -m32 hellow.obj -o hellow.exe && hellow Hello, World C:\work> |
Again, couple of important points:
- Where is GetStdHandle declared in? The answer is, Kernel32.dll. The immediate next question is, how did gcc know to link with Kernel32.lib? Aren’t we supposed to get an error ? The short answer is, because we specified the -m32 flag.
- Why the funny names, like _GetStdHandle@4? The answer has to do something with the way method names are mangled or decorated in Win32. That’s juicy material for a next article. For now, remember that the calling convention for Win32 is known as __stdcall, which defines the way functions are made available to public after compilation. Specifically, the MSDN article says, that under __stdcall, “an underscore (_) is prefixed to the name. The name is followed by the at sign (@) followed by the number of bytes (in decimal) in the argument list.“
- Why the constant (-11)? That’s how we tell _GetStdHandle@4 to get us the “Standard Output” (which in this case, is the screen). Consider this the equivalent way of grabbing a handle to stdout in C, and cout in C++.
Again, knowing how a Win32 function is mangled, or decorated after compiling seems like far too much to expect at this level. After all, all C programmers get to happily write “ExitProcess” instead of “_ExitProcess@4”.
In the next step, we will look at how this can be done.
6.5.4 elf-расширение директивы COMMON
ELF позволяет задавать требования к выравниванию общих переменных. Это делается
путем помещения числа (которое должно быть степенью двойки) после имени и размера
общей переменной и отделения этого числа (как обычно) двоеточием. Например,
массив двойных слов, который должен быть выровнен по двойным словам:
common dwordarray 128:4
Эта строка объявляет массив размером 128 байт и требует, чтобы он был выровнен
по 4-байтной границе.
6.6 aout: Объектные файлы
a.out Линукс
Формат aout генерирует объектные файлы a.out
в форме, используемой устаревшими Линукс системами. (Он отличается от других
объектных файлов a.out магическим числом в первых
четырех байтах файла. Также некоторые реализации a.out,
например NetBSD, поддерживают позиционно-независимый код, который реализация
Линукс не знает).
Формат a.out подразумевает расширение выходных
файлов по умолчанию .o.
Этот формат очень простой. Он не поддерживает специальных директив и символов,
не использует SEG или WRT
и в нем нет расширений никаких стандартных директив. Он поддерживает только
три стандартных секции с именами .text, .data и
.bss.
6.7 aoutb: Объектные файлы
a.out NetBSD/FreeBSD/OpenBSD
Формат aoutb генерирует объектные файлы a.out
в форме, используемой различными BSD-клонами UNIX: NetBSD, FreeBSD и OpenBSD.
Для большинства объектных файлов этот формат не отличается от aout
за исключением магического числа в первых четырех байтах файла. Однако формат
поддерживает (как и формат elf) позиционно-независимый
код, поэтому вы можете использовать его для написания разделяемых библиотек
BSD.
Расширение объектных файлов формата aoutb по умолчанию
.o.
Формат не поддерживает специальных директив и символов и имеет только три стандартных
секции с именами .text, .data и .bss.
Несмотря на это, для обеспечения типов перемещений в позиционно-независимом
коде он поддерживает использование WRT так же,
как это делает elf. Более подробно это описано
в .
aoutb, как и elf
поддерживает также расширение директивы GLOBAL:
см. .
6.8 as86: Объектные файлы
as86 Линукс
16-битный ассемблер Линукс as86 имеет свой собственный
нестандартный формат объектных файлов. Хотя его компаньон компоновщик ld86
выдает что-то близкое к обычным бинарникам a.out,
объектный формат, используемый для взаимодействия между as86
и ld86, все же не является a.out.
NASM на всякий случай поддерживает данный формат как as86.
Расширение выходного файла по умолчанию для данного формата .o.
Формат as86 это очень простой объектный
формат (с точки зрения NASM). Он не поддерживает специальных директив и символов,
не использует SEG и WRT,
и в нем нет никаких расширений стандартных директив. Он поддерживает только
три стандартных секции с именами .text, .data и
.bss.
6.9 rdf: Перемещаемые динамические
объектные файлы
Выходной формат rdf создает объектные файлы RDOFF.
RDOFF это «доморощенный» формат объектных файлов, разработанный вместе
с NASM и отражающий в себе внутреннюю структуру ассемблера.
RDOFF не используется никакими широко известными операционными системами. Однако
тот, кто пишет собственную систему, возможно захочет использовать его в качестве
собственного объектного формата, так как разработан он прежде всего для упрощения
и содержит очень мало бюрократии в заголовках файлов.
Архив Unix NASM и архив DOS с исходниками имеют подкаталог rdoff,
содержащий набор RDOFF-утилит: RDF-компоновщик, менеджер статических библиотек,
утилита, делающая дамп RDF-файла, и программа, загружающая и выполняющая RDF-исполнимый
файл под Линукс.
Формат rdf поддерживает только стандартные секции
с именами .text, .data и .bss.
3.2.5 TIMES: Повторение инструкций или данных
Префикс TIMES заставляет инструкцию ассемблироваться
несколько раз. Данная псевдо-инструкция отчасти представляет NASM-эквивалент
синтаксиса DUP, поддерживающегося MASM-совместимыми
ассемблерами. Вы можете написать, например
или что-то подобное; однако TIMES более разносторонняя
инструкция. Аргумент TIMES не просто числовая
константа, а числовое выражение, поэтому вы можете писать следующие вещи:
При этом будет резервироваться строго определенное пространство, начиная от
метки buffer и длиной 64 байта. Наконец, TIMES
может использоваться в обычных инструкциях, так что вы можете писать тривиальные
развернутые циклы:
Заметим, что нет никакой принципиальной разницы между times
100 resb 1 и resb 100 за исключением того,
что последняя инструкция будет обрабатываться примерно в 100 раз быстрее из-за
внутренней структуры ассемблера.
Операнд псевдо-инструкции TIMES, подобно EQU
и RESB, является критическим выражением ().
Имейте также в виду, что TIMES не применима в
макросах: причиной служит то, что TIMES обрабатывается
после макро-фазы, позволяющей аргументу TIMES содержать
выражение, подобное 64-$+buffer. Для повторения
более одной строки кода или в сложных макросах используйте директиву препроцессора
%rep.
3.3 Эффективные адреса
Эффективный адрес это любой операнд инструкции со ссылкой на память.
Эффективные адреса в NASM имеют очень простой синтаксис: они содержат выражение
(в результате вычислений которого получается нужный адрес), обрамленное квадратными
скобками. Например:
Любая другая ссылка, не соответствующая этой простой системе, для NASM недействительна,
например es:wordvar.
Более сложные эффективные адреса, когда вовлечено более одного регистра, работают
точно также:
NASM способен воспринимать алгебру таких выражений, поэтому он правильно транслирует
вещи, выглядящие на первый взгляд недопустимыми:
Некоторые варианты эффективных адресов имеют более одной ассемблерной формы;
в большинстве таких ситуаций NASM будет генерировать самую короткую из них.
Например, у нас имеются простые ассемблерные инструкции
и . NASM будет генерировать последнюю
из них, т.к. первый вариант требует дополнительно 4 байта для хранения нулевого
смещения.
NASM имеет механизм подсказок, позволяющий создавать из
и разные инструкции; это порой полезно,
т.к. например и
по умолчанию имеют разные сегментные регистры.
Несмотря на это, вы можете заставить NASM генерировать требуемые формы эффективных
адресов при помощи ключевых слов BYTE, WORD, DWORD
и NOSPLIT. Если вам нужно, чтобы
ассемблировалась со смещением в двойное слово, вместо одного байта по умолчанию,
вы можете написать . Точно также при
помощи вы можете заставить NASM
использовать байтовые смещения для небольших значений, не определяемых при первом
проходе (см. пример такого кода в ).
В особых случаях, будет кодироваться
как с нулевым байтовым смещением, а будет кодироваться с нулевым смещением в двойное слово. Обычная
форма, , будет оставлена без смещения.
NASM будет разделять на ,
т.к. это позволяет избежать использования поля смещения и сэкономить некоторое
пространство; соответственно, будет
разделено на . При помощи ключевого
слова NOSPLIT вы можете запретить такое поведение
NASM: будет буквально оттранслировано
в .
The Three Kinds of Operands
Register Operands
In this tutorial we only care about the integer registers and the xmm
registers. You should already know what the registers are, but here is a quick
review. The 16 integer registers are 64 bits wide and are called:
R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 RAX RCX RDX RBX RSP RBP RSI RDI
(Note that 8 of the registers have alternate names.) You can treat the lowest
32-bits of each register as a register itself but using these names:
R0D R1D R2D R3D R4D R5D R6D R7D R8D R9D R10D R11D R12D R13D R14D R15D EAX ECX EDX EBX ESP EBP ESI EDI
You can treat the lowest 16-bits of each register as a register itself but using these names:
R0W R1W R2W R3W R4W R5W R6W R7W R8W R9W R10W R11W R12W R13W R14W R15W AX CX DX BX SP BP SI DI
You can treat the lowest 8-bits of each register as a register itself but using these names:
R0B R1B R2B R3B R4B R5B R6B R7B R8B R9B R10B R11B R12B R13B R14B R15B AL CL DL BL SPL BPL SIL DIL
For historical reasons, bits 15 through 8 of .. are named:
AH CH DH BH
And finally, there are 16 XMM registers, each 128 bits wide, named:
XMM0 ... XMM15
Study this picture; hopefully it helps:
Memory Operands
These are the basic forms of addressing:
- scale is 1, 2, 4, or 8 only
The number is called the displacement; the plain register is called
the base; the register with the scale is called the index.
Examples:
; displacement only
; base register only
; base + index * scale
; scale is 1
; displacement is -8
; all four components
; uses the address of the variable 'counter' as the displacement
Immediate Operands
These can be written in many ways. Here are some examples from the official docs.
200 ; decimal 0200 ; still decimal - the leading 0 does not make it octal 0200d ; explicitly decimal - d suffix 0d200 ; also decimal - 0d prefex 0c8h ; hex - h suffix, but leading 0 is required because c8h looks like a var 0xc8 ; hex - the classic 0x prefix 0hc8 ; hex - for some reason NASM likes 0h 310q ; octal - q suffix 0q310 ; octal - 0q prefix 11001000b ; binary - b suffix 0b1100_1000 ; binary - 0b prefix, and by the way, underscores are allowed
6.1.1 ORG: Начало бинарного файла
Формат bin предусматривает дополнительную к списку
главы 5 директиву ORG.
Функция этой директивы задавать начальный адрес программы, с которого
она располагается при загрузке в память.
Например, следующий код будет генерировать двойное слово 0x00000104:
org 0x100
dd label
label:
В отличие от директивы ORG, применяемой MASM-совместимыми
ассемблерами, которые позволяют перемещаться в объектном файле и переписывать
уже сгенерированный код, NASM-овская ORG означает
только то, что и соответствующее слово: origin (начало). Ее единственная
функция задавать смещение, которое будет прибавляться ко всем ссылкам
на адреса внутри файла; она не допускает такого жульничества, как MASM. Дополнительные
комментарии содержатся в .
6.5.2 Позиционно-независимый код: Специальные символы формата elf и WRT
Спецификация ELF содержит достаточное число возможностей написания позиционно-независимого
кода (PIC), благодаря которым разделяемые библиотеки ELF весьма гибкие. Однако
это также означает, что NASM должен быть способен генерировать разнообразные
замысловатые типы релокейшнов объектных ELF-файлов.
Так как ELF не поддерживает сегментные ссылки, оператор WRT
для своей обычной цели не используется; вместо этого формат elf
использует WRT для других целей, а именно для специальных
PIC-типов перемещений.
elf определяет пять специальных символов, которые
вы можете использовать с правой стороны оператора WRT
для получения PIC-типов перемещений. Это ..gotpc, ..gotoff,
..got, ..plt и ..sym. Их функции описаны
ниже:
- Ссылка на символ, помеченный как база глобальной таблицы смещений (GOT)
при помощи wrt ..gotpc, будет в результате давать
расстояние от начала текущей секции до глобальной таблицы смещений. (Для ссылки
на GOT используется обычно стандартный символ
_GLOBAL_OFFSET_TABLE_). Таким образом, для получения
реального адреса GOT, вам необходимо прибавить к результату конструкцию $$. - Ссылка на определенную позицию в одной из ваших собственных секций при помощи
wrt ..gotoff будет давать расстояние от начала
GOT до заданной позиции, поэтому прибавив это расстояние к адресу GOT, вы
получите реальный адрес нужной вам позиции. - Ссылка на внешний или глобальный символ при помощи wrt
..got заставляет компоновщик построить элемент GOT, содержащий адрес
символа, поэтому ссылка дает расстояние от начала GOT до этого элемента. Таким
образом, прибавляя к полученной ссылке адрес GOT, вы получите адрес, по которому
содержится адрес символа. - Ссылка на имя процедуры при помощи wrt ..plt
заставляет компоновщик построить элемент таблицы компоновки процедуры (PLT)
и ссылка в результате дает адрес элемента PLT. Вы можете использовать это
обычно только в контексте создания относительных перемещений (т.е. цели для
CALL или JMP), так
как ELF абсолютно не имеет перемещаемых типов для ссылки на элементы PLT. - Ссылка на имя символа при помощи wrt ..sym
заставляет NASM записать обычное перемещение, однако вместо того, чтобы сделать
перемещение относительным к началу секции и затем добавить смещение символа,
он создаст запись смещения непосредственно к запрашиваемому символу. Различие
необходимо из-за особенностей динамического компоновщика.
Более полное объяснение использования типов перемещений для написания в NASM
разделяемых библиотек дано в .
Příklady sestavených programů pro různé operační systémy
Toto je „Ahoj, světe!“ program pro operační systém DOS .
section .text org 0x100 mov ah, 0x9 mov dx, hello int 0x21 mov ax, 0x4c00 int 0x21 section .data hello: db 'Hello, world!', 13, 10, '$'
Ekvivalentní program pro Linux :
global _start section .text _start: mov eax, 4 ; write mov ebx, 1 ; stdout mov ecx, msg mov edx, msg.len int 0x80 ; write(stdout, msg, strlen(msg)); xor eax, msg.len ; invert return value from write() xchg eax, ebx ; value for exit() mov eax, 1 ; exit int 0x80 ; exit(...) section .data msg: db "Hello, world!", 10 .len: equ $ - msg
Příklad podobného programu pro Microsoft Windows :
global _main extern _MessageBoxA@16 extern _ExitProcess@4 section code use32 class=code _main: push dword ; UINT uType = MB_OK push dword title ; LPCSTR lpCaption push dword banner ; LPCSTR lpText push dword ; HWND hWnd = NULL call _MessageBoxA@16 push dword ; UINT uExitCode call _ExitProcess@4 section data use32 class=data banner: db 'Hello, world!', title: db 'Hello',
Níže je 64bitový program pro Apple OS X, který zadává stisknutí klávesy a zobrazuje ji na obrazovce
global _start section .data query_string: db "Enter a character: " query_string_len: equ $ - query_string out_string: db "You have input: " out_string_len: equ $ - out_string section .bss in_char: resw 4 section .text _start: mov rax, 0x2000004 ; put the write-system-call-code into register rax mov rdi, 1 ; tell kernel to use stdout mov rsi, query_string ; rsi is where the kernel expects to find the address of the message mov rdx, query_string_len ; and rdx is where the kernel expects to find the length of the message syscall ; read in the character mov rax, 0x2000003 ; read system call mov rdi, ; stdin mov rsi, in_char ; address for storage, declared in section .bss mov rdx, 2 ; get 2 bytes from the kernel's buffer (one for the carriage return) syscall ; show user the output mov rax, 0x2000004 ; write system call mov rdi, 1 ; stdout mov rsi, out_string mov rdx, out_string_len syscall mov rax, 0x2000004 ; write system call mov rdi, 1 ; stdout mov rsi, in_char mov rdx, 2 ; the second byte is to apply the carriage return expected in the string syscall ; exit system call mov rax, 0x2000001 ; exit system call xor rdi, rdi syscall
NASM — The Netwide Assembler is 80×86 assembler designed for portability and modularity.
NASM is an 80×86 assembler designed for portability and modularity. The project supports a range of object file formats including Linux a.out and ELF, COFF, Microsoft 16-bit OBJ and Win32. It will also output plain binary files.
Its syntax is designed to be simple and easy to understand, similar to Intel’s but less complex. It supports Pentium, P6, MMX, 3DNow! and SSE opcodes, and has macro capability. It includes a disassembler as well.
The Netwide Assembler grew out of an idea on comp.lang.asm.x86 (or possibly alt.lang.asm — I forget which), which was essentially that there didn’t seem to be a good free x86-series assembler around, and that maybe someone ought to write one.
— a86 is good, but not free, and in particular you don’t get any 32-bit capability until you pay. It’s DOS only, too.
— gas is free, and ports over DOS and Unix, but it’s not very good, since it’s designed to be a back end to gcc, which always feeds it correct code. So its error checking is minimal. Also, its syntax is horrible, from the point of view of anyone trying to actually write anything in it. Plus you can’t write 16-bit code in it (properly).
— as86 is Minix- and Linux-specific, and (my version at least) doesn’t seem to have much (or any) documentation.
— MASM isn’t very good, and it’s (was) expensive, and it runs only under DOS.
— TASM is better, but still strives for MASM compatibility, which means millions of directives and tons of red tape. And its syntax is essentially MASM’s, with the contradictions and quirks that entails (although it sorts out some of those by means of Ideal mode). It’s expensive too. And it’s DOS-only.
So here, for your coding pleasure, is NASM. At present it’s still in prototype stage — we don’t promise that it can outperform any of these assemblers. But please, please send us bug reports, fixes, helpful information, and anything else you can get your hands on (and thanks to the many people who’ve done this already! You all know who you are), and we’ll improve it out of all recognition. Again.
Installing NASM under Unix
NASM is an auto-configuring package: once you’ve unpacked it, cd to the directory it’s been unpacked into and type ./configure. This shell script will find the best C compiler to use for building NASM and set up Makefiles accordingly.
Once NASM has auto-configured, you can type make to build the nasm and ndisasm binaries, and then make install to install them in /usr/local/bin and install the man pages nasm.1 and ndisasm.1 in /usr/local/man/man1. Alternatively, you can give options such as —prefix to the configure script (see the file INSTALL for more details), or install the programs yourself.
NASM also comes with a set of utilities for handling the RDOFF custom object-file format, which are in the rdoff subdirectory of the NASM archive. You can build these with make rdf and install them with make rdf_install, if you want them.
If NASM fails to auto-configure, you may still be able to make it compile by using the fall-back Unix makefile Makefile.unx. Copy or rename that file to Makefile and try typing make. There is also a Makefile.unx file in the rdoff subdirectory.