Forum: Mikrocontroller und Digitale Elektronik Assembler Neuling - komme nicht weiter


von T.Baumbach (Gast)


Lesenswert?

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!

von Sascha (Gast)


Lesenswert?

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.

von Sascha (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

Ich glaube der GCC versteht den AVR-ASM code so nicht. Das kannst du 
nicht einfach mischen. Dann musst du auch GCC-ASM schreiben.

von T.Baumbach (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

T.Baumbach schrieb:
> LDI XH, r25
>   LDI XL, r24

ist falsch.
Richtig:
1
   movw r26, r24

von T.Baumbach (Gast)


Lesenswert?

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

von T.Baumbach (Gast)


Lesenswert?

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?

von Sascha (Gast)


Lesenswert?

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.

von volker (Gast)


Lesenswert?

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

von T.Baumbach (Gast)


Lesenswert?

Hi,

zur Info: ich arbeite mit dem Atmega32 und AVR Studio 7

von Axel S. (a-za-z0-9)


Lesenswert?

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
von T.Baumbach (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.