# Roll Pair Of Dice And Calculate The Percentage For Each Value After N Trials Using MARS Mips Assembly Assignment Solution.

## Instructions

Objective
Write an assembly language homework to find primes using sieve, greatest common divisor.

## Requirements and Specifications

Screenshots of output

Source Code

Problem 1

INCLUDE Irvine32.inc

.data

DB "----------------------------------------------", 13, 10

DB "1. Display all primes between 2 and 5000", 13, 10

DB "2. Display all primes between 2 and n", 13, 10

DB "3. Euclid's Algorithm", 13, 10

DB "4. Exit", 13, 10

DB "Option?: ", 0

errorOptStr DB "Invalid option.", 13, 10, 13, 10, 0

promptStr DB "Value for n?: ", 0

errorNStr DB "Invalid n value.", 13, 10, 13, 10, 0

promptN1Str DB "Value for first number?: ", 0

promptN2Str DB "Value for second number?: ", 0

header1Str DB 13, 10, "There are ", 0

header2Str DB " primes between 2 and n (n = ", 0

DB "----------------------------------------------", 13, 10, 0

gcdHeadStr DB 13, 10, "Number #1 Number #2 GCD GCD Prime?", 13, 10

DB "-------------------------------------------", 13, 10, 0

gcdYes DB "Yes", 0

gcdNo DB "No", 0

is_prime DB 10001 DUP(0)

.code

;-------------------------------------------------------

main PROC

;

; Main procedure

;-------------------------------------------------------

; initialize is_prime array

push OFFSET is_prime ; pass is_prime address

call FindPrimes ; find all primes <= 10000

add esp, 4 ; pop argument from stack

; display and get option

push OFFSET errorOptStr ; pass error string

add esp, 8 ; pop arguments from stack

cmp eax, 1 ; if first option

je print5000 ; print first 5000 primes

cmp eax, 2 ; if second option

je printN ; print first n primes

cmp eax, 3 ; if third option

je euclid ; do Euclid's algorithm

jmp done ; if fourth option, exit

print5000:

; display primes <= 5000

mov eax, 5000 ; print primes up to n=5000

push eax ; pass n

push OFFSET is_prime ; pass is_prime address

call DisplayResults ; display result

add esp, 20 ; pop arguments from stack

jmp pauseDisp ; wait for a key press

printN:

push OFFSET errorNStr ; pass address of error string

push OFFSET promptStr ; pass address of prompt string

add esp, 8 ; restore stack

push eax ; pass n

push OFFSET is_prime ; pass is_prime address

call DisplayResults ; display result

add esp, 20 ; pop arguments from stack

jmp pauseDisp ; wait for a key press

euclid:

push OFFSET errorNStr ; pass address of error string

push OFFSET promptN1Str ; pass address of prompt string

add esp, 8 ; restore stack

mov ebx, eax

push OFFSET errorNStr ; pass address of error string

push OFFSET promptN2Str ; pass address of prompt string

add esp, 8 ; restore stack

push OFFSET gcdNo ; pass no string

push OFFSET gcdYes ; pass yes string

push eax ; pass n2

push ebx ; pass n1

push OFFSET is_prime ; pass is_prime address

call DisplayGCDResults ; display result

add esp, 24 ; pop arguments from stack

pauseDisp:

call WaitMsg ; wait for a key press

call CrLF

call CrLF ; leave empty line

done:

call WaitMsg ; wait for a key press

exit ; terminate the program

main ENDP

;-------------------------------------------------------

InputN PROC

;

; Accepts an unsigned number from the user and verifies

; that the number is a valid input.

; Returns: EAX has the validated number

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

call WriteString ; display the string

cmp eax, 2 ; if n < 2

jl invalidInput ; it's invalid

cmp eax, 5000 ; if n <= 5000

jle validInput ; it's valid

invalidInput:

call WriteString ; display the string

validInput:

pop ebp ; restore base pointer

ret

InputN ENDP

;-------------------------------------------------------

InitSieve PROC

