Musterlo ̈sung
U ̈bung3 RAWiSe18/19
Fu ̈r die folgenden Aufgaben gibt es sehr viele Lo ̈sungsmo ̈glichkeiten. Die folgenden Pro- gramme stellen jeweils nur eine mo ̈gliche Lo ̈sung dar, die nicht notwendigerweise optimal bezu ̈glich Laufzeit und/oder Anzahl der Instruktionen sein muss.
Hinweis: Bei den Aufgaben 3 und 4 werden Prozeduren verwendet. Da diese Prozeduren keine weitere Prozeduren aufrufen und keine sicheren Register verwenden, mu ̈ssen sie auch keine Register auf den Stack sichern und wieder herstellen. Zu beachten ist die Lo ̈sung der Aufgabe 4, die in der Prozedur i2t den Stack benutzt, um eine Stack-Datenstruktur zu implementieren.
Aufgabe 1 (Ein erstes Assemblerprogramm)
Gegeben ist folgendes Assemblerprogramm:
.data # start data section
prompt: .asciiz “\nEnter number: \n”
answer: .asciiz “Result = ”
main:
.text
addi $v0, $zero, 4
la $a0, prompt
syscall
addi $v0, $zero, 5
syscall
addi $t0, $v0, 1
mul $t1, $t0, $v0
srl $t1, $t1, 1
addi $v0, $zero, 4
la $a0, answer
syscall
add $a0, $t1, $zero
addi $v0, $zero, 1
syscall
addi $v0, $zero, 10
syscall
# start text section
# load system call for print_string
# print prompt
# load system call code for read_int
# read a number n, value in $v0
# compute ?
# result in $a0
# load system call for print_string
# print answer message
# move result to $a0
# load system call code for print_int
# print result
# load system call code for exit
# exit the program
(1) Machen Sie sich mit dem Simulator MARS vertraut. Laden Sie dazu den source code des Assemblerprogramms Aufgabe1.s von der PANDA-Seite. Starten Sie MARS, laden sie das Assemblerprogramm und testen Sie das Programm. Probieren Sie verschiedene Funktionen des Simulators aus (zB. Go, Single-Step).
Seite 1 / 8
Musterlo ̈sung
U ̈bung3 RAWiSe18/19
(2) Was berechnet dieses Programm?
(3) Erweitern Sie das Programm um die U ̈berpru ̈fung, ob die eingegebene Zahl negativ
ist. Falls ja, geben Sie eine Fehlermeldung aus und beenden Sie das Programm.
(4) Erweitern Sie das Programm so, dass in einer Schleife nach einer Eingabe verlangt und das Resultat berechnet wird. Bei Eingabe einer negativen Zahl geben Sie eine Fehlermeldung aus und fragen weiter nach einer Eingabe. Bei Eingabe von 0 beenden Sie das Programm.
Musterlo ̈sung
(2) Dieses Programm berechnet fu ̈r eine Eingabe n den Wert n i = n·(n+1) .
(3)
2
# start text section
# load system call for print_string
# print prompt
# load system call code for read_int
# read a number n, value in $v0
#jump,if$v0>=0
# load system call for print_string
# print error message
# terminate
# compute
# result in $a0
# load system call for print_string
# print answer message
# move result to $a0
# load system call code for print_int
# print result
# load system call code for exit
# exit the program
i=0
.data # start data section
.asciiz “\nEnter number: ”
.asciiz “Result = ”
prompt:
answer:
negativ: .asciiz “Please enter positive number.\n”
main:
.text
addi $v0,
la $a0,
syscall
addi $v0,
syscall
bgez $v0,
addi $v0,
la $a0,
syscall
j main2
$zero, 4
prompt
$zero, 5
main1
$zero, 4
negativ
$v0, 1
$t0, $v0
$t1, 1
$zero, 4
answer
$t1, $zero
$zero, 1
$zero, 10
main1: addi $t0,
mul $t1,
srl $t1,
addi $v0,
la $a0,
syscall
add $a0,
addi $v0,
syscall
main2: addi $v0,
syscall
Seite 2 / 8
Musterlo ̈sung
U ̈bung3 RAWiSe18/19
(4) .data # start data section prompt: .asciiz “\nEnter number: ”
answer: .asciiz “Result = ”
negativ: .asciiz “Please enter positive number.\n”
.text
main: addi $v0, $zero, 4
# start text section
# load system call for print_string
# print prompt
# load system call code for read_int
# read a number n, value in $v0
#jump,if$v0>0
# terminate on $v0 ==0
# load system call for print_string
# print error message
# repeat
# compute
# result in $a0
# load system call for print_string
# print answer message
# move result to $a0
# load system call code for print_int
# print result
# load system call code for exit
# exit the program
la $a0,
syscall
addi $v0,
syscall
bgtz $v0,
beqz $v0,
addi $v0,
la $a0,
syscall
j main
main1: addi $t0,
mul $t1,
srl $t1,
addi $v0,
la $a0,
syscall
add $a0,
addi $v0,
syscall
j main
main2: addi $v0,
syscall
prompt
$zero, 5
main1
main2
$zero, 4
negativ
$v0, 1
$t0, $v0
$t1, 1
$zero, 4
answer
$t1, $zero
$zero, 1
$zero, 10
Seite 3 / 8
Musterlo ̈sung
U ̈bung3 RAWiSe18/19
Aufgabe 2 (Fibonacci-Folge)
Schreiben Sie ein Assemblerprogramm, das die ersten n Fibonacci-Zahlen ausgibt. Die Fibonacci-Zahlen sind durch folgende rekursive Bildungsvorschrift bestimmt:
F(n)=F(n−1)+F(n−2); F(0)=0;F(1)=1 (1) Hinweis 1: Implementieren Sie keine rekursive, sondern eine iterative Lo ̈sung.
Hinweis 2: Verwenden Sie das Programmgeru ̈st aus Aufgabe 1.
Musterlo ̈sung
.data
.asciiz “\nGeben Sie eine positive Zahl ein: ”
in:
f_0_f_1:
endl:
.asciiz “0\n1\n”
.asciiz “\n”
main:
.text
li $v0, 4
la $a0, in
syscall
li $v0, 5
syscall
move $s3, $v0
li $v0, 4
la $a0, f_0_f_1
syscall
li $s0, 0
li $s1, 1
add $s2, $s0, $s1
move $s0, $s1
move $s1, $s2
move $a0, $s1
li $v0, 1
syscall
li $v0, 4
la $a0, endl
syscall
addi $s3, $s3, -1
slti $t0, $s3, 3
# select print_string for syscall
# string to print
# print
# select read_int for syscall
# read int, value in $v0
# s3<-v0
# select print_string for syscall
# first and second fibonacci numbers are known
# print them
# s0<-0
# s1<-1
# s2<-s0+s1
# s0<-s1
# s1<-s2
# print fibonacci number
# load system call code for print_int
# print result
# print newline
# s3<-s3-1
# dont print the first two fibonacci number
# while(s3-2>0) <=> while(not(s3-2<=0))
# <=> while(not(s3-2<1)) <=> while(not(s3<3))
L2:
beq $t0,
j main
$zero, L2
Seite 4 / 8
Musterlo ̈sung
U ̈bung3 RAWiSe18/19
Aufgabe 3 (Primzahlentest)
(1) (2)
(1)
Schreiben Sie ein Assemblerprogramm, das fu ̈r eine positive, ganze Zahl n feststellt, ob sie eine Primzahl ist.
Wandeln Sie den Primzahlentest in eine Prozedur test prime(n) um, die 1 zuru ̈ck- gibt, falls n eine Primzahl ist und 0 sonst. Schreiben Sie basierend auf dieser Pro- zedur ein Assemblerprogramm, das die ersten m Primzahlen findet.
Musterlo ̈sung
.data
.asciiz "\nGeben Sie eine positive Zahl ein: "
.asciiz "ist prim"
in:
prim:
nichtprim: .asciiz "nicht prim"
main:
.text
li $v0, 4
la $a0, in
syscall
li $v0, 5
syscall
li $t0, 2
blt $v0, $t0,
li $t0, 3
ble $v0, $t0,
andi $t1, $v0,
# select print_string for syscall
# string to print
# print
# select read_int for syscall
# read int, value in $v0
# t0<-2
# dont handle numbers < 2
# v0==2 or v0==3 ?
# then prime found
#t1<-v0modt0==0? # if so, exit
# t1<-t0^2
# t0<-t0+2 #ift1
# s0<-s0+1
main1: bge $s2,
addi $s0,
move $a0,
jal test_prime
beq $v0, $zero, main1 # not a prime, try with next
addi $s2, $s2,
li $v0, 1
syscall
li $v0, 4
la $a0, endl
syscall
j main1
test_prime:
li $v0, 0
1
# increment the counter for founded primes
# select print_int for syscall
# select print_string for syscall
# string to print
# print
# assume a0 is not a prime
# dont handle numbers < 2
# a0==2 or a0==3 ?
# then prime found
# is a0 even?
li $t0, 2
blt $a0, $t0,
li $t0, 3
ble $a0, $t0,
andi $t1, $a0,
FAIL
PRIME
LOOP:
PRIME: li
FAIL: jr $ra
rem $t1, $a0, $t0
beq $t1, $zero, FAIL
#t1<-a0modt0==0? # if so, exit
# t1<-t0^2
# t0<-t0+2
# if t1