.model small
.stack 64
.data
error_alpha db "Invalid input. Expression contains letter/s. ",13,10,"$"
error_range db "Invalid input. Operand/s may be out of range. ",13,10,"$"
error_overflow db "An overflow has occurred. ",13,10,"$"
error_invalidinput db "Invalid Input. ",13,10, "$"
redo db "Please enter a valid one.",13,10,"$"
newline db 13,10,"$"
inputlen dw 2
op1len dw 1
op2len dw 2
prompt db "Enter an expression: ","$"
inputLabel label byte
inputmaxLen db 50
inputcurLen db ?
inputData db 50 dup (?)
str_operand1 db 10 dup (?)
str_operand2 db 10 dup (?)
str_operator db 2 dup (?)
operand_sign1 db 2 dup (?)
operand_sign2 db 2 dup (?)
sign_counter db 0h
multbyTen db 10
op_temp1 dw ?
op_temp2 dw ?
op_fin1 dw ?
op_fin2 dw ?
tempAnswer dw ?
finalAnswer dw ?
divAnswer dw 0h
remainder db ?
finalRem dw ?
outputDecimal db "DECIMAL: $"
outputBinary db "BINARY: $"
outputOctal db "OCTAL: $"
outputHex db "HEXADECIMAL: $"
rev_ascii_decimal db ?
rev_ascii_binary db ?
rev_ascii_octal db ?
rev_ascii_hexadecimal db ?
outputSign db ?
dec_len dw 0h
bin_len dw 0h
oct_len dw 0h
hex_len dw 0h
find_operand1 dw 0h
find_operand2 dw 0h
temp dw 0h
sum dw 0h
multiplier dw 0h
product dw 0h
.code
;asks the user for input
prompt_for_input proc
mov dx, offset prompt
mov ah, 9h
int 21h
mov dx, offset inputLabel
mov ah, 0ah
int 21h
mov bx, 0h
mov bl, inputcurLen
mov inputData[bx], "$"
mov bx, 0
mov bl, inputcurLen
mov inputlen, bx
ret
prompt_for_input endp
; gets the operands and the operator from the one line of input
get_operators_and_operands proc
mov ax, 0
mov bx, 0
mov dx, 0
mov cx, 0
mov si, 0
mov bp, 0
mov op1len, 0h
mov op2len, 0h
pre_conv1:
mov al, inputData[bx]
call check_if_digit
jz pre_start_operand1
check_sign1:
cmp al, "-"
je negative_op1
cmp al, "+"
je positive_op1
call invalid_input
negative_op1:
mov operand_sign1[0], "-"
mov operand_sign1[1], "$"
inc bx
jmp start_operand1
positive_op1:
mov operand_sign1[0], "+"
mov operand_sign1[1], "$"
inc bx
jmp start_operand1
pre_start_operand1:
mov operand_sign1[0], "+"
mov operand_sign1[1], "$"
jmp start_operand1
start_operand1:
mov al, inputData[bx]
cmp al, " "
je end_operand1
push bx
mov bx, 0
mov bx, cx
mov str_operand1[bx],al
pop bx
inc op1len
inc cx
inc bx
jmp start_operand1
end_operand1:
push bx
mov bx, 0
mov bx, cx
mov str_operand1[bx], "$"
pop bx
jmp get_operator
get_operator:
inc bx
mov al, inputData[bx]
mov str_operator[0], al
mov str_operator[1], "$"
inc bx
inc bx
mov ax, 0
mov cx, 0
jmp pre_conv2
pre_conv2:
mov al, inputData[bx]
call check_if_digit
jz pre_start_operand2
jnz check_sign2
check_sign2:
cmp al, "-"
je negative_op2
cmp al, "+"
je positive_op2
call invalid_input
pre_start_operand2:
mov operand_sign2[0], "+"
mov operand_sign2[1], "$"
jmp start_operand2
start_operand2:
mov al, inputData[bx]
cmp al, "$"
je end_operand2
push bx
mov bx, 0
mov bx, cx
mov str_operand2[bx],al
pop bx
inc op2len
inc cx
inc bx
jmp start_operand2
end_operand2:
push bx
mov bx, 0
mov bx, cx
mov str_operand2[bx], "$"
pop bx
ret
negative_op2:
mov operand_sign2[0], "-"
mov operand_sign2[1], "$"
inc bx
jmp start_operand2
positive_op2:
mov operand_sign2[0], "+"
mov operand_sign2[1], "$"
inc bx
jmp start_operand2
get_operators_and_operands endp
;checks what operator was used and performs the indicated operation
check_operator proc
mov bx, 0
mov bl, str_operator[0]
cmp bl, "+"
jne check_sub
call add_nos
ret
check_sub:
cmp bl, "-"
jne check_mul
call sub_nos
ret
check_mul:
cmp bl, "*"
jne check_div
call mul_nos
ret
check_div:
cmp bl, "/"
jne call_invalid_input
call div_nos
ret
call_invalid_input:
call invalid_input
check_operator endp
;jumps to the procedure input_out_of_range
to_input_out_of_range proc
jmp input_out_of_range
to_input_out_of_range endp
;converts the operands to decimal to be used in the arithmetic operations
convert_operands_to_decimal proc
mov bx, 0h
find_eostring1:
mov ax, 0
mov al, str_operand1[bx]
cmp al, "$"
je two
sub al, 30h
mov str_operand1[bx], al
inc bx
jmp find_eostring1
two:
mov bx, 0h
find_eostring2:
mov ax, 0
mov al, str_operand2[bx]
cmp al, "$"
je exit_cotd
sub al, 30h
mov str_operand2[bx], al
inc bx
jmp find_eostring2
exit_cotd:
cmp op1len, 6
jg to_input_out_of_range2
cmp op2len, 6
jg to_input_out_of_range2
ret
convert_operands_to_decimal endp
;performs addition if the operator is the '+' sign
add_nos proc
mov cl, operand_sign1[0]
mov bl, operand_sign2[0]
cmp cl, bl
jne subit
mov al, str_operand1
mov dl, str_operand2
add al, dl
add al, 30h
mov dl, al
mov ah, 9h
int 21h
ret
subit:
mov bx, op1len
mov cx, op2len
cmp bx, cx
jl subop2
subop1:
mov cl, operand_sign1[0]
mov outputSign[0],cl
mov outputSign[1],"$"
sub al, dl
ret
subop2:
mov dl, operand_sign2[0]
mov outputSign[0],dl
mov outputSign[1],"$"
sub dl, al
ret
add_nos endp
;performs subtraction if the operator is the '-' sign
sub_nos proc
ret
sub_nos endp
;jumps to the procedure input_out_of_range
to_input_out_of_range2 proc
jmp input_out_of_range
to_input_out_of_range2 endp
;performs multiplication if the operator is the '*' sign
mul_nos proc
mov al, str_operand1
mov dl, str_operand2
mul dl
mov finalAnswer,ax
mov cl, operand_sign1[0]
mov bl, operand_sign2[0]
cmp cl, bl
je outputSign_is_pos
mov outputSign[0],"-"
jmp endsignmul
outputSign_is_pos:
mov outputSign[0]," "
endsignmul:
mov outputSign[1],"$"
ret
mul_nos endp
;performs division if the operator is the '/' sign
div_nos proc
mov dx, 0
mov al, str_operand1
mov bl, str_operand2
div bl
mov remainder, ah
mov ah, 0
mov divAnswer, ax
mov cl, operand_sign1[0]
mov bl, operand_sign2[0]
cmp cl, bl
je outputSign_is_pos2
mov outputSign[0],"-"
jmp endsigndiv
outputSign_is_pos2:
mov outputSign[0]," "
endsigndiv:
mov outputSign[1],"$"
ret
div_nos endp
;prints the error message indicating that an operand's value is greater that 65536
input_out_of_range proc
call print_new_line
mov dx, offset error_range
mov ah, 09h
int 21h
call print_new_line
mov dx, offset redo
mov ah, 09h
int 21h
call print_new_line
jmp start_program
input_out_of_range endp
;prints the error message indicating that an overflow has occured
overflow proc
call print_new_line
mov dx, offset error_overflow
mov ah, 09h
int 21h
call print_new_line
mov dx, offset redo
mov ah, 09h
int 21h
call print_new_line
jmp start_program
overflow endp
;checks if there is a letter in the input
isalpha proc
mov cx , inputlen
mov si, 0
start:
mov ax, 0
mov al, inputData[si]
call check_if_alpha
jz input_is_alpha
inc si
loop start
ret
isalpha endp
;prints the error message indicating that there are letter/s or symbol/s in the input
input_is_alpha proc
call print_new_line
mov dx, offset error_alpha
mov ah, 09h
int 21h
call print_new_line
mov dx, offset redo
mov ah, 09h
int 21h
call print_new_line
call start_program
input_is_alpha endp
;prints the error message indicating that the syntax of the input is wrong
invalid_input proc
call print_new_line
mov dx, offset error_invalidinput
mov ah, 09h
int 21h
call print_new_line
mov dx, offset redo
mov ah, 09h
int 21h
call print_new_line
call start_program
;ret
invalid_input endp
;prints the decimal equivalent of the answer
print_decimal_output proc
mov dx, offset outputDecimal
mov ah, 9h
int 21h
mov ax, finalAnswer
mov bl, 0ah
div bl
mov ah, 0
mov rev_ascii_decimal,al
mov bx, 0
mov cx, dec_len
convertdecloop:
mov al, rev_ascii_decimal[bx]
add al, 30h
mov rev_ascii_decimal, al
inc bx
loop convertdecloop
mov ax, 0
mov bx, 0
mov cx, dec_len
;mov bx, dec_len
decimalloop:
mov ah, 02h
mov dl, rev_ascii_decimal[bx]
int 21h
inc bx
loop decimalloop
call print_new_line
call print_binary_output
print_decimal_output endp
;prints the binary equivalent of the number
print_binary_output proc
mov dx, offset outputBinary
mov ah, 9h
int 21h
mov dx, offset outputSign
mov ah, 02h
int 21h
mov bx, 0
mov ax, finalAnswer
convertbinloop:
mov cl, 2
div cl
cmp ah, 0
je zerobin
mov rev_ascii_binary[bx],"1"
zerobin:
mov rev_ascii_binary[bx],"0"
nextbin:
inc bx
cmp bx, bin_len
je endbinary
jmp convertbinloop
endbinary:
;mov bx, bin_len
;mov bx, 4
mov rev_ascii_binary[bx],"$"
;mov ax, 0
mov bx, 4
;mov cx, bin_len
mov cx, 4
;mov bx, bin_len
binaryloop:
mov ah, 02h
mov dl, rev_ascii_binary[bx]
int 21h
dec bx
loop binaryloop
call print_new_line
ret
;call print_octal_output
print_binary_output endp
;prints the octal equivalent of the answer
print_octal_output proc
mov dx, offset outputOctal
mov ah, 9h
int 21h
mov ax, finalAnswer
convertoctloop:
mov cl, 16
div cl
cmp ah, 0
je zerooct
mov rev_ascii_octal[bx], "1"
jmp nextoct
zerooct:
mov rev_ascii_octal[bx], "0"
nextoct:
inc bx
cmp bx, oct_len
je endoct
jmp convertoctloop
endoct:
mov rev_ascii_octal[bx],"$"
mov ax, 0
mov bx, 0
mov cx, oct_len
mov bx, oct_len
octalloop:
mov ah, 02h
mov dl, rev_ascii_octal[bx]
int 21h
inc bx
loop octalloop
call print_new_line
call print_hex_output
print_octal_output endp
;prints the hexidecimal equivalent of the number
print_hex_output proc
mov dx, offset outputHex
mov ah, 9h
int 21h
mov ax, finalAnswer
mov bx, 0
converthexloop:
mov cl, 16
div cl
cmp ah, 0
je zerohex
mov rev_ascii_hexadecimal[bx], "1"
jmp nexthex
zerohex:
mov rev_ascii_hexadecimal[bx], "0"
nexthex:
inc bx
cmp bx, hex_len
je endhex
jmp converthexloop
endhex:
mov rev_ascii_hexadecimal[bx],"$"
mov ax, 0
mov cx, hex_len
mov bx, hex_len
hexadecimalloop:
mov ah, 02h
mov dl, rev_ascii_hexadecimal[bx]
int 21h
inc bx
loop hexadecimalloop
call end_program
print_hex_output endp
;prints a new line
print_new_line proc
mov dx, offset newline
mov ah, 09h
int 21h
ret
print_new_line endp
check_if_alpha proc
push ax
and al, 11011111b
cmp al, 'A'
jb B1
cmp al, 'Z'
ja B1
test ax, 0
B1: pop ax
ret
check_if_alpha endp
check_if_digit proc
cmp al, '0'
jb A1
cmp al, '9'
ja A1
test ax, 0
A1: ret
check_if_digit endp
;terminates the program
end_program proc
mov ah, 4ch
int 21h
end_program endp
main proc
mov ax, @data
mov ds, ax
call setcolors
start_program:
call prompt_for_input
call print_new_line
mov dx, offset inputData
mov ah, 09h
int 21h
call isalpha
call print_new_line
call get_operators_and_operands
call convert_operands_to_decimal
call check_operator
call print_decimal_output
call end_program
main endp
end main