Netwide Assembler
Original author(s) | Simon Tatham, Julian Hall |
---|---|
Developer(s) | H. Peter Anvin, Chang Seok Bae, Jim Kukunas, Frank B. Kotler, Cyrill Gorcunov |
Initial release | October 1996; 27 years ago (1996-10) |
Stable release | |
Repository |
|
Written in | Assembly, C[2] |
Operating system | Unix-like, Windows, OS/2, MS-DOS |
Available in | English |
Type | x86 assembler |
License | BSD 2-clause |
Website | www |
The Netwide Assembler (NASM) is an assembler and disassembler for the Intel x86 architecture. It can be used to write 16-bit, 32-bit (IA-32) and 64-bit (x86-64) programs. It is considered one of the most popular assemblers for Linux and x86 chips.[3]
It was originally written by Simon Tatham with assistance from Julian Hall. As of 2016[update], it is maintained by a small team led by H. Peter Anvin.[4] It is open-source software released under the terms of a simplified (2-clause) BSD license.[5]
Features
NASM can output several binary formats, including COFF, OMF, a.out, Executable and Linkable Format (ELF), Mach-O and binary file (.bin, binary disk image, used to compile operating systems), though position-independent code is supported only for ELF object files. It also has its own binary format called RDOFF.[6]
The variety of output formats allows retargeting programs to virtually any x86 operating system (OS). It can also create flat binary files, usable to write boot loaders, read-only memory (ROM) images, and in various facets of OS development.[6] It can run on non-x86 platforms as a cross assembler, such as PowerPC and SPARC, though it cannot generate programs usable by those machines.
NASM uses a variant of Intel assembly syntax instead of AT&T syntax.[7] It also avoids features such as automatic generation of segment overrides (and the related ASSUME directive) used by MASM and compatible assemblers.[6]
Sample programs
A "Hello, world!" program for the DOS operating system:
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, '$'
An equivalent program for 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
An example of a similar program for Microsoft Windows:
global _main extern _MessageBoxA@16 extern _ExitProcess@4 section code use32 class=code _main: push dword 0 ; UINT uType = MB_OK push dword title ; LPCSTR lpCaption push dword banner ; LPCSTR lpText push dword 0 ; HWND hWnd = NULL call _MessageBoxA@16 push dword 0 ; UINT uExitCode call _ExitProcess@4 section data use32 class=data banner: db 'Hello, world!', 0 title: db 'Hello', 0
A 64-bit program for Apple OS X that inputs a keystroke and shows it on the screen:
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, 0 ; 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
section .data
vuid db "BC220425429", 0 ; Provided VUID: "BC220425429" numeric_array times 10 db 0 ; Array to store numeric digits largest_digit db 0 ; Variable to store the largest digit updated_array times 10 db 0 ; Array to store updated VUID temp_array times 10 db 0 ; Temporary array for sorting
section .text global _start
_start:
; Step 1: Store the numeric part of VUID in an array mov esi, vuid ; Point to the VUID string mov ecx, 10 ; Loop counter for 10 digits mov ebx, numeric_array ; Point to the numeric_array
extract_digits:
mov al, [esi] ; Load character from VUID cmp al, 0 ; Check if end of string je end_extract ; If end of string, exit loop
cmp al, '0' ; Check if character is a digit jl next_char ; If not a digit, skip to next character cmp al, '9' jg next_char
sub al, '0' ; Convert character to numeric value mov [ebx], al ; Store numeric value in array inc ebx ; Move to next element in array
next_char:
inc esi ; Move to next character in VUID loop extract_digits ; Repeat until all 10 digits are extracted
end_extract:
; Step 2: Find the largest numeric digit mov ebx, numeric_array ; Point to the numeric_array mov al, [ebx] ; Load the first digit mov [largest_digit], al ; Assume it as the largest digit
mov ecx, 9 ; Loop counter for remaining digits inc ebx ; Move to the next digit
compare_digits:
mov al, [ebx] ; Load the digit cmp al, [largest_digit] ; Compare with largest digit found so far jle skip_update ; If less than or equal, skip update mov [largest_digit], al ; Update largest digit
skip_update:
inc ebx ; Move to the next digit loop compare_digits ; Repeat until all digits are compared
; Step 3: Subtract each numeric digit from the largest digit mov ebx, numeric_array ; Point to the numeric_array mov edi, updated_array ; Point to the updated_array
subtract_digits:
mov al, [ebx] ; Load numeric digit sub al, [largest_digit] ; Subtract from largest digit mov [edi], al ; Store the result in updated_array inc ebx ; Move to the next digit inc edi ; Move to the next element in updated_array loop subtract_digits ; Repeat for all digits
; Step 4: Sort and store updated VUID in ascending order ; (You can implement any sorting algorithm here, like bubble sort or insertion sort)
; Sort updated_array using bubble sort mov ecx, 10 ; Number of elements dec ecx ; Outer loop counter
outer_loop:
mov ebx, updated_array ; Reset pointer to the beginning of the array mov edx, 9 ; Inner loop counter
inner_loop:
mov al, [ebx] ; Load current element mov ah, [ebx + 1] ; Load next element cmp al, ah ; Compare current and next element jg swap_elements ; If current element > next element, swap inc ebx ; Move to the next element dec edx ; Decrement inner loop counter jnz inner_loop ; Repeat inner loop until edx = 0 loop outer_loop ; Repeat outer loop until ecx = 0
; Store sorted array back to updated_array mov ebx, updated_array ; Point to the updated_array mov edi, temp_array ; Point to the temporary array for sorting mov ecx, 10 ; Loop counter rep movsb ; Copy the sorted array back to updated_array
; Display the sorted array mov eax, 4 ; Syscall number for sys_write mov ebx, 1 ; File descriptor (stdout) mov ecx, updated_array ; Pointer to the array mov edx, 10 ; Number of bytes to write int 0x80 ; Call kernel
; Exit the program mov eax, 1 ; Syscall number for sys_exit xor ebx, ebx ; Exit code 0 int 0x80 ; Call kernel
swap_elements:
; Swap elements in updated_array mov al, [ebx] ; Move current element to al mov ah, [ebx + 1] ; Move next element to ah mov [ebx], ah ; Move next element to current position mov [ebx + 1], al ; Move current element to next position jmp inner_loop ; Continue inner loop
Development
NASM version 0.90 was released in October 1996.[5]
Version 2.00 was released on 28 November 2007, adding support for x86-64 extensions.[4] The development versions are not uploaded to SourceForge.net, but are checked into GitHub with binary snapshots available from the project web page.
A search engine for NASM documentation is also available.[8]
In July 2009, as of version 2.07, NASM was released under the Simplified (2-clause) BSD license. Previously, because it was licensed under LGPL, it led to development of Yasm, a complete rewrite of under the New BSD License. Yasm offered support for x86-64 earlier than NASM. It also added support for GNU Assembler syntax.
RDOFF
Relocatable Dynamic Object File Format (RDOFF) is used by developers to test the integrity of NASM's object file output abilities. It is based heavily on the internal structure of NASM,[9] essentially consisting of a header containing a serialization of the output driver function calls followed by an array of sections containing executable code or data. Tools for using the format, including a linker and loader, are included in the NASM distribution.
Until version 0.90 was released in October 1996, NASM supported output of only flat-format executable files (e.g., DOS COM files). In version 0.90, Simon Tatham added support for an object-file output interface, and for DOS .OBJ files for 16-bit code only.[10]
NASM thus lacked a 32-bit object format. To address this lack, and as an exercise to learn the object-file interface, developer Julian Hall put together the first version of RDOFF, which was released in NASM version 0.91.[10]
Since this initial version, there has been one major update to the RDOFF format, which added a record-length indicator on each header record,[11] allowing programs to skip over records whose format they do not recognise, and support for multiple segments; RDOFF1 only supported three segments: text, data and bss (containing uninitialized data).[9]
The RDOFF format is strongly deprecated and has been disabled starting in NASM 2.15.04.[12]
See also
References
- ^ "Release 2.16.03". 17 April 2024. Retrieved 23 April 2024.
- ^ "NASM, the Netwide Assembler". GitHub. 25 October 2021.
- ^ Ram Narayan. "Linux assemblers: A comparison of GAS and NASM". IBM. Archived from the original on 3 October 2013.
two of the most popular assemblers for Linux, GNU Assembler (GAS) and Netwide Assembler (NASM)
- ^ a b "The Netwide Assembler". Retrieved 27 June 2008.
- ^ a b "NASM Version History". Retrieved 3 August 2019.
- ^ a b c "NASM Manual". Archived from the original on 23 February 2009. Retrieved 15 August 2009.
- ^ Randall Hyde. "NASM: The Netwide Assembler". Archived from the original on 12 September 2010. Retrieved 27 June 2008.
- ^ "NASM Doc Search Engine". Archived from the original on 23 January 2010. Retrieved 14 September 2009.
- ^ a b "NASM Manual Ch. 6". Retrieved 27 June 2008.
- ^ a b "NASM CVS". 8 June 2008. Retrieved 27 June 2008.
- ^ "V1-V2.txt". 4 December 2002. Retrieved 27 June 2008.
- ^ "Relocatable Dynamic Object File Format (deprecated)".
Further reading
- Jeff Duntemann (2000). Assembly Language Step by Step. J Wiley and Sons. ISBN 0-471-37523-3.
External links
- Official website
- Netwide Assembler on SourceForge
- Special edition for Win32 and BeOS.
- A comparison of GAS and NASM at IBM
- "Netwide Assembler". Freecode.: a converter between the source format of the assemblers NASM and GAS
- v
- t
- e
- A86/A386
- Flat Assembler (FASM)
- GNU Assembler (GAS)
- High Level Assembly (HLA)
- Microsoft Macro Assembler (MASM)
- Netwide Assembler (NASM)
- Turbo Assembler (TASM)
- Open Watcom Assembler (WASM)
issues