Forum: Mikrocontroller und Digitale Elektronik [ASM] XOR with immediate als Macro


von Ville (Gast)


Lesenswert?

Guten Abend,

hin und wieder bräuchte ich auf dem Atmega8 ein XOR with immediate. 
Mangels eingebauter Instruktion habe ich mir ein Macro erstellt:

1
.macro eori             // usage: eori Rd, K (15 <= d <= 31, 0 <= K <= 255)
2
    push    temp2       // 2c
3
4
    mov     temp2, @0   // 1c
5
    ldi     @0, @1      // 1c
6
    eor     @0, temp2   // 1c
7
8
    pop     temp2       // 2c
9
.endmacro

temp2 ist r12. Das ganze braucht 7 Taktzyklen.

Geht das irgendwie schneller? Wenn ja, wie?


Danke und Gruss
Ville

von Nase (Gast)


Lesenswert?

Warum das "mov"?

von Ville (Gast)


Lesenswert?

Ich glaube, ich verstehe die Frage nicht richtig.

Ohne das "mov" verliere ich den Wert im Register @0 beim "ldi", den ich 
für mein "eori" verwenden möchte. Und beim "eor" würde ein unbestimmter 
Wert aus temp2 verarbeitet werden.

Oder übersehe ich da was?

von Nase (Gast)


Lesenswert?

Ville schrieb:
> Ohne das "mov" verliere ich den Wert im Register @0 beim "ldi", den ich
> für mein "eori" verwenden möchte. Und beim "eor" würde ein unbestimmter
> Wert aus temp2 verarbeitet werden.

Ja schon, aber warum nimmst du kein temporäres Register >= R16 und lädst 
direkt darein?

von S. Landolt (Gast)


Lesenswert?

Weil er sich dann u.U. das Quellregister überschreibt.

von Ville (Gast)


Lesenswert?

Genau, man weiss ja nicht, welches Register @0 ist. Daher habe ich eins 
kleiner gleich r15 für temp2 gewählt. Und "ldi" sichert ab, dass @0 
grösser gleich r16 ist. Ein Überschreiben ist somit ausgeschlossen.

von Jobst M. (jobstens-de)


Lesenswert?

Und was überschreibt man sich bei:
1
.macro xori
2
push    temp2       // 2c
3
ldi  temp2, @1
4
eor  @0, temp2
5
pop     temp2       // 2c
6
.endmacro

?

Zumal sich bei mir bei temp sowieso nur um ein Kürztzeitspeicher handelt 
und ich schreiben würde:
1
ldi  temp, "Zahl"
2
eor  Zielregister, temp

... ohne push/pop


Gruß

Jobst

von (prx) A. K. (prx)


Lesenswert?

Jobst M. schrieb:
> Und was überschreibt man sich bei:

Wenn @0 = temp2

Aber wenn man ernsthaft mit Macros arbeiten will, nicht bloss diesem 
einen, dann sollte man mindestens 1 Register für Macros reservieren. Ist 
sonst witzlos, denn oft hat man ein Register frei, was die push/pop 
Befehle unnötig macht.

von Jobst M. (jobstens-de)


Lesenswert?

A. K. schrieb:
> Wenn @0 = temp2

Nö. Das Problem hat er auch so. Wenn das Macro zu Ende ist, wird temp2 
wieder vom Stack geholt und der alte Wert hergestellt.


Gruß

Jobst

von Ville (Gast)


Lesenswert?

Jobst M. schrieb:
> ...wird temp2 wieder vom Stack geholt und der alte Wert hergestellt.
Richtig so. Es soll ja auf Register @0 ein XOR mit dem Wert @1 
stattfinden und temp2 am Ende unverändert sein.

A. K. schrieb:
> ...dann sollte man mindestens 1 Register für Macros reservieren.
Das habe ich mir schon gedacht. Dann werde ich das wohl so machen - 
spart ja auch Programmspeicher, wenn ich die Pushs/Pops weglassen kann 
(gerade, wenn man das Macro öfter im Code verwendet). Ich wollte nur 
sicher gehen, dass es nicht vielleicht doch eine kleverere Lösung gibt.

Danke an alle!

von Route_66 H. (route_66)


Lesenswert?

Ville schrieb:
> hin und wieder bräuchte ich auf dem Atmega8 ein XOR with immediate.

Man kann es auch übertreiben.

Für das doch eher seltene "hin und wieder" halte ich das Verstecken in 
einem Makro für Blödsinn. Die Erwiderungen oben zeigen die Risiken 
bezüglich der verwendeten Register auf.
"Hin und wieder" kann man den Assemblertext auch ausschreiben, und kennt 
im konkreten Fall die nutzbaren Register.

von Willi (Gast)


Lesenswert?

