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 |
Stable release | 2.16.03[1]
/ 17 April 2024 |
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[edit]
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[edit]
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[edit]
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[edit]
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[edit]
References[edit]
- ^ "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[edit]
- Jeff Duntemann (2000). Assembly Language Step by Step. J Wiley and Sons. ISBN 0-471-37523-3.
External links[edit]
- 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