;

;

; Initializes Sieve array filling it with ones

; Returns: nothing

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

push esi ; save used registers

push ecx

mov ecx, 10001 ; initialize all 10000 entries

iniSieveLoop:

mov BYTE PTR[esi], 1 ; save 1 in array

inc esi ; advance to next number

loop iniSieveLoop ; decrement ecx, repeat loop until ecx is zero

pop ecx ; restore used registers

pop esi

pop ebp ; restore base pointer

ret

InitSieve ENDP

;-------------------------------------------------------

FindPrimes PROC

;

; Calculates the prime numbers between 2 and 10000 using

; the Sieve of Eratosthenes

; Returns: nothing

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

push esi ; save used registers

push ebx

push ecx

push esi ; pass is_prime array

call InitSieve ; initialize is_prime array

add esp, 4 ; restore stack pointer

mov ebx, 2 ; start i in 2

SieveLoop:

cmp BYTE PTR[esi], 1 ; if is_prime[i] is true

jne SieveNext ; if not, go to next

mov ecx, ebx ; load current i as m

add ecx, ebx ; multiply m by 2 = 2*i

SieveMarkLoop:

cmp ecx, 10000 ; if m > 10000

jg SieveNext ; go to next number

mov BYTE PTR[esi + ecx], 0 ; else, set is_prime[m] to false

jmp SieveMarkLoop ; repeat loop

SieveNext:

inc ebx ; increment i

cmp ebx, 10000 ; if i <= 10000

jle SieveLoop ; repeat loop

pop ecx ; restore used registers

pop ebx

pop esi

pop ebp ; restore base pointer

ret

FindPrimes ENDP

;-------------------------------------------------------

CountPrimes PROC

;

; Count the number of primes between 2 and n

; Returns: number of primes between 2 and n

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

push esi ; save registers

push ebx

mov esi, [ebp + 8] ; point to array

mov ebx, 2 ; start i in 2

mov eax, 0 ; count = 0

countLoop:

cmp BYTE PTR[esi + ebx], 1 ; if not prime

jne countNext ; go to next

inc eax ; else, increment count

countNext:

inc ebx ; advance i to next

cmp ebx, [ebp + 12] ; compare i with n

jle countLoop ; if i <= n , repeat

pop ebx ; restore registers

pop esi

pop ebp ; restore base pointer

ret

CountPrimes ENDP

;-------------------------------------------------------

CountDigits PROC

;

; Counts the number of digits in the unsigned number

; Returns: number of digits

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

push ebx ; save registers

push ecx

mov ecx, 0 ; start count in zero

mov ebx, 10 ; for divisions

mov eax, [ebp + 8] ; load number

digLoop: mov edx, 0

div ebx ; divide by 10

inc ecx ; increment digits

cmp eax, 0 ; if number is not zero

jne digLoop ; repeat loop

mov eax, ecx ; return count

pop ecx ; restore registers

pop ebx

pop ebp ; restore base pointer

ret

CountDigits ENDP

;-------------------------------------------------------

DisplayArray PROC

;

; Displays primes between 2 and n

; Returns: nothing

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

push esi ; save registers

push edi

push ebx

push ecx

mov esi, [ebp + 8] ; point to array

mov ebx, 2 ; start i in 2

mov edi, 5 ; count 5 per line

dispLoop:

cmp BYTE PTR[esi + ebx], 1 ; if not prime

jne dispNext ; go to next

mov eax, ebx ; copy current prime

mov eax, 6 ; fill 6 spaces

push eax

push ebx ; pass number

call DisplayDecN ; print number

add esp, 8 ; restore stack

dec edi

jne dispNext ; if not 5, go to next

mov edi, 5 ; else, reload count

dispNext:

inc ebx ; advance i to next

cmp ebx, [ebp + 12] ; compare i with n

jle dispLoop ; if i <= n , repeat

cmp edi, 5 ; if we printed a whole line

je dispEnd ; skip

call CrLF ; else, print new line

dispEnd:

