Computer Science/컴퓨터 구조

[컴퓨터 구조] 어셈블리어 계산기

바보1 2023. 6. 7. 17:40
.data
equation : .space 256
equal : .string "="
error_msg : .string "incorrect operation !"
comma : .string ", "
# ------------------------------------------------------------------------------------
# [KNU COMP0411 Computer Architecture] Skeleton code for the 1st project (calculator)
# ------------------------------------------------------------------------------------

.text	
# main
main:
	
	jal x1, test #functionality test, Do not modify!!
	
	#----TODO-------------------------------------------------------------
	#1. read a string from the console
	#2. perform arithmetic operations
	#3. print a string to the console to show the computation result
	#----------------------------------------------------------------------
	
	jal ra, get_equation

	mv t0, a0
	addi t1, zero, 41
	la t2, equation
	
	lb a0, (t2)
	li a7, 11	
	
print:
	ecall
	addi t2, t2, 1
	lb a0, (t2)
	bge a0, t1, print
	
	la a0, equal
	li a7, 4
	ecall
	
	addi t1, zero, 1
	mv a0, t0

	beq x11, t1, signed
	li a7, 36
	beq zero, zero, unsigned

signed:
	li a7, 1
unsigned :
	ecall
	
	addi t1, zero, 3
	bne x11, t1, remainder
	la a0, comma
	li a7, 4
	ecall
	mv x10, x14
	li a7, 1
	ecall
	
remainder:
	li a0, 0
	li a7, 93
	ecall
    ebreak
	
get_equation :
# get equation
	la a0, equation
	li a1, 256
	li a7, 8
	ecall

	addi sp, sp, -4
	sw ra, 0(sp)
	
	addi s10, zero, 1
	slli s10, s10, 3
	addi s10, s10, 2		# create 10
	
	jal ra, get_first_int
	
	jal ra, get_operation_symbol
	lw ra, 0(sp)
	addi sp, sp, 4
	
	jalr zero, 0(ra)

get_first_int :
# get first integer
# result in x12

	mv s8, ra
	
	first_int_loop:

	lb t0, (a0)		# get 1 Byte from Memory
	addi t0, t0, -48		# Sub ASCII code(0 == ASCII 48)
	
	blt t0, zero, get_operation		# if t0 < 0 (a1 is not integer) goto parse_equation
	
	add s0, s0, t0		# s0 = s0 + t0
	mv s9, x11
	addi sp, sp, -8
	sw a0, 4(sp)
	sw s10, 0(sp)
	
	mv x12, s0
	mv x13, s10

	jal ra, Mul

	mv s0, a0
	
	lw s10, 0(sp)
	lw a0, 4(sp)
	addi sp, sp, 8
	mv x11, s9
	
	#Mul s0, s0, s10		# s0 = s0 * s10(10)

	addi a0, a0, 1		# a0 = a0 + 1 -> for get next ASCII
	
	beq zero, zero, first_int_loop		# loop
	
get_operation :
# if a1 is not integer -> operations
# result in x11
	mv t3, zero
	
	addi t0, t0, 48
	addi t1, zero, 43
	beq t0, t1, symbol
	addi t1, zero, 45
	addi t3, t3, 1
	beq t0, t1, symbol
	addi t1, zero, 42
	addi t3, t3, 1
	beq t0, t1, symbol
	addi t1, zero, 47
	addi t3, t3, 1

	symbol:
	mv x11, t3		# x11 is operation
	mv s9, x11
	addi sp, sp, -8
	sw a0, 4(sp)
	sw s10, 0(sp)
	
	mv x12, s0
	mv x13, s10

	jal ra, Div

	mv a7, a0
	
	lw s10, 0(sp)
	lw a0, 4(sp)
	addi sp, sp, 8
	mv x11, s9
	#Div a6, s0, s10
		
	addi a0, a0, 1
	mv s0, zero
	
