Hallo. 'Tschuldigung, dass ich hier wieder was auf den Tisch bringe, was schon beliebig häufig durchgekaut worden ist: Mit folgendem Code kann ich auf das dritte Byte in einer Tabelle zugreifen. ldi ZH,high(LookUp*2) ldi ZL,low(LookUp*2) adiw ZL,2 lpm ... .db 0x01, 0x90, 0xwasweissdennich... In meinem Fall möchte ich aber die Tabelle über ein Register indizieren. Nun kann ich eine Kopie des Registers erstellen und in einer Schleife auf Null prüfen, und wenn nicht adiw ZL,1 und an den Anfang der Schleife hüpfen... Die Lösung gefällt mir aber nicht, wegen der Schleife. Ich habe versucht mein Register auf das ZL draufzuaddieren, und dann den Carry zu verarbeiten. Kommt aber Scheissdreck dabei raus.... Ich habe hier auch in den Beiträgen gesucht, aber nix gefunden... Wie macht man's richtig? ciao Dirk
clr R1 ... add ZL,R16 addc ZH,R1 gcc hat in Wert R1 immer die NULL stehen, ist sicher auch für asm-Programmierung kein schlechter Ansatz. Wenn Du Assembler tiefer verstehen willst: schau Dir den asm-Output Deines Compilers an und versuche ihn nachzuvollziehen ... Gruß, Stefan
R1 sollte man aber besser nicht als Null-Wert verwenden, daß wird doch bei MUL und SPM benötigt. Peter
Ich habe dsa Register angegeben, welches von gcc auch als NULL-Reg benutzt wird. Dann muss man nicht groß umbauen, wenn die asm-Funktion vom Compiler aus verwendet wird. Nach mul oder muls löscht der Compiler R1 wieder auf Null (eor r1,r1). Stefan
@Stefan, als Assemblerprogramierer ist man ja glücklicherweise an keinerlei Restriktionen gebunden, wie ein C Compiler. Da kann man alles so machen, wie es gerade auch vernünftig ist. Die Sache hat nämlich noch einen weiteren Haken, ein Interrupt muß dann davon ausgehen, daß R1 doch nicht 0 ist. Die Folge davon ist, daß in C Interrupts sehr lang werden. Ein leerer Interrupt dauert ja 10 Zyklen. Mit einer Grundarie an PUSH/POP für R0,R1,SREG usw. dauert ein leerer Interrupt in C aber schon 30 Zyklen, d.h. da ist noch garnichts gemacht. Das ergibt dann z.B. für einen 16Bit Zähler an einem externen Interrupt in Assembler 14 Zyklen unter Verwendung von Registervariablen aber in C sinds dann ja schon 40 Zyklen. Anders gesagt, wenn man sich in Assembler an die C Konventionen halten würde, verliert man doch alles Vorteile in Bezug auf Kodegröße und Geschwindigkeit. Deshalb würde ich in Assembler auf C überhaupt keine Rücksicht nehmen. Was einmal in Assembler angefangen wurde kann man eh nicht 1:1 in C umschreiben oder integrieren. Peter
ich benutze in C eigentlich immer die Option #savereg- und kümmer mich selber um die Sicherung, ist in der Tat ein bisschen viel des guten, was die Compiler da so veranstalten. Oft stört es zwar nicht, aber es gibt schon zeitkritische Sachen. Ich habe bis jetzt auch noch keinen Compiler gesehen, der vorher schaut, was gerettet werden muss, und auch nur dieses tut.
Hallo. Danke nochmal für die Hinweise. Ich hatte 'Add With Carry' verwendet und nicht darüber nachgedacht, was das eigentlich bedeutet. Jetzt sieht's echt gut aus. ciao Dirk
@crazy horse: ist ne gute Idee, werde ich mal ausprobieren. @peter: ich mache eigendlich auch sehr gerne viel in Assembler. Aber Portieren auf eine andere CPU heisst dann halt immer: komplett neuschreiben. Mittlerweile bemühe ich mich, den Hauptteil in C zu schreiben und nur die zeitkritischen Sachen in ASM zu machen. Klar, einen IR in C, das tut schon weh. Aber die Ausgabe auf ein LCD in ASM zu optimieren, um danach länger auf selbiges warten zu dürfen ... muss ich mir nicht mehr antun. Ich bin gerade am Ausprobieren, wie man gcc überredet, Register freizuhalten (für den IR), was ich bisher gelesen habe, sollte das eigendlich schon machbar sein. Stefan
Register freihalten ist doch gar kein Problem, du definierst dir einfach eine (oder mehrere) char-Variablen global, bei CV kannst du sogar bestimmen, in welches Register die kommt (bei anderen Compilern sicher auch, weiss ich aber nicht) unsigned char asm_var @ 5 z.B. Meckert dann zwar ein bisschen beim compilieren warning: var xxx declared, but never used bla bla bla), aber wen stört das. Ist auch ein schöner Weg, in einer ISR per Assembler Daten zu manipulieren, die dann vom C-Programm weiterverarbeitet werden. Meist reserviere ich auch ein Register auf diesem Weg für das SREG in ISRs. Bsp: eine Int-Variable soll bei Timerüberlauf incrementiert werden. Lässt man den Compiler gewähren, wie er will, dauert diese einfache Aufgabe 74 Takte, assembleroptimiert sind es nur 9 Takte...
Ja, genau das probiere ich gerade beim gcc. Da funktioniert es mit register char dummy asm("r8"); Habe aber noch nicht auf ev. Seiteneffekte untersucht bzw. welche Reg man für sowas verwenden darf. Vor allem wie die libc auf sowas reagiert will ich mir noch anschauen. Es gibt auch eine Compiler-Option, die ein Reg freihält, dann geht es auch ohne Warnung, habe ich aber noch nicht probiert. Stefan
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.