pop ecx ; restore registers

pop ebx

pop edi

pop esi

pop ebp ; restore base pointer

ret

DisplayArray ENDP

;-------------------------------------------------------

DisplayResults PROC

;

; Displays the primes from 2 to n using the given is_prime array

; Returns: nothing

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

push esi ; save registers

push ebx

mov esi, [ebp + 8] ; point to array

mov ebx, [ebp + 12] ; load n

push ebx ; pass n

push esi ; pass array pointer

call CountPrimes ; count the number of primes

add esp, 8 ; restore stack

mov ebx, eax ; save number of primes

call WriteString

mov eax, ebx ; print n

call WriteDec

call WriteString

mov eax, [ebp + 12] ; print n

call WriteDec

call WriteString

mov esi, [ebp + 8] ; point to array

mov ebx, [ebp + 12] ; load n

push ebx ; pass n

push esi ; pass array pointer

call DisplayArray ; display the array

add esp, 8 ; restore stack

pop ebx ; restore registers

pop esi

pop ebp ; restore base pointer

ret

DisplayResults ENDP

;-------------------------------------------------------

GCD PROC

;

; Calculates the GCD of 2 numbers using euclid's algorithm

; it validates the user input.

; Taken from:

; https://en.wikipedia.org/wiki/Euclidean_algorithm

; Returns: GCD result

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

push ebx ; save registers

mov eax, [ebp + 8] ; load a

mov ebx, [ebp + 12] ; load b

cmp DWORD PTR[ebp + 12], 0 ; if b = 0

je gcdReturn ; return a

gcdElse:

mov edx, 0 ; clear edx for division

div ebx ; a/b

push edx ; pass a mod b

push ebx ; pass b

call GCD ; recurse gcd(b, a mod b)

add esp, 8 ; restore stack

gcdReturn:

pop ebx ; restore registers

pop ebp ; restore base pointer

ret

GCD ENDP

;-------------------------------------------------------

DisplayDecN PROC

;

; Displays number filling to n spaces

; Returns: nothing

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

mov eax, [ebp + 8] ; load number

call WriteDec ; print it

mov eax, [ebp + 8] ; load n

push eax ; get digits in number

call CountDigits

add esp, 4 ; restore stack

mov ecx,[ebp + 12] ; load separation

sub ecx, eax ; calculate remainder

mov eax, 32

dispSpcLoop:

call WriteChar ; fill remaining space with chars

loop dispSpcLoop

pop ebp ; restore base pointer

ret

DisplayDecN ENDP

;-------------------------------------------------------

DisplayGCDResults PROC

;

; Displays the gcd of 2 numbers

; Returns: nothing

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

push esi ; save registers

push ebx

mov eax, 12 ; fill 12 spaces

push eax

mov eax, [ebp + 12] ; pass n1

push eax

call DisplayDecN ; print number

add esp, 8 ; restore stack

mov eax, 13 ; fill 13 spaces

push eax

mov eax, [ebp + 16] ; pass n2

push eax

call DisplayDecN ; print number

add esp, 8 ; restore stack

mov eax, [ebp + 12] ; load n1

mov ebx, [ebp + 16] ; load n2

push ebx ; pass n2

push eax ; pass n1

call GCD ; calculate gcd

add esp, 8 ; restore stack

mov ebx, eax

mov eax, 9 ; fill 9 spaces

push eax

push ebx ; pass gcd

call DisplayDecN ; print number

add esp, 8 ; restore stack

mov esi, [ebp + 8] ; point to array

cmp BYTE PTR[esi + ebx], 1 ; if prime

je gcdPrime

mov edx, [ebp + 28] ; load no

jmp displayGCDPrime

gcdPrime:

mov edx, [ebp + 24] ; load yes

displayGCDPrime:

call WriteString

call CrLF

pop ebx ; restore registers

pop esi

pop ebp ; restore base pointer

ret

DisplayGCDResults ENDP

;-------------------------------------------------------

;

; Displays the menu and returns the selected option

; it validates the user input