Noch ein Risiko:

Dieses EORI Rx,K sieht in einem Assemblerlisting zunächst mal aus wie
ein einzelner CPU-Befehl. Deshalb übersieht man leicht, dass evtl. mal 
ein
Interrupt genau in Macro "reinhauen" kann.
Das kann zu schwer zu findenden, weil nur sporadisch auftretenden 
Fehlern führen. Ich hab selbst mal Tage damit verbracht, so einen blöden 
Fehler zu finden. Ein Antrieb, der ansonsten sauber lief, "zuckte" so 
etwa ein bis zwei mal pro Stunde ganz kurz. Ursache war ein kleines 
Macro wie oben. Die Chance war klein, aber ein Interrupt schaffte es 
trotzdem ab und zu, genau in den Macro und veänderte ein Register das 
der Macro per PUSH gesichert hatte. Die Änderung war dann nach dem POP 
verloren. Das auch für den Macro der Wert geändert wurde, war in diesem 
Fall nicht tragisch.
Also nicht nur PUSH und POP sondern auch CLI und SEI. besonders, wenn 
man das Macro öfters auch in späteren Projekten einsetzen will.
Führt natürlich zu dem neuen Problem, das man dem EORI nicht ansieht, 
das wärend der Ausführungszeit die INTs gesperrt sind...

MfG Willi

von Ralf G. (ralg)


Lesenswert?

Willi schrieb:
> aber ein Interrupt schaffte es
> trotzdem ab und zu, genau in den Macro und veänderte ein Register das
> der Macro per PUSH gesichert hatte.

Da ist aber nicht das Macro schuld, sondern der Interrupt, der sich 
nicht an die Regeln hält.

von Micha (Gast)


Lesenswert?

@Willi: Was du da schilderst, hat doch nichts mit Macros zu tun. Es ist 
doch egal, ob der Code automatisch durch das Macro erzeugt wird, oder ob 
ich ihn selbst eintippe.
Klingt mir eher danach, als hättest du die in der ISR verwendeten 
Register nicht auf dem Stack gesichert. CLI und SEI sind hier nicht 
notwendig.

von Jobst M. (jobstens-de)


Lesenswert?

Ville schrieb:
> Richtig so. Es soll ja auf Register @0 ein XOR mit dem Wert @1
> stattfinden und temp2 am Ende unverändert sein.

Und bei der Bedingung, dass @0 = temp2 ist @0 anschliessend unverändert.
Richtig so?


Gruß

Jobst

von Sascha W. (sascha-w)


Lesenswert?

Jobst M. schrieb:
> Ville schrieb:
>> Richtig so. Es soll ja auf Register @0 ein XOR mit dem Wert @1
>> stattfinden und temp2 am Ende unverändert sein.
>
> Und bei der Bedingung, dass @0 = temp2 ist @0 anschliessend unverändert.
> Richtig so?
Kann nicht passieren,
schon im ersten Post steht doch das @0 nur die Register r15 bis r31 
annehmen kann (wie bei immidate Befehlen üblich - ok könnte man noch per 
if prüfen) temp2 aber Register r12 ist.

Sascha

von Thomas H. (Firma: CIA) (apostel13)


Lesenswert?

Und ich sag wieder mal was ganz böses: Wer für so etwas basal simples 
eine Frage in einem Forum stellen muss, versucht sich vielleicht besser 
an etwas noch simplerem als 8 Bit Assembler.

von S. Landolt (Gast)


Lesenswert?

Sascha Weber schrieb:
> ok könnte man noch per if prüfen
Wie sähe das aus?

von (prx) A. K. (prx)


Lesenswert?

Sascha W. schrieb:
> schon im ersten Post steht doch das @0 nur die Register r15 bis r31
> annehmen kann (wie bei immidate Befehlen üblich - ok könnte man noch per
> if prüfen) temp2 aber Register r12 ist.

Man kann sich durch geeignete Randbedingungen das Leben so schwer wie 
möglich machen. Also beispielsweise, indem man vorrangig jene Register 
für temporäre Zwecke reserviert, die dafür am wenigsten geeignet sind. 
Wie R0-15.

Ohne Reservierung eines geeigneten Registers gibt es schlicht keinen 
wirklich kurzen eleganten Weg, den fehlenden Befehl zu ersetzen. Also 
bleibt eigentlich nur, entweder ein Register für Makroverwendung zu 
reservieren, oder auf den Makro zu verzichten.

Dazu kommt freilich auch, dass AVRs Assembler durch recht überschaubare 
Leistungsfähigkeit glänzt. Assembler, die für umfangreiche 
Makroprogrammierung konzipiert wurden, sehen anders aus. Atmel setzt 
offenbar eher auf Programmierung in C.

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.