Forum: Mikrocontroller und Digitale Elektronik Seltsame ASM-Anweisung -> Erklärung?


von Ina (Gast)


Lesenswert?

Hallo,

ich debugge gerade ASM-Code für einen Atmega128 der von einem Vorgänger 
(Studienarbeit an der Uni) verbrochen wurde. Dokumentation des Codes 
geht quasi gegen 0 und ich habe die ehrenvolle Aufgabe, nun die 
Fehlerursache zu finden.

Ich bin dabei nun mehrfach auf folgendes Konstrukt gestoßen mit dem ich 
irgendwie nicht viel anfangen kann:
1
sts     PORTG, r24
2
sts     DDRG, r24
3
lds     r24, PORTG

Ich meine hierbei das letzte "lds". Dort passiert nach meinem 
Verständnis ja nichts anderes, als dass der Wert, der von r24 nach PORTG 
geladen wurde wieder zurück nach r24 geladen wird, die Anweisung könnte 
man also auslassen da sie ja nichts anderes macht als "r24 = r24", oder 
sehe ich das falsch? Denn an PORTG anliegende Signale müssten ja mittels
1
lds r24,PING

eingelesen werden, oder?

Gruß,
Ina

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ina schrieb:
> die Anweisung könnte
> man also auslassen da sie ja nichts anderes macht als "r24 = r24", oder
> sehe ich das falsch?

Wenn er nicht gerade die verplemperten Taktzyklen für das Timing
braucht ;-), ja.  Ist ein teurer NOP.

> Denn an PORTG anliegende Signale müssten ja mittels
> lds r24,PING
>
> eingelesen werden, oder?

So ist es.

von Karl H. (kbuchegg)


Lesenswert?

Darf ich fragen, was der Code überhaupt macht?

Ungewöhnlich, dass man mitten im Code das DDR Register umsetzt. 
Normalerweise stellt man die am Programmanfang einmal korrekt ein, und 
dann bleibt das auch so.
Kann natürlich auch sein, dass der Portpin bewusst zwischen Ein/Ausgang 
hin und hergeschaltet wird, um an einem Ausgangspin die Zustände 
High-Low-Tristate zu erreichen. Das kommt aber nicht so oft vor und der 
abschliessende LDS weckt dann nicht wirklich das Vertrauen in mir.

von Ina (Gast)


Lesenswert?

Hallo,

diese Stelle taucht nicht mitten im Programm auf sondern beim 
Progbrammstart, das hatte ich vergessen zu erwähnen. Die "normalen" 
I/O-Ports werden wie üblich konfiguriert aber bei den Ports die im 
extended I/O liegen fängt er dann plötzlich mit solchen Geschichten an. 
An Port G hängt zwar auch ein DSP, aber dadurch dass ja eben nicht PING 
eingelesen wird kann es ja eben nicht sein, dass dort irgendwelche 
Signale ausgewertet werden. ich weiß nun nicht wie fit mein Vorgänger in 
ASM war, vielleicht ist es tatsächlich nur ein teures NOP weil er dachte 
er müsste zwingend die zwei Zyklen überbrücken bis das STS fertig ist 
o.ä., ich wollte mich nur nochmal absichern dass mit solch einer 
Befehlskombination nicht möglicherweise irgendetwas ganz "Abgedrehtes" 
gemacht werden kann ;)

Gruß,
Ina

von spess53 (Gast)


Lesenswert?

Hi

> oder?

Nicht unbedingt. Das Portregister hat auch noch die Aufgabe bei 
Eingängen den Pull-Up-Widestand einzuschalten. Also kann es durchaus 
sinnvoll sein dieses auszulesen. Für den Zustand der Eingänge wäre 
natürlich PING richtig.

MfG Spess

von Anton (Gast)


Lesenswert?

Das Umschalten eines Ports oder Teile davon
kann schon mal vorkommen, wenn der Port Bidirektionales
IO macht.

