PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Iterativ Fibonacci-Zahlen in Assembler



Unregistriert
10.06.2015, 19:34
Hallo,

ich habe folgendes Problem und zwar sollen wir die Fibonacci-Zahlen in Assembler programmieren.
Da wir kaum Unterlagen oder sonstige Hilfe bereitgestellt bekommen haben, wurden wir quasi ins kalte Wasser geschmissen.
Genau deshalb schreibe ich nun diesen Eintrag, in der Hoffnung das mir jemand helfen kann.

Aufgabe:
In dieser Aufgabe soll ein iterativer Algorithmus zur Berechnung der Fibonacci-Zahlen auf einem ATMega16 implementiert werden. Fibonacci-Zahlen bilden eine unendliche Folge, für die gilt:
F(0) = 0, F(1) = 1, F(k) = F(k-1) + F(k-2) Für alle k Elemente aus den natürlichen Zahlen und k>=2
Schreiben Sie ein Assemblerprogramm, das iterativ die Fibonacci-Zahl F(k) entsprechend der gegebenen Bildungsvorschrift berechnet.

(a) Anlegen eines Projektes und Initialisierungen
Beginnen Sie mit einem neuen Atmel Studio Projekt. Wählen Sie als Programmiersprache Assembler, als Mikrocontroller einen ATmega16 und als Debug-Tool den Simulator aus. Folgende Registerbezeichnungen sind gegeben Tmp=R16, K=R19 und Result=R20. Definieren Sie diese und alle weiteren verwendeten Registerbezeichnungen.
(b) Implementierung des Hauptprogramms
Implementieren Sie das Hauptprogramm main. Belegen Sie hier das Register K als Eingabe für die Berechnung von F(k) mit einem konstanten Wert und führen Sie anschließend die Berechnung der Fibonacci-Zahlen durch. Das Ergebnis F(k) soll sich nach der Berechnung im Register Result befinden und der ATmega in einer Endlossschleife verharren.

Folgenden Code habe ich schon:
;-----------------------------------------------------------------------------
; Einbinden der controllerspezifischen Definitionsdatei
;-----------------------------------------------------------------------------
.NOLIST ; List-Output ausschalten
.INCLUDE "m16def.inc" ; Deklarationen für Mega16 einfügen
.LIST ; List-Output wieder einschalten
;------------------------------------------------------------------------------
; Programmspeicher (FLASH) Programmstart nach RESET ab Adr. 0x0000
;------------------------------------------------------------------------------
.CSEG ; Programmbereich im Flash
.ORG 0x0000 ; Programm beginnt an der FLASH-Adresse 0x0000
RESET: RJMP INIT ; Springe nach INIT (Ueberspringe ISR Vektoren)
;------------------------------------------------------------------------------
; Initialisierungen und eigene Definitionen
;------------------------------------------------------------------------------
.ORG INT_VECTORS_SIZE ; Platz fuer ISR Vektoren lassen
INIT: .DEF Tmp = R16
.DEF K = R19
.DEF Result = R20
.EQU Takt = 1000000

CLR Tmp ; Initialisiere Tmp mit 0
CLR K ; Initialisiere K mit 0
CLR Result ; Initialisiere Result mit 0

; Stapel initialisieren
LDI Tmp, HIGH(RAMEND) ; RAMEND (SRAM) ist in der Definitionsdatei
OUT SPH, Tmp ; festgelegt
LDI Tmp, LOW(RAMEND)
OUT SPL, Tmp


;------------------------------------------------------------------------------
; Hauptprogramm
;------------------------------------------------------------------------------
MAIN:


RJMP MAIN ; Endlosschleife
END: RJMP END ; Endlosschleife
.EXIT ; Ende des Quelltextes

i_make_it
10.06.2015, 20:47
Ich sehe zwei Aufgabenstellungen.
1) Algorythmus für Fibonaccizahlen
2) Programm in Assembler

Von dem was Du bisher gepostet hast, kann man nicht erkennen ob Du überhaupt was davon kannst.
Poste doch einmal einen Fibonacci Algorythmus in einer Sprache die Du schon kannst.
Dann kann man auf der Basis anfangen das ganze in Assembler zu übersetzen.

Unregistriert
10.06.2015, 20:57
Ich kenne die Programmiersprache Java.

public class FibonacciIterativ {
// Iterative Berechnung der Fibonaccizahl
static int compute (int n)
{
if(n<=0) // fuer negative Zahl auch 0!
return 0;
else if(n==1)
return 1;
else
{
int a=0; // hat am Anfang der Schleife den Wert Fib(i-2)
int b=1; // hat am Anfang der Schleife den Wert Fib(i-1)
int i=2;
while(i<=n) // Schleife fuer alle Werte von 2 bis n {
int aa=b; // Wert von Fib(i-1)
int bb=a+b; // Wert von Fib(i)
a=aa; // Vorbereitung fuer den naechsten Durchgang
b=bb; // Vorbereitung fuer den naechsten Durchgang
i++; }
return b; } }

i_make_it
11.06.2015, 12:26
So der erste Schritt ist schon mal sich von der Klasse zu trennen.
Sprich alles was in "public class FibonacciIterativ" definiert ist,
muß in jeder Codezeile des eigentlichen Programms stehen.
(Assembler kennt keine Klassen)
Eigentlich muß man sich von allen Aspekten der Objekt orientierten Programmierung verabschieden (außer man deffiniert sie selbst in Assembler neu)

Schreib das mal so hin und schau schon mal welche Register im Zielsystem mit welcher Bitbreite für Operationen zur Verfügung stehen.
Ohne mir jetzt die Assemblerbefehle des spezifischen Zielsystems angesehen zu haben, wird z.B. aus einem Befehl wie:
int aa=b
lade Wert von Speicherzelle aa (Speicheradresse wo die Variable aa abgelegt wird) in Register xy.
Schreibe Wert von Register xy in Speicherzelle b (Speicheradresse wo die Variable b abgelegt wird).
danach hat man dann noch den Wert in dem Register xy stehen, und kann damit weiter arbeiten.
man braucht also lese und schreib Befehle und Vergleiche (für While und If) dann noch Sprünge um in die verschiedenen Zweige einer IF Struktur zu gelangen und auch wider raus sowie für Schleifen.

Gosub und Return kennt Assembler auch nicht.
Sprungbefehle sind eigentlich GOTO Befehle. (also das was man in Hochsprachen immer vermeiden soll)

Je nach Speicher Adressierung (Speicherblöcke) gibt es in Assembler auch Jump und Farjump. (hat der gesamte Code und die Daten in einem Speicherblock platz, dann spart man mit einem Jump gegenüber einem Farjump pro Befehl 33 bis 50% Speicherplatz und die Codeverarbeitung ist auch schneller.

Schreib jetzt mal den Code ohne die Klasse nochmal und bei den Returns und dem Ende der While Schleife je einen Komentar, das da ein Goto stattfindet und auch wohin.

Alternativ kann man sich auch das uralt Qbasic mal runterladen und den code damit schreiben.
Dadurch erhält man einen ser simplen sequentiellen Code der sich dann leicht in Assembler übersetzen lässt.

Wenn man den funktionierenden Assembler Code hat, kann man anfangen zu optimieren. (Verwendung von zwei, drei oder vier Registern um Schreib- und Leseoperationen zu minimieren.
Die Variablen stehen imme in den Registern und werden nur durch Registeroperationen bearbeitet. Nur die Ergebnisse werden geschrieben.
Da die Registerzugriffe schneller sind als Speicherzugriffe, wird damit die Verarbeitungsgeschwindigkeit deutlich erhöht.