;-------------------------------------------------------

push ebp ; save base pointer

mov ebp, esp ; base of stack frame

mLoop:

call WriteString ; display the string

cmp eax, 1 ; if < 1

jl invalidOpt ; is invalid

cmp eax, 4 ; if <= 4

jle validOpt ; is valid

invalidOpt:

call WriteString ; display the string

validOpt:

pop ebp ; restore base pointer

ret

END main

Problem 2

INCLUDE Irvine32.inc

Generate7x7Matrix PROTO,

ptrMatrix: PTR DWORD

Display7x7Matrix PROTO,

ptrMatrix: PTR DWORD

isVowel PROTO,

char: BYTE

DisplayWord PROTO,

ptrWord: PTR BYTE,

incVal: DWORD

FindWords PROTO,

ptrMatrix: PTR DWORD

FindRowWords PROTO,

ptrMatrix: PTR DWORD

FindColWords PROTO,

ptrMatrix: PTR DWORD

FindDiagWords PROTO,

ptrMatrix: PTR DWORD

.data

matGenStr DB "Matrix has been generated...", 13, 10, 0

matrix7x7 DWORD 49 DUP(0)

.code

;-------------------------------------------------------

main PROC

;

; Main procedure

;-------------------------------------------------------

call Randomize ; initialize the random generator

; initialize matrix

; print menu and get option

cmp eax, 1 ; if first option

je genMat ; generate matrix

cmp eax, 2 ; if second option

je printMat ; print random matrix

cmp eax, 3 ; if third option

je findSets ; find sets of 7 letters

jmp done ; if fourth option, exit

genMat:

INVOKE Generate7x7Matrix, ADDR matrix7x7 ; generate new matrix

call WriteString ; display string

jmp pauseDisp ; wait for a key press

printMat:

INVOKE Display7x7Matrix, ADDR matrix7x7 ; print the matrix

jmp pauseDisp ; wait for a key press

findSets:

INVOKE FindWords, ADDR matrix7x7 ; find 7 letter words and print them

pauseDisp:

call WaitMsg ; wait for a key press

call CrLF

call CrLF ; leave empty line

done:

call WaitMsg ; wait for a key press

exit ; terminate the program

main ENDP

.data

DB "----------------------------------------------", 13, 10

DB "1. Generate a 7x7 matrix with random letters", 13, 10

DB "2. Print random matrix", 13, 10

DB "3. Find sets of 7 letter words", 13, 10

DB "4. Exit", 13, 10

DB "Option?: ", 0

errorStr DB "Invalid option.", 13, 10, 13, 10, 0

.code

;-------------------------------------------------------

;

; Displays the menu and returns the selected option

; it validates the user input

;-------------------------------------------------------

mLoop:

call WriteString ; display the string

cmp eax, 1 ; if < 1

jl invalidOpt ; is invalid

cmp eax, 4 ; if <= 4

jle validOpt ; is valid

invalidOpt:

call WriteString ; display the string

validOpt:

ret

.data

vowels DB "AEIOU"

consonants DB "BCDFGHJKLMNPQRSTVWXYZ"

.code

;-------------------------------------------------------

Generate7x7Matrix PROC,

ptrMatrix: PTR DWORD

; Generates a 7 x 7 random matrix of letters

; Returns: nothing

;-------------------------------------------------------

push edi ; save registers

push ecx

mov ecx, 49 ; generate 7x7 elements

genLoop:

call Random32 ; generate a random number

and eax, 1 ; if odd,

je genVowel ; generate vowel

genConsonant:

mov eax, 21 ; generate one consonant

call RandomRange ; generate it

mov al, consonants[eax] ; load consonant

mov [edi], al ; save in matrix

jmp genNext

genVowel:

mov eax, 5 ; generate one vowel

call RandomRange ; generate it

mov al, vowels[eax] ; load vowel

mov [edi], al ; save in matrix

genNext:

inc edi ; advance to next position in matrix

loop genLoop

pop ecx ; restore registers

