Netwide Assembler sample programs

From Wikibooks, open books for an open world
Jump to navigation Jump to search

This is a collection of sample programs for the Netwide Assembler.

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