Daß das Register des Ports zurückgelesen wird kann
den Grund haben: z.B. ein am Port hängender Transistor
zieht den Pin beim H-Zustand "zuweit" runter und der
PIN liest dann eine 0 statt einer 1 zurück.

Ohne nähere Info zur HW halte ich mich mal mit
evtl. bösen Kommentaren zurück.

Hier würde ich aber mal nach dem Fehler suchen.

von Karl H. (kbuchegg)


Lesenswert?

spess53 schrieb:
> Hi
>
>> oder?
>
> Nicht unbedingt. Das Portregister hat auch noch die Aufgabe bei
> Eingängen den Pull-Up-Widestand einzuschalten. Also kann es durchaus
> sinnvoll sein dieses auszulesen.

Schon.
Aber in diesem Zusammenhang und unter Berücksichtigung des Faktums, dass 
immer das gleiche Register r24 involviert ist, macht es nicht wirklich 
großartig Sinn


    ldi   r24, 0xAA
    sts   PORTG, r24
    sts   DDRG, r24
    lds   r24, PORTG

was soll in r24 jetzt stehen, ausser 0xAA?


Er schaltet die Pins auf 1, dann auf Ausgang. Bis daher ist das noch 
sinnvoll. Aber wozu das zurücklesen?

von MWS (Gast)


Lesenswert?

Man muss nicht immer in merkwürdigem Code nach Sinn suchen, jedoch gäbe 
es eine Bedingung, d.h. wenn ein Interrupt PORTG verändern kann, bei der 
dieser Code dann nicht mehr einem einfachen MOV R24, R24 entspricht. Da 
käme es auf das weitere Code-Umfeld an.

Anton schrieb:
> Daß das Register des Ports zurückgelesen wird kann
> den Grund haben: z.B. ein am Port hängender Transistor
> zieht den Pin beim H-Zustand "zuweit" runter und der
> PIN liest dann eine 0 statt einer 1 zurück.

Nein, den Grund hat's sicher nicht. Wenn der Portpin mit Gewalt gezogen 
wird, kann man das nicht durch Lesen des Port-Registers raus bekommen, 
da muss man Pin lesen.

von Karl H. (kbuchegg)


Lesenswert?

Anton schrieb:

> zieht den Pin beim H-Zustand "zuweit" runter und der
> PIN liest dann eine 0 statt einer 1 zurück.

Dann müsste er aber das Pin Register auslesen. Aus dem Port Register 
kriegt er genau den Wert wieder raus, den er vorher reingeschrieben hat.

von Karl H. (kbuchegg)


Lesenswert?

MWS schrieb:
> Man muss nicht immer in merkwürdigem Code nach Sinn suchen,

Ist für mich eine Frage der Vertrauensbildung.

Kann natürlich auch sein, dass das ein Überbleibsel von früher oder ein 
Copy&Paste Fehler ist.

Macht er denn in weiterer Folge irgendwas mit dem Wert in r24?
Das ist für mich bei Analysen meistens ein ganz guter Leitfaden. Die 
Überlegung: OK, da wird also ein Wert geholt - was macht er damit?

von K. J. (Gast)


Lesenswert?

Hm mal ne Spekulation bin in AVR ASM nicht so fit, aber z.b. bei PICs 
wird das auch öfters gemacht z.b. um nen Statusbit zu setzen b.z.w. nen 
Resultat in nem Statusbit zu bekommen, allerdinks müsste dann im 
folgecode was dementsprechend auftauchen.