pop edi

ret

Generate7x7Matrix ENDP

.data

titleStr DB "The matrix is:", 13, 10, 13, 10, 0

.code

;-------------------------------------------------------

Display7x7Matrix PROC,

ptrMatrix: PTR DWORD

;

; Displays a matrix of 7x7

; Returns: nothing

;-------------------------------------------------------

push esi ; save registers

push ebx

push ecx

call WriteString ; print title

mov esi, ptrMatrix ; point to matrix

mov ebx, 7 ; print 7 from a row

dispRow:

mov ecx, 7 ; print 7 from a column

dispCol:

mov al, [esi] ; load letter

call WriteChar ; display letter

mov al, 32 ; load ascii space

call WriteChar ; display space

inc esi ; advance to next position

loop dispCol ; decrement cols, repeat if not zero

dec ebx ; decrement rows

jne dispRow ; repeat if not zero

call CrLF ; print new line

pop ecx ; restore registers

pop ebx

pop esi

ret

Display7x7Matrix ENDP

;-------------------------------------------------------

DisplayWord PROC,

ptrWord: PTR BYTE,

incVal: DWORD

;

; Display 7 letter word at a given address incrementing each time by incVal

; Returns: nothing

;-------------------------------------------------------

push esi ; save registers

push ebx

push ecx

mov ecx, 7 ; print 7 letters

mov ebx, incVal ; load increment

dispWordLoop:

mov al, [esi] ; load letter

call WriteChar ; display letter

loop dispWordLoop ; decrement letter count, repeat if not zero

pop ecx ; restore registers

pop ebx

pop esi

ret

DisplayWord ENDP

;-------------------------------------------------------

isVowel PROC,

char: BYTE

;

; Returns 1 if the character is a vowel, 0 if not

; Returns: 1 if the character is a vowel, 0 if not

;-------------------------------------------------------

mov al, char ; load character

cmp al, 'A' ; if vowel

je vowelOk ; return 1

cmp al, 'E' ; if vowel

je vowelOk ; return 1

cmp al, 'I' ; if vowel

je vowelOk ; return 1

cmp al, 'O' ; if vowel

je vowelOk ; return 1

cmp al, 'U' ; if not vowel

jne vowelNot ; go to not

vowelOk:

mov eax, 1 ; return 1

jmp isVowelEnd

vowelNot:

mov eax, 0 ; return 0

isVowelEnd:

ret

isVowel ENDP

.data

foundStr DB "The words from this matrix is/are:", 13, 10, 0

notFoundStr DB "No words were found", 13, 10, 0

.code

;-------------------------------------------------------

FindWords PROC,

ptrMatrix: PTR DWORD

LOCAL nFound:DWORD

;

; Find the 7 letter words with 2 vowels and prints them

; Returns: Nothing

;-------------------------------------------------------

push esi ; save registers

push ebx

push edx

call WriteString ; print title

mov esi, ptrMatrix ; point to start of matrix

INVOKE FindRowWords, esi ; find in rows

mov ebx, eax ; save number of found words

INVOKE FindColWords, esi ; find in columns

INVOKE FindDiagWords, esi ; find in diagonals

cmp ebx, 0 ; if number of found words != 0

jne findEnd ; end

call WriteString ; print the string

findEnd:

pop edx ; restore registers

pop ebx

pop esi

ret

FindWords ENDP

.code

;-------------------------------------------------------

FindRowWords PROC,

ptrMatrix: PTR DWORD

;

; Find the 7 letter words with 2 vowels in the rows and prints them

; Returns: Number of found words

;-------------------------------------------------------

push edi ; save registers

push esi

push ebx

push ecx

push edx

mov edi, 0 ; number of found words = 0

mov esi, ptrMatrix ; point to start of matrix

mov edx, 7 ; repeat for 7 rows

findRLoop:

mov ecx, 0 ; vowels = 0

mov ebx, 0 ; try 7 letters

findRVowels:

INVOKE isVowel, BYTE PTR[esi + ebx] ; check if it's a vowel

