2011-10-18 11:47:32 +02:00

243 lines
8.1 KiB
ArmAsm

#TGDI-Praktikum WS 09/10
#Berechnung der Determinante einer 3x3 bzw. 4x4 Matrix
.data
dim:
.word 3
#.word 4
matrix:
#3x3-Matrix
.word 3, 4, 5, 9, 4, 9, 1, 2, 2
#.word 1, 2, 3, 4, 5, 6, 7, 8, 9
#4x4-Matrix
#.word 3, 4, 5, 9, 4, 9, 1, 2, 2, 1, 3, 5, 7, 9, 3, 5
#.word 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7
det: .asciiz "Die Determinante ist: "
###############################################################################
.text
main:
###################################
###################################
#Hier soll das Programm stehen
#Das Ergebnis muss am Ende in $s6 stehen.
#
# (c) Jana Becher, Ulf Gebhardt 2010
#
# Dieses Programm wurde in Java geschrieben und dann
# händisch übersetzt. Der Java-Algorithmus wird beigelegt.
#
# Dieses Programm kann von nXn Matrizen die Determinante bestimmen,
# Allerdings sollte n <= 2^31 sein und die enthaltenen Zahlen in der Matrix
# sollten folgende bedingungen erfüllen: max(a1*a2*...*an) <= 2^31, wobei a1
# bis an beliebige Zahlen aus der Matrix sind.
#
lw $a0, dim #load dimension
la $a1, matrix #load matrix-startadress
jal calcdet #calc determinante
addi $s6, $v0, 0 #write result to $s6
j ende #ende
#pow(integer,integer) = integer
#
#$a0 = number;
#$a1 = exp;
#$v0 = number^exp
#Comment:
#Java: Math.pow
#keep it withoin 32bit -> using mul
#
pow: addi $t0, $0, 0 #load 0 in $t0
ble $a1, $t0, powrecdone #$a1 <= 0
sw $ra, 0($sp) #sichere $ra
addi $sp, $sp, 4 #stackpointer + 1
addi $a1, $a1, -1 #$a1 -= 1
jal pow #jump in pow
addi $sp, $sp -4 #stackpointer - 1
lw $ra, 0($sp) #sichere $ra zurück
mul $v0,$a0, $v0 #$v0 = number($a0) * pow($v0)
jr $ra #jumpback
powrecdone: addi $v0, $0, 1 #result = 1
jr $ra #jumpback
#calcnewmatrix(integer,integer,address) = address, size
#
#$a0 = pos in Matrix
#$a1 = size of matrix
#$a2 = address of matrix
#$v0 = address of new matrix (on stack)
#$v1 = size of matrix on stack (negative -> add to $sp)
#Comment:
#new matrix lives on Stack, but stackpointer is not increased - do it if you need the object
#
calcnewmatrix: #create new matrix with (size-1)*(size-1) and store size in $v1, address =$sp
addi $t0, $a1, -1 #$t0= size-1
mul $t0, $t0, $t0 #$t0= (size-1)(size-1)
addi $t1, $0, 4 #$t1= bytes in 1 word
mul $t0, $t0, $t1 #$t0= bytesperword*arraysize
addi $v1, $t0, 0 #result $v1 = $t0 = arraysize in bytes on stack
#forA
addi $t0, $0, 1 #$t0=counter for forA = i starts with 1
forA: bge $t0, $a1, cnmjb #exit calcnewmatrix: cnmjb
addi $t1, $0, 0 #$t1=counter for forB = j starts with 0
forB: bge $t1, $a1, forBDone #exit forB -> forA: forBDone
beq $t1, $a0, forBSkip #if(pos == j) skip one cycle
addi $t2, $t1, 0 #tempvar $t2 = j
blt $t2, $a0, forBCalc #if(j($t2) < pos($a0)) start calc
addi $t2, $t2, -1 #else $t2 -= 1
forBCalc: addi $t7, $0, 4 #byteofset of an integer in $t7
#oldmatrixpos
mul $t3, $t0, $a1 #$t3=i*size
add $t3, $t3, $t1 #$t3=i*size+j = posinmatrix
mul $t3, $t3, $t7 #$t3=byteoffset*posinmatrix
add $t3, $t3, $a2 #$t3=matrixadress+byteoffset*posinmatrix
#newmatrixoffset
addi $t4, $t0, -1 #$t4=i-1
addi $t5, $a1, -1 #$t5=size-1
mul $t4, $t4, $t5 #$t4=(i-1)*(size-1)
add $t4, $t4, $t2 #$t4=(i-1)*(size-1) + j(-1 if pos is already skipped) =posinmatrix
mul $t4, $t4, $t7 #$t4=byteoffset*posinmatrix
add $t4, $t4, $sp #$t4=newmatrixadress($sp)+byteoffset*posinmatrix
#load value of old matrix
lw $t5, 0($t3) #$t5=oldmatrix[$t3]
#store word in new matrix
sw $t5, 0($t4) #newmatrix[$t4] = $t5
forBSkip: #skip forB Calculation needed for j==pos
#forB: j++ and forjumpback
addi $t1, $t1, 1 #j++
j forB #forB Jumpback
forBDone: #Dummy to jump out of ForB and continue with ForA
#forA: i++ and forjumpback
addi $t0, $t0,1 #i++
j forA #forA Jumpback
#calcnewmatrixjumpback
cnmjb: addi $v0, $sp, 0 #result=$sp=newmatrixadress #add $v0 to $sp to keep dataobject
jr $ra #jump back
#calcdet(integer,address) = integer
#
#$a0 = size of matrix(dimension)
#$a1 = address of matrix
#$v0 = determinante of matrix
#Comment:
#size is in most cases the dimension of the matrix not the actual size, which is (dim*dim)
calcdet: #Rec-Anchor and Result
addi $t0, $0, 1 #load 1 in $t0
beq $a0, $t0, recanchor #check size
addi $t5, $0, 0 #set result to 0
#for1
addi $t0, $0, 0 #countervar $t0 for for1 -> countervar=i
for1: bge $t0, $a0, cdjb #if i >= size -> cdjb #Rescursion Anchor
#sichere vars
sw $ra, 0($sp) #sichere $ra
sw $t5, 4($sp) #sichere result
sw $t0, 8($sp) #sichere for-counter
sw $a0, 12($sp) #sichere param0
sw $a1, 16($sp) #sichere param1
addi $sp, $sp, 20 #stackpointer - 5 #stack +5
#pow(-1,forcounter) -> t2
addi $a0, $0, -1 #number = -1
add $a1, $0, $t0 #exp = for-counter
jal pow #calc pow
#sichere result
sw $v0, 0($sp) #sichere result nach stack
addi $sp, $sp, 4 #stackpointer - 1 #stack +1
#CalcNewMatrix
lw $t0, -16($sp) #load for-counter=i
addi $a0, $t0, 0 #pos = i
lw $t7, -12($sp) #load $a0=size
addi $a1, $t7, 0 #size
lw $t7, -8($sp) #load $a1=matrixaddress
addi $a2, $t7, 0 #matrix
jal calcnewmatrix #calcnewmatrix -> newmatrix=$v0
addi $t6, $sp, 0 #$t6 = store $sp before matrix and size is added! - makes it simple
add $sp, $sp, $v1 #Matrix is on Stack now, keep it by increasing stackpointer #stack +$v1
sw $v1, 0($sp) #Store size of Matrix@Stack to delete it afterwards
sw $t6, 4($sp) #Store old $sp
addi $sp, $sp, 8 #1word on Stack reserved #stack +2
#CalcDet - Recursion ($t3)
lw $t7, -12($t6) #load $a0=size #Oldstackpointer $t6
addi $a0, $t7, -1 #size -1
addi $a1, $v0, 0 #matrixaddress from calcnewmatrix
jal calcdet #calcdet of new matrix
addi $t3, $v0, 0 #Save result from calcdet in $t3
#restore vars/cleanup
addi $sp, $sp, -4 #1word - stored sp #stack -1
lw $t7, 0($sp) #load old sp
addi $sp, $t7, 0 #free memory used for matrix and matrixsize #stack -$v1 -1
addi $sp, $sp, -24 #stackpointer - 6 #stack -6
lw $ra, 0($sp) #sichere $ra
lw $t5, 4($sp) #sichere result
lw $t0, 8($sp) #sichere for-counter
lw $a0, 12($sp) #sichere param0
lw $a1, 16($sp) #sichere param1
lw $t1, 20($sp) #result aus pow
#Get Matrix@pos i
addi $t7, $0, 4 #bytesize of word -> $t7
mul $t7, $t0, $t7 #matrixposcalc: i*byteoffset
add $t7, $t7, $a1 #get actual matrixpos
lw $t2, 0($t7) #loadmatrix content @ pos forcounter
#calc result #tempvar = $t7
mul $t7, $t1, $t2 #pow*matrix@posi
mul $t7, $t7, $t3 #pow*matrixpos@posi*submatrix
add $t5, $t5, $t7 #add to result
#for: i++ and forjumpback
addi $t0,$t0, 1 # +1 to counter
j for1 #jump to for again
#cdjb = calcdetjumpback
cdjb: addi $v0, $t5, 0 #set result
jr $ra #jump back
recanchor: lw $v0, 0($a1) #return matrix[0]
jr $ra #jump back
###################################
###################################
ende:
#Ausgabe
la $a0 det
li $v0 4
syscall
move $a0, $s6
li $v0, 1
syscall
###################################
#Ende
li $v0, 10
syscall