von MWS (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> MWS schrieb:
>> Man muss nicht immer in merkwürdigem Code nach Sinn suchen,
>
> Ist für mich eine Frage der Vertrauensbildung.

Meine Aussage war: manchmal ist Blödsinn einfach nichts weiter als 
Blödsinn.

Karl Heinz Buchegger schrieb:
> OK, da wird also ein Wert geholt - was macht er damit?

Genau darauf sollte man achten und das schrieb ich:
> Da käme es auf das weitere Code-Umfeld an.

von Peter D. (peda)


Lesenswert?

Manchmal sieht man in C eine verkettete Zuweisung. Dann muß der Compiler 
die volatile Variable wieder auslesen.
1
  PORTA = PORTB = 0xAA;
2
  72:   8a ea           ldi     r24, 0xAA       ; 170
3
  74:   88 bb           out     0x18, r24       ; 24
4
  76:   88 b3           in      r24, 0x18       ; 24
5
  78:   8b bb           out     0x1b, r24       ; 27


Peter

von Wooschder (Gast)


Lesenswert?

Wie wird r24 nach dem Stückchen Code benutzt?

von Peter D. (peda)


Lesenswert?

Ina schrieb:
> ich debugge gerade ASM-Code für einen Atmega128
...
> ich habe die ehrenvolle Aufgabe, nun die
> Fehlerursache zu finden.

Der Fehler wird sein, daß man 128kB einfach nicht mehr in Assembler 
programmieren kann.
Schmeiß alles weg und schreibs in C.

Assembler nehme ich nur für sehr kleine Programme (unter 2kB).


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Manchmal sieht man in C eine verkettete Zuweisung. Dann muß der Compiler
> die volatile Variable wieder auslesen.

http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_assign_chain

von Klaus W. (mfgkw)


Lesenswert?

Vielleicht ist es ja auch gar kein originärer Quelltext, sondern 
versehentlich disassemblierter Datenbereich :-)

von Ina (Gast)


Lesenswert?

Hallo,

danke für eure Hilfe, es ist allerdings definitiv Code :) Peter 
Dannegger hat mich aber auf die richtige Spur gebracht.
1
PORTA = PORTB = 0x01;
2
DDRA = DDRB = 0x01;

wird z.B. mit AVR Studio 5 tatsächlich zu
1
ldi r24, 1
2
out PORTB, r24
3
in r24, PORTB
4
out PORTA, r24
5
ser r24
6
out DDRB, r24
7
in r24, DDRB
8
out DDRA, r24

Ich habe damit wohl meinem Vorgänger Unrecht getan, ich muss jetzt 
erstmal klären woher dann dieser ASM-Code kommt, bzw. warum mir kein 
C-Code zur Verfügung gestellt wird. Auf jeden Fall schonmal vielen Dank 
für eure Hilfe, wieder was gelernt :)

Gruß,
Ina

von Ina (Gast)


Lesenswert?

Nachtrag: DDRA und DDRB werden natürlich auf 0xFF gesetzt, nicht auf 
0x01 :D

von Mark L. (m2k10) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Der Fehler wird sein, daß man 128kB einfach nicht mehr in Assembler
> programmieren kann.

Ähm, naja, also, um zumindest für mich persönlich diese Sache einmal zu 
klären habe ich vor ca. 12 Monaten ein Projekt begonnen, das inzwischen 
auch langsam fertig wird.
Ich habe hier einen Heimcomputer komplett aus parallel arbeitenden AVRs, 
mehr als 15 Grafikmodi, Raster-IRQ, SD-Laufwerk, 
6502/6510/Z80/6809-Interpreter, alles durchgetaktet, in Echtzeit mit 
2MHz bei 24MHz-Systemtakt. Alles komplett durchoptimierter Assemblercode 
bzgl. Laufzeit und über 128kB dürfte ich locker drüber liegen. Die 
einzelnen AVRs sind komplett über den gesamten Code Taktgenau 
synchronisiert um die hohe Geschwindigkeit zu erreichen, absolut 
unmöglich das per Compiler zu machen.
Und das 'Ding' läuft :-) Weiß noch nicht, was ich damit überhaupt 
anfange und ob ich es evtl. veröffentliche, aber prinzipiell können kann 
'man' auch viele zehntausend Zeilen sinnvollen und hochoptimierten 
Assemblercode schreiben, der Beweis steht hier neben mir.

