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
 

Assembly Online Compiler

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.

About Assembly

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.

Syntax help

Assembly language usually consists of three sections,

  1. Data section

    To initialize variables and constants, buffer size these values doesn't change at runtime.

  2. bss section

    To declare variables

  3. text section

    _start specifies the starting of this section where the actually code is written.

Variables

There are various define directives to allocate space for variables for both initialized and uninitialized data.

1. To allocate storage space to Initialized data

Syntax

variable-name    define-directive    initial-value 
Define DirectiveDescriptionAllocated Space
DBDefine Byte1 byte
DWDefine Word2 bytes
DDDefine Doubleword4 bytes
DQDefine Quadword8 bytes
DTDefine Ten Bytes10 bytes

2. To allocate storage space to un-initialized data

Define DirectiveDescription
RESBReserve a Byte
RESWReserve a Word
RESDReserve a Doubleword
RESQReserve a Quadword
RESTReserve a Ten Bytes

Constants

Constants can be defined using

1. equ

  • To define numeric constants
CONSTANT_NAME EQU regular-exp or value

2. %assign

  • To define numeric constants.
%assign constant_name value

3. %define

  • To define numeric or string constants.
%define constant_name value

Loops

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.

Procedures

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