243 lines
8.1 KiB
ArmAsm
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
|