add ecx, eax ; increment number of vowels

inc ebx ; increment position in matrix

cmp ebx, 7 ; if below 7

jl findRVowels ; repeat

cmp ecx, 2 ; if 2 vowels were found

jne nextRow ; if not, go to next row

INVOKE DisplayWord, esi, 1 ; display the 7 letter word

call CrLF ; print newline

inc edi ; increment number of found words

nextRow:

dec edx ; decrement rows

jne findRLoop ; repeat if not zero

mov eax, edi ; return found words

pop edx ; restore registers

pop ecx

pop ebx

pop esi

pop edi

ret

FindRowWords ENDP

;-------------------------------------------------------

FindColWords PROC,

ptrMatrix: PTR DWORD

;

; Find the 7 letter words with 2 vowels in the columns and prints them

; Returns: Number of found words

;-------------------------------------------------------

push edi ; save registers

push esi

push ebx

push ecx

push edx

mov edi, 0 ; number of found words = 0

mov esi, ptrMatrix ; point to start of matrix

mov edx, 7 ; repeat for 7 columns

findCLoop:

mov ecx, 0 ; vowels = 0

mov ebx, 0 ; try 7 letters

push edx

mov edx, 7

findCVowels:

INVOKE isVowel, BYTE PTR[esi + ebx] ; check if it's a vowel

add ecx, eax ; increment number of vowels

add ebx, 7 ; increment position in matrix

dec edx ; decrement count to check

jne findCVowels ; repeat if not zero

pop edx

cmp ecx, 2 ; if 2 vowels were found

jne nextCol ; if not, go to next column

INVOKE DisplayWord, esi, 7 ; display the 7 letter word

call CrLF ; print newline

inc edi ; increment number of found words

nextCol:

inc esi ; advance to next column

dec edx ; decrement columns

jne findCLoop ; repeat if not zero

mov eax, edi ; return found words

pop edx ; restore registers

pop ecx

pop ebx

pop esi

pop edi

ret

FindColWords ENDP

;-------------------------------------------------------

FindDiagWords PROC,

ptrMatrix: PTR DWORD

;

; Find the 7 letter words with 2 vowels in the diagonals and prints them if found

; Returns: Number of found words

;-------------------------------------------------------

push edi ; save registers

push esi

push ebx

push ecx

push edx

mov edi, 0 ; number of found words = 0

mov esi, ptrMatrix ; point to start of matrix

mov ebx, 0 ; current pos

mov ecx, 7 ; repeat for 7 letters in diag

mov edx, 0 ; number of vowels

findD1Vowels:

INVOKE isVowel, BYTE PTR[esi + ebx] ; check if it's a vowel

add edx, eax ; increment number of vowels

add ebx, 8 ; increment position in matrix diagonal

loop findD1Vowels ; decrement leters and repeat if not zero

cmp edx, 2 ; if 2 vowels were found

jne nextDiag ; if not, go to next diagonal

INVOKE DisplayWord, esi, 8 ; display the 7 letter diagonal word

call CrLF ; print newline

inc edi ; increment number of found words

nextDiag:

mov ebx, 6 ; current pos

mov ecx, 7 ; repeat for 7 letters in diag

mov edx, 0 ; number of vowels

findD2Vowels:

INVOKE isVowel, BYTE PTR[esi + ebx] ; check if it's a vowel

add edx, eax ; increment number of vowels

add ebx, 6 ; increment position in matrix diagonal

loop findD2Vowels ; decrement leters and repeat if not zero

cmp edx, 2 ; if 2 vowels were found

jne findDiagEnd ; if not, end

mov ebx, esi ; point to start of second diagonal

INVOKE DisplayWord, ebx, 6 ; display the 7 letter diagonal word

call CrLF ; print newline

inc edi ; increment number of found words

findDiagEnd:

mov eax, edi ; return found words

pop edx ; restore registers

pop ecx

pop ebx

pop esi

pop edi

ret

FindDiagWords ENDP

END main