TITLE Week 6 Programming Assignment						(main.asm)

; Program Description:  This program finds the least common multiple of 2 inputs
; Author:		        		Bob Markham
; Instructor:           Panos Mastrogiannis
; Creation Date:        18 November 2012
; Revisions:            none

INCLUDE Irvine32.inc
.data

; Messages to display at appropriate time
msgIntro    BYTE "--Bob Markham-- Week 6 LCM",0dh,0ah,0
msgInstruct BYTE "I need 2 integers and I will tell you what the least common multiple is.",0dh,0ah,0
msg1stInt   BYTE "What is the first integer? ",0
msg2ndInt   BYTE "What is the second integer? ",0
msgLCM      BYTE "The least common multiple is: ",0
msgPrime    BYTE " is a prime number.",0dh,0ah,0
msgNotPrime BYTE " can be divided by ",0

; Data to hold the 2 inputs and will be used twice
input1 WORD ?
input2 WORD ?

; Data to hold the LCM
LCM    WORD ?

; Data used in finding prime
tstLo  WORD ?
tstHi  WORD ?
tst    WORD ?

; Data to use Results 
prime1 WORD ?
prime2 WORD ?

.code
main PROC
	CALL Clrscr  

	MOV	 edx, OFFSET msgIntro
	CALL WriteString

; Problem 1 - Accept two integers from the user
  CALL  GetInputs  ; results are returned in AX and BX
  MOV   input1, AX
  MOV   input2, BX

; Problem 2 - Calculate the least common multiple
  CALL CalculateLCM
  MOV  LCM, AX
  MOV  EDX, OFFSET msgLCM
  CALL WriteString
  CALL WriteInt
  CALL crlf

; Problem 3 - Using the same two inputs, determine if they are prime and display the results
  MOV  prime1, 0
  MOV  prime2, 0         ; Will stay as 0 if not prime

  MOV  AX, input1        ; Check if input1 is prime
  CALL IsPrime
  MOV  prime1, AX
  CMP  AX, input1
  JE   inputPrime1       ; input1 is prime

  MOV  AX, input1        ; Display input1 + " can be divided by " + prime1
  CALL WriteInt
  MOV  EDX, OFFSET msgNotPrime
  CALL WriteString
  MOV  AX, prime1
  CALL WriteInt
  CALL crlf
  JMP  checkPrime2

inputPrime1:             ; Show that input1 is prime
  CALL WriteInt
  MOV  EDX, OFFSET msgPrime
  CALL WriteString

checkPrime2:
  MOV  AX, input2        ; Check if input1 is prime
  CALL IsPrime
  MOV  prime2, AX
  CMP  AX, input2
  JE   inputPrime2       ; input1 is prime

  MOV  AX, input2        ; Display input2 + " can be divided by " + prime2
  CALL WriteInt
  MOV  EDX, OFFSET msgNotPrime
  CALL WriteString
  MOV  AX, prime2
  CALL WriteInt
  CALL crlf
  JMP  finishWeek6

inputPrime2:             ; Show that input2 is prime
  CALL WriteInt
  MOV  EDX, OFFSET msgPrime
  CALL WriteString

finishWeek6:
  CALL WaitMsg
  exit
main ENDP

; ===============================================
; GetInputs  (Problem 1)
;   Inputs:  none
;   Returns: AX = First  input
;            BX = Second input
; ===============================================
GetInputs PROC
; Give instructions for what to do
  MOV    EDX, OFFSET msgInstruct
  CALL   WriteString

; Ask for first integer
  MOV    EDX, OFFSET msg1stInt
  CALL   WriteString

; Now retrieve it
  CALL   ReadInt

; I'm using AX to return the first input and it's the result of ReadInt
; So I'll PUSH it out of the way for now
  PUSH   AX

; Ask for the second integer
  MOV    EDX, OFFSET msg2ndInt
  CALL   WriteString

; Now retrieve it
  CALL   ReadInt

; I'm using BX to return the second integer
  MOVzx  EBX, AX

; Put the first integer which I PUSHed out of the way back into AX
  POP    AX

;  CALL   DumpRegs       ; Used to test where things were going
  RET
GetInputs ENDP

; ===============================================
; CalculateLCM  (Problem 2)
;   Inputs:  AX  = input1  BX = input2
;   Returns: AX  = LCM of input1 and input2
; ===============================================
CalculateLCM PROC
CalculateLoop:
  CMP  AX, BX            ; Compare the 2 values
  JE   Found             ; if (test1 == test2) { Found }
  JL   Less              ; if (test1 <  test2) { Less  }

  ADD  BX, input2        ; if (test1 >  test2) { test2+=input2 } // Making sure it's a multiple
  JMP  CalculateLoop

Less:
  ADD  AX, input1        ; if (test1 <  test2) { test1+=input1 } // Making sure it's a multiple
  JMP  CalculateLoop

Found:
;  CALL   DumpRegs       ; Used to test where things were going
  RET
CalculateLCM ENDP

; ===============================================
; IsPrime  (Problem 3)
;   Inputs:  AX
;   Returns: AX unchanged if prime
;            AX = first divisible number
;            AX = 0 if less than 2
;   Changes: AX, BX, CX, DX
; ===============================================
IsPrime PROC
; Setup the testing variables
  MOV  tstLo, 2
  MOV  tstHi, AX
  MOV  tst,   AX
; Check for AX < 2
  CMP  AX, 2
  JL   primeLess2
primeLoop:
; Setup the Divide       AX = DX:AX / CX    DX = DX:AX % CX :: AX = tst / tstLo  DX = tstHi % tstLo
  MOV  DX, 0
  MOV  AX, tst
  MOV  CX, tstLo
  DIV  CX

  CMP  DX, 0             ; Test for even divide
  JE   divFound          ; If it's even, then a divisor was found so lets end the madness and return such
  
; Setup for the next divide.
  MOV  tstHi, AX         ; Setup for the next divide
  INC  tstLo             ; We'll test all numbers, not just the prime ones
  CMP  tstLo, AX         ; No need to test beyond the sqrt of the testing number
  JL   primeLoop
divNotFound:
  MOV  AX, tst           ; Return Original Number, divisors not found
  JMP  primeDone
divFound:
  MOV  AX, tstLo         ; Divisor found and so we return it
  JMP  primeDone
primeLess2:
  MOV  AX, 0
primeDone:
  RET
IsPrime ENDP

END main

