Hallo, ich mache meine ersten Gehversuche mit C gemischt mit Assembler und brauche da Eure Hilfe. Ich habe in meinem C-Programm ein Array, dessen Bytes ich in der asm-Funktion durchlaufen und damit was machen möchte. Es geht hier nicht um eine bestimmte Funktion, sondern nur ums Lernen! Ich möchte auch kein Inline-Assembler! Wenn ich meinen Code kompiliere erhalte ich folgende Fehlermeldungen: undefined reference to r25 undefined reference to r24 ld returned 1 exit status Hier meine Code: C-Datei main.c: #include <avr/io.h> extern void firstfunc_asm(uint8_t* pArray); uint8_t myArray[2]; int main(void) { myArray[0] = 128; myArray[1] = 64; firstfunc_asm((uint8_t*)myArray); } Assembler-Datei test_asm.s: #include <avr/io.h> .global firstfunc_asm .section .text firstfunc_asm: LDI XH, r25 LDI XL, r24 LD r1,X+ ; do somethimg with r1 here ret Was mache ich falsch? Danke!
Du greifst direkt auf die Register zu, aber deine Daten sind in dem Array. Und das liegt im Speicher. Also LD r25, (Adresse von myArray). Laut http://www.mikrocontroller.net/articles/AVR_ASM_Befehls%C3%BCbersicht lädt man mit LDI nur Konstanten. Aber ich kann eigentlich auch nur ein bischen x86 Assembler, bei den AVRs hab ich das nie gemacht.
Halt: LDS r25, Adresse von myArray[0]. LD hat ein Pointerregister als Argument und das müsste man ja erstmal mit einem Pointer füllen. LDS braucht ja 2 Clocks, macht vermutlich diese beiden Schritte in einem Befehl.
Ich glaube der GCC versteht den AVR-ASM code so nicht. Das kannst du nicht einfach mischen. Dann musst du auch GCC-ASM schreiben.
Hallo Sascha, danke aber was ich hier mache ist ja auf R25 und R24 zuzugreifen, um den C-Pointer in das X-Register (für die indirekte Adressierung) zu bekommen. Wenn man aus C heraus eine asm-Funktion aufruft, dann werden die Parameter der C-Funktion in den Registern R25:R24, R23:R22 usw. übergeben. In meinem Fall würde also in R25 der high-Teil und in R24 der low-Teil der Adresse des Arrays übergeben. Nun möchte ich indirekt adressieren und dazu verwende ich das X-Register, dass ich über LDI XH, r25 und LDI XL, r24 fülle. Somit müsste das X-Register jetzt auf das erste Byte im Array zeigen. Dann möchte ich mit LF R1, X+ den Inhalt, auf den X nun zeigt in das Register 1 kopieren. Nach meinem Wissensstand müsste das so funktionieren, Aber wie gesagt es werden diese Fehler angezeigt.
Hallo Peter, danke aber das verstehe ich nicht. :-( Was macht movw. r26, r24? 1. Frage: Ist denn, wenn ich in der ASM-Funktion bin, im Register R25 die high-Adresse von myArray[0] und in R24 die low-Adresse von myArray[0]? 2.Frage: Warum geht LDI XH, r25 und LDI XL, r24 nicht? Ich wollte damit das X-Register auf die Adresse des Arrays setzen
Hi, konnte mir selber helfen, movw r26, r24 kopiert den Inhalt von r25:r24 nach r27:r26 (r27:r26 ist X Register) somit ist das, das was ich brauche (Danke Peter). Habe es probiert und es klappt auch. Ich würde aber gerne trotzdem wissen, warum ich das nicht so machen kann wie ich es gedacht habe mit: LDI XH, r25 LDI XL, r24 Wo ist da mein Denkfehler?
T.Baumbach schrieb: > Hallo Sascha, > > danke aber was ich hier mache ist ja auf R25 und R24 zuzugreifen, um den > C-Pointer in das X-Register (für die indirekte Adressierung) zu > bekommen. > > Wenn man aus C heraus eine asm-Funktion aufruft, dann werden die > Parameter der C-Funktion in den Registern R25:R24, R23:R22 usw. > übergeben. > In meinem Fall würde also in R25 der high-Teil und in R24 der low-Teil > der Adresse des Arrays übergeben. > Nun möchte ich indirekt adressieren und dazu verwende ich das > X-Register, dass ich über LDI XH, r25 und LDI XL, r24 fülle. Somit > müsste das X-Register jetzt auf das erste Byte im Array zeigen. > Dann möchte ich mit LF R1, X+ den Inhalt, auf den X nun zeigt in das > Register 1 kopieren. > > Nach meinem Wissensstand müsste das so funktionieren, Aber wie gesagt es > werden diese Fehler angezeigt. Der Fehler ist ganz klar, du verwendest LDI und das funktioniert nur mit Konstanten Werten, siehe Link. Du übergibst der ASM Funktion einen Pointer auf dein Array, also musst du vermutlich LD r1, X verwenden, das lädt dir die Daten auf die der X-Pointer zeigt in dein r1 Register. Also dein myArray[0]. Mit LD r2, X+ lädst du dann myArray[1]. Ist aber ungetestet. Aber sicher ist: LDI XH, r25 kann nicht funktionieren weil zweites Argument von LDI eine Konstante sein muss, kein Register und keine Speicherstelle. Also nur sowas wie LDI r1, 255 kann funktionieren.
Habe ich es übersehen, oder steht als erstes nicht um was für einen µC es sich handelt? Bei AVRs gibt es von Typ zu Typ Unterschiede in dem ASM Umfang. T.Baumbach schrieb: > danke aber das verstehe ich nicht. :-( > Was macht movw. r26, r24? http://www.atmel.com/images/atmel-0856-avr-instruction-set-manual.pdf
T.Baumbach schrieb: > Ich würde aber gerne trotzdem wissen, warum ich das nicht so machen kann > wie ich es gedacht habe mit: > > LDI XH, r25 > LDI XL, r24 > > Wo ist da mein Denkfehler? Beim LDI. Das I steht für Immediate. Mit LDI lädt man eine Konstante in ein Register. Was du willst, ist ein Register-zu-Register Transfer. Der Opcode dafür heißt MOV. Bzw. MOVW für ein Registerpaar. Leseempfehlung: http://www.atmel.com/images/atmel-0856-avr-instruction-set-manual.pdf @Sascha: wenn du keine Ahnung vom Thema hast, dann schreib doch bitte nichts. Ich lese deinen Namen seit ein paar Tagen regelmäßig über Posts, die bezeigen daß du noch nicht mal die Problemstellung begriffen hast. Deine Hilfsbereitschaft ist zu loben, aber wenn du schon das Problem nicht begriffen hast, dann bist du eben gerade keine Hilfe sondern trägst nur zur (weiteren) Verwirrung des Fragestellers bei. PS: das gilt nicht für deinen letzten Post. Aber für die beiden ersten.
:
Bearbeitet durch User
Danke Alex, das hat sehr geholfen! Dann werde ich mal weiter lernen ;-) Danke an alle!
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.