Forum: Mikrocontroller und Digitale Elektronik An "Unterprogramm" Parameter übergeben (Assembler)


von Sebastian Wille (Gast)


Lesenswert?

Hi,

mit Unterprogramm meine ich z.B.:

UART_Ausgabe:
...
ret

Nun möchte ich an dieses "Unterprogramm" Parameter übergeben. Im
Moment mache ich dies mit festen Stellen im SRAM und eben per LDS bzw.
STS.

Nun war meine Idee das ganze per PUSH und POP zu machen. Wenn ich's
recht verstanden habe, geht das aber nicht. Denn wenn ich im
"Unterprogramm" POP sage, bekomme ich ja die Rücksprung-Adresse,
richtig?!?

Wie kann man sonst noch Parameter geschickt und schnell übergeben?

Per festem Register-Befehl geht auch nicht, da ich die Register von
R16-R31 im Unterprogramm direkt brauche und die restlichen Register nur
über Umwege und nicht über ldi beschrieben werden können.

Danke schonmal!

Sebastian

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Normalerweise ist der Umweg über den Stack sinnlos, wenn man schon einen
Prozessor mit so vielen Registern hat. Du kannst doch problemlos R0-R15
verwenden, das zusätzliche mov bei der Übergabe von Konstanten tut
nicht weh (ldi r16, 'a'; mov r8, r16; rcall unterprogramm).

von Mike (Gast)


Lesenswert?

So sinnlos kann das mit dem übergeben der Parameter per Push und Pop
nicht sein, besonders wenn die Register belegt sind oder nicht
ausreichen.

Dass du die betreffenden Parameter nicht mit Pop bekommst ist richtig,
du kannst sie aber mit push auf den Stack legen und dann in deinem
Unterprogramm mit:
IN  ZL, SP
SUBI  ZL, (-5)
lesen. Dabei musst du die -5 natürlich evtl. anpassen.

Der Vorteil ist einfach, das das Programm universeller wird.
Nach der Routine nicht vergessen die Daten wieder vom Stack zu löschen,
sonst läufter der irgendwann über.

MfG Mike

von Peter D. (peda)


Lesenswert?

"Wie kann man sonst noch Parameter geschickt und schnell übergeben?"


Viele Wege führen nach ROM:


Von Push würde ich abraten, da man zu sehr aufpassen muß, daß der Stack
immer ausbalanciert ist.

Außerdem ist doch "ldi r16, 1"+"mov r2,16" schneller als "ldi r16,
1"+"push r16".


Du kannst aber auch die Register erst innerhalb der Funktion pushen,
wenn Du sie brauchst. Wenn die Funktion öfter aufgerufen wird, ist das
sogar effektiver.


Schließlich kannst Du konstante Parameter einfach hinter den Aufruf
plazieren ".db xxx"und dann per "lpm" auslesen. Mit "ijmp"
springt man dann dahinter zurück. Das wird z.B. gerne gemacht, um Texte
auszugeben, in AVRFReaks ist dazu eine Designnote.


Dann kannst Du auch einen Pointer als Parameterstack reservieren und
mit "st X+, r16" und "ld r16, -X" die Parameter reinladen bzw.
abholen.



Peter

von Sebastian Wille (Gast)


Lesenswert?

Hi,

danke erstmal für alle Antworten! :-)

Ich stell' gerade fest, daß sowohl PUSH als auch POP ja je 2
Taktzyklen brauchen. LDI und MOV brauchen jeweils 1 Taktzyklus, also
gibt sich das ganze ja dann die Hand.

Ich werde die Register r2 bis r15 als generelle Übergabe-Parameter
verwenden, r0 und r1 brauche ich schon für MUL.

Vielen Dank nochmals für die tollen Ideen! :-)

Sebastian

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.