Mag sein bzw. würde mich inzwischen nicht mehr wundern, dass das etwas 
sehr ungewöhnlich ist, wie bspw. Pi auf über 22.000 Stellen aufsagen, 
kann ich selbst so wenig, wie die meisten anderen. Aber da kann 'man' ja 
auch nicht mehr allgemein sagen, 'man' könne es nicht sondern muss sagen 
'ich' kann es nicht. Dafür darf man sich dann freuen eine Gemeinsamkeit 
mit 99,irgendwas Prozent aller Menschen zu haben :-)

Ich will auf keinen Fall eine Diskussion zu dem Thema Assembler 
verursachen, ich wollte nur mal die Gelegenheit wahrnehmen, diese 
althergebrachte Behauptung mit Fakten zu widerlegen. Jemand sagte zwar 
mal, dass ein Vorurteil in der heutigen Zeit schwerer zu zertrümmern 
sei, als ein Atom, aber vielleicht kann ich dieses Dogma ja mal etwas 
ankratzen. ;-)

Ontopic:
Es war keine Rede von der Programmgröße auf dem mega128. Und 64.000 
Zeilen Code schreiben, dürfte für eine Studienarbeit schon vom reinen 
Tippen her zuviel Arbeit sein. Und irgendwie wage ich zu bezweifeln, 
dass die 'freiwillig' Assembler verwenden, wenn's nicht die 
Aufgabenstellung vorschreibt. Da wird vermutlich ein typischer 
Anfängerfehler wie PORTG und PING vertauscht oder so drin sein.

Grüße
Mark

von Jochen (Gast)


Lesenswert?

Mark L. schrieb:
> Ich habe hier einen Heimcomputer komplett aus parallel arbeitenden AVRs,
> mehr als 15 Grafikmodi, Raster-IRQ, SD-Laufwerk,
> 6502/6510/Z80/6809-Interpreter, alles durchgetaktet, in Echtzeit mit
> 2MHz bei 24MHz-Systemtakt.

Faszinierend! Respekt!

von Mark L. (m2k10) Benutzerseite


Lesenswert?

Jochen schrieb:
> Faszinierend! Respekt!

Danke! :-)

von Jonathan S. (joni-st) Benutzerseite


Lesenswert?

Mark L. schrieb:
> Ähm, naja, also, um zumindest für mich persönlich diese Sache einmal zu
> klären habe ich vor ca. 12 Monaten ein Projekt begonnen, das inzwischen
> auch langsam fertig wird.
> Ich habe hier einen Heimcomputer komplett aus parallel arbeitenden AVRs,
> mehr als 15 Grafikmodi, Raster-IRQ, SD-Laufwerk,
> 6502/6510/Z80/6809-Interpreter, alles durchgetaktet, in Echtzeit mit
> 2MHz bei 24MHz-Systemtakt. Alles komplett durchoptimierter Assemblercode
> bzgl. Laufzeit und über 128kB dürfte ich locker drüber liegen. Die
> einzelnen AVRs sind komplett über den gesamten Code Taktgenau
> synchronisiert um die hohe Geschwindigkeit zu erreichen, absolut
> unmöglich das per Compiler zu machen.

WILL! DAS! DING! SEHEN!!! Unbedingt ;)


Ich mache hier übrigens gerade etwas ähnliches - eine kleine 
Spielekonsole mit 2 ATMega1284P. Einer als Grafikprozessor und einer als 
"Großhirn". Das Teil schafft eine Grafikauflösung von 160x100 bei 64 
Farben :D. Aber bei mir sind nur die Takte der Grafikausgabe handgezählt 
und auf eine bestimmte Laufzeit getrimmt, der Rest läuft mit einfachen 
Interrupts ;). Im Großhirn wird dann ein CPU-Emulator laufen - ich peile 
da so 500k bis 1M Instruktionen pro Sekunde an...


Gruß
Jonathan


P.S.: Sorry für's OT

von Jobst M. (jobstens-de)


Lesenswert?

Peter Dannegger schrieb:
> Der Fehler wird sein, daß man 128kB einfach nicht mehr in Assembler
> programmieren kann.

Hmmm ... mit 64kB geht es noch ...

> Schmeiß alles weg und schreibs in C.

Halte ich für Unsinn!


Gruß

Jobst

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.