Hallo,
ich arbeite derzeit an meinem ersten Assemblerprogramm. Es soll einen
Counter, der bei 0 beginnt, hochzählen bis er max_value erreicht, in
diesem Fall 99. Anschließend soll diese Zahl mit dem Counter verglichen
werden, sollten sie gleich sein, dann soll in den Counter min_value,
hier -99, geladen und wieder hochgezählt werden.
Das Programm zählt ganz normal hoch, jedoch wird bei 99 kein wechsel
vorgenommen. Liegt das an dem Vergleich und anschließend dem Kopieren
der Zahl in den Counter? Oder ist es nicht ganz so einfach mit negativen
Zahlen im Assembler zu arbeiten? Ich kann leider den Fehler nicht
identifizieren und korrigieren. Ich hoffe, Ihr könnt mir weiterhelfen.
MfG Simner
Ähm was für ein Schwachsinn, sorry ...
Wieso nimmst du diesen seltsamen Inline-Assembler her?
In C brauchst du keinerlei Assembler und wenn du unbedingt Assembler
lernen möchtest, dann verwende einen Assembler und nicht diesen
Inline-C-Assembler-Quatsch, bei dem man nicht weiß, was passiert ;-)
Simner schrieb:> Ich hoffe, Ihr könnt mir weiterhelfen.
Aber gerne doch:
Hilfe Nr. 1: poliere doch mal bitte die universelle Glaskugel oder
alternativ teile uns doch mal mit welche Architektur es denn sein
soll...
Dein Code ist unsinnig. Z.B. sehe ich folgende Sequenz (das nop steht
nur zur Illustration da, real wäre da Code, der was tut)
1
cp foo, bar
2
breq label
3
4
label: nop
Du vergleichst zwei Werte und willst, das bei Gleichheit zu label
gesprungen wird. Nur kommt label direkt nach dem Sprungbefehl. Was
glaubst du wohl, was die CPU als nächstes ausführt wenn der Sprung
nicht genommen wird?
>Oder ist es nicht ganz so einfach mit negativen Zahlen im Assembler zu arbeiten?
Also wenn in einem Register z. B. 9D drinsteht (Hex) und du davon
ausgegangen bist, dass es -99 (Dez), dann liegst du falsch - im Register
steht 157 (Dez). Wenn du Assembler benutzt, würde ich Atmel Studio
empfehlen, bei dem Inline-Ding blicken wenige durch... ich nicht...
Ferner... Axel erwähnte es bereits:
"label_inc: \n\t"
"inc %[counter] \n\t"
"cp %[counter], %[max_value] \n\t"
"breq label_high \n\t"
"jmp label_end \n\t"
Ich nehme an, du möchtest den counter erhöhen (mehrmals), bis dieser den
Wert max_value erreicht, wenn also counter=max_value dann springst du zu
label high, wenn aber nicht, dann springst du zu label_end - heißt der
counter wird hier nur ein Mal inkrementiert.
Simner schrieb:> ich arbeite derzeit an meinem ersten Assemblerprogramm.
Dann schreibs auch als Assemblersource (*.S) und nicht dieses völlig
verquaste Inline.
Warum denkst Du überhaupt, daß Du besseren Assembler erzeugen kannst,
als der Compiler?
Simner schrieb:> Das Programm zählt ganz normal hoch, jedoch wird bei 99 kein wechsel> vorgenommen.
Naja, der Assemblercode sollte da eigentlich schon einen Wechsel
vornehmen (hat gerade beim Testen auch so funktioniert). Da sollte der
Fehler irgendwo in deinem restlichen Programm zu finden sein. Hast du
darauf geachtet signed ints zu verwenden? Wie Norbert schon schrieb sind
-99 und +157 lediglich unterschiedliche Interpretationen des gleichen
Bitmusters, und hier muss man dem Compiler schon sagen wie man's
interpretiert haben möchte.
Das Program hier
Der Wechsel ist deutlich zu sehen, und bei der Betrachtung von Counter
als signed int ist das Ergebnis auch wie gewünscht (vorausgesetzt
natürlich das wirklich das Intervall ]-99, 99[ gewünscht ist, und
nicht[-99, 99]).
Danke schon mal für die Tipps und Kommentare.
Im Prinzip sieht mein Programm ähnlich aus. Ich nutze aber für counter,
min_value und max_value signed ints.
Das mit dem unterschiedlichen Interpretationen war mir nicht klar. Ich
lasse mir den Counter über ein 7-Segment-Display anzeigen. Der Wechsel
erfolgt dann doch, da er von 99 auf 157 springt und weiter hochzählt.
Wie kann ich dem Compiler sagen, dass ich die 157 als -99 interpretiert
haben möchte?
Das wird dann wohl nicht mehr am Compiler sondern an den Funktionen zur
Ansteuerung des Displays liegen. Sind dort denn negative Zahlen
vorgesehen? Falls nicht dann muss man sich das halt selber dazustricken
(ohne die Funktionen zu kennen kann man dazu allerdings kaum hilfreiche
Tipps geben..)
Peter D. schrieb:> Simner schrieb:>> ich arbeite derzeit an meinem ersten Assemblerprogramm.>> Dann schreibs auch als Assemblersource (*.S) und nicht dieses völlig> verquaste Inline.>> Warum denkst Du überhaupt, daß Du besseren Assembler erzeugen kannst,> als der Compiler?
Das hat er nicht behauptet. Ganz im Gegenteil, er wies ausdrücklich
darauf hin, dass es sein erstes Assemblerprogramm ist, und du wußtest
das, denn du hast diese Aussage sogar selber zitiert.
Klar: jemand, der gerade sein erstes Assemblerprogramm schreibt, ist
höchstens zufällig bei einer kleinen Teilroutine mal nennenswert besser
als ein heutiger C-Compiler. In aller Regel wird er bestenfalls gleich
gut oder gar schlechter sein.
Aber: jeder fängt mal an. Man muss eben aus seinen Fehlern einfach mal
nur lernen. Es fängt an, cool zu werden, wenn man in der Lage ist, die
Sache wenigstens erstmal korrekt in Asm umzusetzen.
Soweit ist der TO allerdings offensichtlich noch lange nicht. Zwischen
dem geposteten Programm und der verbalen Beschreibung der gewünschten
Funktion besteht doch eine ganz erhebliche Diskrepanz...
Ich vermute allerdings ganz stark: der TO ist auch nicht in der Lage,
die gewünschte Funktionalität korrekt in C umzusetzen...
Ich sage nur: Arduino. Das sagt eigentlich schon alles...
c-hater schrieb:> Zwischen> dem geposteten Programm und der verbalen Beschreibung der gewünschten> Funktion besteht doch eine ganz erhebliche Diskrepanz...
Das wundert mich garnicht, wenn man das falsche Werkzeug benutzt.
Inline Assembler fasse ich nichtmal mit der Kneifzange an. Ich muß mir
meine Gehirnwindungen nicht unnütz verknoten.
Dessen Berechtigung sehe ich ausschließlich in *.h-Files (delay.h usw.).
Ich hab nichts gegen Assembler lernen. Dann aber im richtigen Assembler
und mit aussagefähigen Registernamen und Kommentaren. Sonst lernt man
nichts außer irgendwo was abzuschreiben.
Aber auch in Assembler gilt, alle verwendeten Symbole einem Leser
bekannt zu machen. Er kann schließlich nicht in Deinen Kopf sehen.
Und diese magischen 0x55, 0x44 sollte man auch erklären.
> Wie kann ich dem Compiler sagen, dass ich die 157 als -99 interpretiert> haben möchte?
Gar nicht. Wie Besucher sagte, du musst die entsprechende
Display-Routine anpassen. Wenn man Assembler lernen möchte, sollte man
immer das "Instruction Set Manual" anschauen, um zu sehen welche
Kommandos überhaupt mit negativen Zahlen arbeiten. Dann sollte man
wissen, dass in einem Register stets nur eine Zahl zwischen 0 und 255
stehen wird. Dies hier:
LDI r16,0x00
DEC r16
wird ins Register r16 die Zahl 0 laden. Dann wird die 0 dekrementiert,
was zu folge hat, dass dann in r16 die Zahl 255 steht. Wenn man
allerdings im "Instruction Set Manual" nach dem Kommando DEC nachschaut,
wird man feststellen können, dass DEC u. a. das Negativ-Flag beeinflußt.
(Einige Kommandos arbeiten halt mit signed andere mit unsigned.) Wenn
man also das N Flag im obigen Beispiel nach der Ausführung von DEC
überprüft, wird man feststellen, dass es gesetzt wurde, was nun heißt,
dass man eine negative Zahl im Register hat. -1 in Hex ist ff, also 255.
Dies heißt deine Anzeige-Routine muss nach DEC oder INC das N-Flag
überprüfen um dann die Zahl entsprechend als -1 oder 255 anzuzeigen.
Norbert T. schrieb:> Dies heißt deine Anzeige-Routine muss nach DEC oder INC das N-Flag> überprüfen um dann die Zahl entsprechend als -1 oder 255 anzuzeigen.
Nein.
Ob 0xFF in einem 8-Bit Register 255 oder -1 bedeutet, ist allein eine
Interpretationssache. In C gibts dafür die signed und unsigned
Modifier an den Integer-Typen. In Assembler muß der Programmierer das
selber wissen. Genauso wie er seine Variablen auf Register (und RAM)
verteilen muß, muß er auch wissen ob sie vorzeichenbehaftet sind.
Das N-Flag wird von vielen arithmetischen Operationen beeinflußt. Die
ALU setzt das Flag immer so, wie es für vorzeichenbehaftete Zahlen
gesetzt sein muß. Ob das Programm das Flag auswertet, hängt einzig davon
ab, was die Zahlen in den Registern bedeuten. Wenn sie unsigned sind,
dann hat das N-Flag schlicht keine Bedeutung. Und manchmal sind die
Registerinhalte auch gar keine Zahlen, sondern z.B. Zeichencodes.