get_second_int :
# get second integer
# result in x13
	lb t0, (a0)		# get 1 Byte from Memory
	
	addi t0, t0, -48		# Sub ASCII code(0 == ASCII 48)

	blt t0, zero, equation_exit		# if t0 < 0 (a1 is not integer) goto parse_equation
	
	add s0, s0, t0		# s0 = s0 + t0
	mv s9, x11
	addi sp, sp, -8
	sw a0, 4(sp)
	sw s10, 0(sp)
	
	mv x12, s0
	mv x13, s10
	
	jal ra, Mul

	mv s0, a0

	lw s10, 0(sp)
	lw a0, 4(sp)
	addi sp, sp, 8
	mv x11, s9
	#Mul s0, s0, s10		# s0 = s0 * s10(10)

	addi a0, a0, 1		# a0 = a0 + 1 -> for get next ASCII
	
	beq zero, zero, get_second_int		# loop
		
equation_exit :

# get two integer and operation	
	mv s9, x11
	addi sp, sp, -8

	sw a0, 4(sp)
	sw s10, 0(sp)
	
	mv x12, s0
	mv x13, s10

	jal ra, Div

	mv x13, a0
	
	lw s10, 0(sp)
	lw a0, 4(sp)
	
	addi sp, sp, 8
	mv x11, s9
	#Div x13, s0, s10
	mv x12, a7
	
	mv ra, s8
	
	jalr x0, 0(ra)
	



#----------------------------------
#name: calc
#func: performs arithmetic operation
#x11(a1): arithmetic operation (0: addition, 1:  Subtraction, 2:  Multiplication, 3: Division)
#x12(a2): the first operand
#x13(a3): the second operand
#x10(a0): return value
#x14(a4): return value (remainder for Division operation)
#----------------------------------
calc:
	#TODO
	
	get_operation_symbol :
	#addi x11, x11, 42
	mv t0, zero		# 42 = *, 43 = +, 45 = -, 47 = /
	beq x11, t0, add		# if x11 < 44 -> x11 is * or +
	addi t0, t0,1
	beq x11, t0, Sub
	addi t0, t0, 1
	beq x11, t0, Mul
	addi t0, t0, 1
	beq x11, t0, Div
	
	la a0, error_msg
	li a7, 4
	ecall
	
	li a0, 0
	li a7, 93
	ecall
    ebreak
   
add:
	addi x11, zero, 0
	add x10, x12, x13
	
	jalr x0, 0(ra)

Sub:
	addi x11, zero, 1
	not x13, x13
	addi x13, x13, 1
	
	add x10, x12, x13
	not x13, x13
	addi x13, x13, 1
	jalr x0, x1, 0
	
Mul:
	addi sp, sp, -8
	sw x12, 4(sp)
	sw x13, 0(sp)
	
#	mv s5, x12
#	mv s6, x13

	addi x11, zero, 2
	mv x10, zero
	mv t2, zero		# control
	addi t3, x0, 1		# iter count
	addi t4, x0, 33		# max iter
	addi t5, x0, 1		# LSB check
	
	Mul_loop:
		and t2, x13, t5
		bne t2, t5, Mul_else
		add x10, x10, x12
		Mul_else:
			slli x12, x12, 1
			srai x13, x13, 1
			
		addi t3, t3, 1
		ble t3, t4, Mul_loop

	lw x12, 4(sp)
	lw x13, 0(sp)
	addi sp, sp, 8
		
#	mv x12, s5
#	mv x13, s6

	jalr x0, 0(ra)
	
Div:
	mv s5, x12
	mv s6, x13

	addi sp, sp, -4
	sw ra, 0(sp)

	slli x13, x13, 16
	addi t3, zero, 1		# iter count
	addi t4, zero, 18		# max iter
	mv t6, zero		# Quotient
	
	Div_loop :
		jal x1, Sub		# Dividend - Divisor
		
		bge x10, zero, Div_else		# if Remainder is grater or equal than 0, goto else -> Divide is true
		add x10, x10, x13		# recover 
		beq zero, zero, Div_exit
		Div_else:
			ori t6, t6, 1
		Div_exit:
			slli t6, t6, 1
			srli x13, x13, 1
			
		addi x12, x10, 0
		addi t3, t3, 1
		blt t3, t4, Div_loop
		
		mv x14, x10
		srli t6, t6, 1
		mv x10, t6

		mv x12, s5
		mv x13, s6
		
	lw ra, 0(sp)
	addi sp, sp, 4
	addi a1, zero, 3
	jalr x0, 0(ra)

.include "common.asm"