TITLE Arrays, Addressing, and Stack-Passed Parameter
INCLUDE Irvine32.inc
.data
LO equ 5 ; Lower bound for random numbers
HI equ 60 ; Upper bound for random numbers
ARRAYSIZE equ 200 ; Size of the array
randArray DWORD ARRAYSIZE dup(?) ; Array to store random numbers
countsArray DWORD (HI-LO+1) dup(0) ; Array to store counts of each number
intro1 BYTE "This program generates 200 random integers between 15 and 50, inclusive.", 0
intro2 BYTE "It then displays the original list, sorts the list, displays the median value of the list, ", 0
intro3 BYTE "displays the list sorted in ascending order, and finally displays the number of instances ", 0
intro4 BYTE "of each generated value, starting with the number of lowest.", 0
myName BYTE "Programmed by ME", 0
unsortedTitle BYTE "Your unsorted random numbers:", 0
sortedTitle BYTE "Your sorted random numbers:", 0
countsTitle BYTE "Your list of instances of each generated number, starting with the smallest value:", 0
medianTitle BYTE "The median value of the array: ", 0
goodbyeMessage BYTE "Goodbye, and thanks for using my MASM program!", 0
.code
main PROC
; Initialize the program
call Randomize
push OFFSET intro1
push OFFSET intro2
push OFFSET intro3
push OFFSET intro4
call introduction
; Fill the array with random numbers
push OFFSET randArray
call fillArray
; Display the unsorted array
push ARRAYSIZE
push OFFSET randArray
push OFFSET unsortedTitle
call displayList
; Sort the array
push OFFSET randArray
call sortList
; Display the median
push OFFSET randArray
push OFFSET medianTitle
call displayMedian
; Display the sorted array
push ARRAYSIZE
push OFFSET randArray
push OFFSET sortedTitle
call displayList
; Count elements in the array
push OFFSET countsArray
push OFFSET randArray
call countList
; Display the counts
push (HI-LO+1)
push OFFSET countsArray
push OFFSET countsTitle
call displayList
;Display goodbye
call goodbye
exit
main ENDP
;------------------------------------------------------------------------------
;Introduction
;------------------------------------------------------------------------------
introduction PROC
pushad ; Save all general-purpose registers
mov esi, [esp + 32] ; Move intro1's address into ESI
call WriteString ; Display intro1
call Crlf
mov esi, [esp + 36] ; Move intro2's address into ESI
call WriteString ; Display intro2
call Crlf
mov esi, [esp + 40] ; Move intro3's address into ESI
call WriteString ; Display intro3
call Crlf
mov esi, [esp + 44] ; Move intro4's address into ESI
call WriteString ; Display intro4
call Crlf
popad ; Restore all general-purpose registers
ret 16 ; Clean up the stack and return
introduction ENDP
;------------------------------------------------------------------------------
;Fill Array
;------------------------------------------------------------------------------
fillArray PROC
push ebp
mov ebp, esp ; Establish stack frame
mov ecx, ARRAYSIZE ; Set loop counter to the size of the array
mov edi, [ebp+8] ; Address of randArray
fillLoop:
push HI ; Upper limit for random number
push LO ; Lower limit for random number
call RandomRange
add esp, 8 ; Clean up the stack
mov [edi], eax ; Store the random number in the array
add edi, 4 ; Move to the next element in the array
loop fillLoop ; Loop until the array is filled
pop ebp ; Restore base pointer
ret 4 ; Clean up the stack and return
fillArray ENDP
;------------------------------------------------------------------------------
;List sort
;------------------------------------------------------------------------------
sortList PROC
push esi
push edi
push ebx
mov esi, [esp + 12] ; esi points to the start of the array (randArray)
mov ecx, ARRAYSIZE ; Loop counter for the outer loop
outerLoop:
dec ecx ; Decrement outer loop counter
mov ebx, ecx ; Inner loop counter
mov edi, esi ; Start of the array for inner loop
innerLoop:
mov eax, [edi] ; Load current element
cmp eax, [edi+4] ; Compare with next element
jle noSwap ; If in correct order, no swap needed
; Swap elements
xchg eax, [edi+4] ; Exchange with next element
mov [edi], eax ; Store back the swapped value
noSwap:
add edi, 4 ; Move to the next element
dec ebx ; Decrement inner loop counter
jnz innerLoop ; Continue inner loop if not zero
cmp ecx, 1 ; Check if outer loop is finished
jne outerLoop ; Continue outer loop if not finished
pop ebx
pop edi
pop esi
ret 4 ; Clean up the stack and return
sortList ENDP
;------------------------------------------------------------------------------
;Display the List
;------------------------------------------------------------------------------
displayList PROC
push ebp
mov ebp, esp
mov edx, [ebp + 8] ; Pointer to title string
call WriteString ; Display title
call Crlf ; New line
mov ecx, [ebp + 16] ; Length of the array
mov ebx, [ebp + 12] ; Pointer to the array
displayLoop:
test ecx, ecx ; Check if loop counter is 0
jz endDisplay ; If zero, end loop
mov eax, [ebx] ; Load current array element
call WriteDec ; Display element
push eax ; Save EAX since WriteChar modifies it
mov al, ' ' ; Load space character into AL
call WriteChar ; Write space character
pop eax ; Restore EAX
add ebx, 4 ; Move to next element
loop displayLoop
endDisplay:
call Crlf ; New line after list
pop ebp
ret 12 ; Clean up the stack and return
displayList ENDP
;------------------------------------------------------------------------------
;Display Median
;------------------------------------------------------------------------------
displayMedian PROC
push ebp
mov ebp, esp
mov edx, [ebp + 8] ; Pointer to median title string
call WriteString ; Display title
mov eax, ARRAYSIZE ; Load array size into eax
mov ebx, [ebp + 12] ; Pointer to the array (randArray)
test eax, 1 ; Check if even or odd
jnz oddSize ; If odd, jump to handling for an odd-sized array
; Handle even-sized array
shr eax, 1 ; Divide by 2 to find the middle, eax now has the upper middle index
dec eax ; Adjust for the lower middle index (zero-based)
imul ecx, eax, 4 ; Multiply index by 4 to get byte offset for the lower middle element
add ebx, ecx ; Adjust ebx to point to the lower middle element
mov eax, [ebx] ; Load the lower middle element
add eax, [ebx + 4] ; Add the value of the upper middle element
sar eax, 1 ; Arithmetic shift right by 1 to get the average
jmp displayMedianValue ; Proceed to display the median
oddSize:
; Handle odd-sized array
shr eax, 1 ; Divide by 2 to find the middle index
imul ecx, eax, 4 ; Multiply index by 4 to get byte offset
add ebx, ecx ; Adjust ebx to point to the middle element
mov eax, [ebx] ; Load the middle element
displayMedianValue:
; Display the median value
call WriteDec ; Display median value
call Crlf ; New line
pop ebp
ret 8 ; Clean up the stack and return
displayMedian ENDP
;------------------------------------------------------------------------------
;Count List
;------------------------------------------------------------------------------
countList PROC
push ebp
mov ebp, esp
mov esi, [ebp + 12] ; Pointer to randArray
mov edi, [ebp + 8] ; Pointer to countsArray
xor ecx, ecx ; Clear ecx for counting
mov ecx, ARRAYSIZE ; Counter set to size of randArray
countLoop:
test ecx, ecx ; Check if loop counter is 0
jz endCount ; If zero, end loop
mov eax, [esi] ; Load current element from randArray
sub eax, LO ; Subtract LO to get index for countsArray
inc dword ptr [edi + eax*4] ; Increment count for this element
add esi, 4 ; Move to next element in randArray
loop countLoop
endCount:
pop ebp
ret 8 ; Clean up the stack and return
countList ENDP
;------------------------------------------------------------------------------
; Goodbye Message
; Displays a farewell message to the user.
;------------------------------------------------------------------------------
goodbye PROC
pushad ; Save all general-purpose registers
mov edx, OFFSET goodbyeMessage ; Load the address of the goodbye message
call WriteString ; Display the goodbye message
call Crlf ; New line for clean output
popad ; Restore all general-purpose registers
ret
goodbye ENDP
Invoke ExitProcess,0 ; exit to OS
END main
Write, Run & Share Assembly code online using OneCompiler's Assembly online compiler for free. It's one of the robust, feature-rich online compilers for Assembly language. Getting started with the OneCompiler's Assembly compiler is simple and pretty fast. The editor shows sample boilerplate code when you choose language as Assembly and start coding.
Assembly language(asm) is a low-level programming language, where the language instructions will be more similar to machine code instructions.
Every assembler may have it's own assembly language designed for a specific computers or an operating system.
Assembly language requires less execution time and memory. It is more helful for direct hardware manipulation, real-time critical applications. It is used in device drivers, low-level embedded systems etc.
Assembly language usually consists of three sections,
Data section
To initialize variables and constants, buffer size these values doesn't change at runtime.
bss section
To declare variables
text section
_start specifies the starting of this section where the actually code is written.
There are various define directives to allocate space for variables for both initialized and uninitialized data.
variable-name define-directive initial-value
| Define Directive | Description | Allocated Space |
|---|---|---|
| DB | Define Byte | 1 byte |
| DW | Define Word | 2 bytes |
| DD | Define Doubleword | 4 bytes |
| DQ | Define Quadword | 8 bytes |
| DT | Define Ten Bytes | 10 bytes |
| Define Directive | Description |
|---|---|
| RESB | Reserve a Byte |
| RESW | Reserve a Word |
| RESD | Reserve a Doubleword |
| RESQ | Reserve a Quadword |
| REST | Reserve a Ten Bytes |
Constants can be defined using
CONSTANT_NAME EQU regular-exp or value
%assign constant_name value
%define constant_name value
Loops are used to iterate a set of statements for a specific number of times.
mov ECX,n
L1:
;<loop body>
loop L1
where n specifies the no of times loops should iterate.
Procedure is a sub-routine which contains set of statements. Usually procedures are written when multiple calls are required to same set of statements which increases re-usuability and modularity.
procedure_name:
;procedure body
ret