Liebe Gemeinde, habe ein Projekt in AVR-Assembler begonnen, da ich noch ein paar Atmega8 rumliegen hatte und diese genügend Pins haben. Mein Code funzt eigentlich, bis ich eine Routine aufrufen wollte, in Abhängigkeit des Carry-Flags. Ich schaff's einfach nicht. Mit brcc hab ich etwas halbwegs Funktionierendes zusammengebrutzelt, aber die Sprungweite ist glaube ich auf 64PC beschränkt und ich weiss nicht, ob der Stack bei dieser Instruktion beeinflusst wird. Ich möchte eine rcall-Routine aufrufen, am Schluss dieser Routine ret und dann im Programm Weiterfahren. Kann mir jemand helfen? freundliche Grüsse Picfan
Hi
>ob der Stack bei dieser Instruktion beeinflusst wird.
Sprünge beeinflussen keine Flags.
MfG Spess
spess53 schrieb: > Hi > >>ob der Stack bei dieser Instruktion beeinflusst wird. > > Sprünge beeinflussen keine Flags. > > MfG Spess Das war überhaupt nicht seine Frage! Er will in Abhängigkeit von einem Flag einen Sprung machen. Und er will wissen, ob der Stack beeinflusst wird.
picfan schrieb: > Ich schaff's einfach nicht. Schade. > Kann mir jemand helfen? Sicher. Hast Du auch eine Frage zu deinem Problem?
picfan schrieb: > Mit brcc hab ich etwas halbwegs Funktionierendes zusammengebrutzelt, > aber die Sprungweite ist glaube ich auf 64PC beschränkt und ich weiss > nicht, ob der Stack bei dieser Instruktion beeinflusst wird. > Ich möchte eine rcall-Routine aufrufen, am Schluss dieser Routine ret > und dann im Programm Weiterfahren. entweder du machst branch also Sprünge ohne Stacknutzung! Das wäre oneway! oder du willst jump subroutine dann wird die Rücksprungadresse auf den Stack gelegt! Das wäre mit return. Am LH5803 vom PC1500 hatte ich relokatibel programmieren wollen, also schied jsr jump subroutine aus, ergo hatte ich den PC gelesen die Rücksprungadresse berechnet auf den Stack gelegt und mit branch vor oder zurück die "Sub" angesprungen, durch die Berechnung vom aktuellen PC war es dann egal wo der Code im EEPROM lag. Also jsr ersetzt durch PC auf Stack + Korrektur dann branch +- byte und return normal durch Rücksprung (return) vom Stack lesen und Stack wieder herstellen.
Ohne den Hintergrund und die Vorstellungen eines 'pic-Fans' zu kennen, ein Versuch, ganz simpel:
1 | . |
2 | . |
3 | brcc hop |
4 | rcall Unterprogramm |
5 | hop: |
6 | . |
7 | . |
8 | |
9 | |
10 | Unterprogramm: |
11 | . |
12 | . |
13 | ret |
S. Landolt schrieb: > rcall Unterprogramm bei rcall wird sicher die Rücksprungadresse auf den Stack gelegt was picfan schrieb: > ob der Stack bei dieser Instruktion beeinflusst wird. eine Beeinflussung wäre S. Landolt schrieb: > Ohne den Hintergrund und die Vorstellungen eines 'pic-Fans' zu kennen so gehts mir auch, was will er was ist sein Ziel? will er Subs anspringen von mehreren Stellen und wieder zurück ohne Stackmanipulation? will er nur immer branch ohne return? keine Ahnung was er möchte.
eigentlich möchte ich nur stinkeinfach in Abhängigkeit vom C-Flag im SREG eine rcall Routine aufrufen, etwa so: start: ldi r16,0x80 ldi R17,0x90 sub R16,R17 ;r16 wird von r17 abgezogen, C-Flag müsste also gesetzt ;sein, d.h. PORTB,0 sollte = 1 sein, ist es aber nicht! ;meine Led an PORTB,1 leuchtet! lds R18,SREG sbrc r18,0 rcall ein nop sbrs r16,0 rcall aus nop rjmp start aus: sbi DDRB,1 sbi PORTB,1 ret ein: sbi DDRB,0 sbi PORTB,0 ret
Dann passt mein Beispiel. Übrigens ist
1 | lds R18,SREG |
falsch, es muss
1 | in r18,SREG |
heißen.
picfan schrieb: > sub R16,R17 ;r16 wird von r17 abgezogen, C-Flag müsste also gesetzt > ;sein, d.h. PORTB,0 sollte = 1 sein, ist es aber nicht! Doku lesen. ;-) Es gibt zwei Arten zu subtrahieren. Die einen subtrahieren, dann kommt im Beispiel hier für ein Borrow ein C=1 raus. Die anderen, wie AVR, addieren statt dessen das Einerkomplement. Dann kommt für ein Borrow ein C=0 raus.
S. Landolt schrieb: > Dann passt mein Beispiel. > > Übrigens ist >
1 | > lds R18,SREG |
2 | > |
> falsch, es muss >
1 | > in r18,SREG |
2 | > |
> heißen.
vielen Dank, werd ich ausprobieren!
Warum tut man sich das heutzutage noch an? Also ein ganzes Programm in Assembler schreiben. Auch den Atmega8 kann man LOCKER in C schreiben.
>Auch den Atmega8 kann man LOCKER in C schreiben.
Vielleicht, weil Assembler wesentlich übersichtlicher und vor Allem
nicht so "geheimnisvoll" wie "C" ist? In Assembler passiert das -und
nur das, was der Programmierer hinschreibt. Da wird nichts
wegoptimiert und Datentypen sind kein Lottospiel.
A. schrieb: > Warum tut man sich das heutzutage noch an? Also ein ganzes Programm in > Assembler schreiben. Auch den Atmega8 kann man LOCKER in C schreiben. Nicht schon wieder... Kannst du nicht zur Abwechslung mal einen Streit um Linux vs Windows anzetteln?
S. Landolt schrieb: > Übrigens ist >
1 | > lds R18,SREG |
2 | > |
> falsch, es muss >
1 | > in r18,SREG |
2 | > |
> heißen.
Hurra! nun klappt es, vielen Dank an S. Landolt!
Vielen Dank auch allen ausser Welke!
A. schrieb: > Warum tut man sich das heutzutage noch an? Also ein ganzes Programm in > Assembler schreiben. Auch den Atmega8 kann man LOCKER in C schreiben. Ja, im nachhinein gesehen wär's einfacher gewesen, habe aber einen fertigen, alten Assembler-code hervorgeholt, in der Hoffnung, diesen mit ein paar klicks an meine Bedürfnisse anzupassen......
picfan schrieb: > habe ein Projekt in AVR-Assembler Ich habe über viele erfolgreich Jahre in Assembler programmiert. Irgendwann kamen leistungsfähigere Prozessoren und mehr Memory. Seitdem Programmiere ich nur in Hochsprache. Assembler heutzutage ist etwas für Masochisten.
Anmerkung:
1 | brcc x1 |
2 | rcall ein |
3 | x1: |
4 | brcs x2 |
5 | rcall aus |
6 | x2: |
ist kürzer und schneller.
S. Landolt schrieb: > ist kürzer und schneller. Hier ja, aber riskant. Sobald ein/aus das C Flag beeinflusst, kommt die nächste Frage ins Forum.
S. Landolt schrieb: > Anmerkung: >
1 | > brcc x1 |
2 | > rcall ein |
3 | > x1: |
4 | > brcs x2 |
5 | > rcall aus |
6 | > x2: |
7 | > |
> ist kürzer und schneller.
ich muss insgesamt 8 Routinen aufrufen, da Branch den Stack nicht
bedient,
habe ich Angst, irgendwo ins Nivana zu springen.
Ich glaube ich mach's lieber etwas umständlich, so weiss ich sicher,
dass es funzt. Zeitkritisch ist das Projekt nicht.
Aber vielen Dank für Deine Bemühungen!
Nogger Dir Einen schrieb: > Vielleicht, weil Assembler wesentlich übersichtlicher und vor Allem > nicht so "geheimnisvoll" wie "C" ist? Das verstehe ich nicht? Assembler ist doch nicht übersichtlicher? Wie gesagt, etwas für Masochisten ;)...
A. schrieb: > Das verstehe ich nicht? Assembler ist doch nicht übersichtlicher? Für dich! Aber ich gebe ihm insofern recht, wenn er sagt, bei Assembler tut der µC genau das, was geschrieben steht. Bei einer Hochsprache bestimmt letztendlich der Compiler, was der µC macht...
Sumo schrieb: > A. schrieb: >> Das verstehe ich nicht? Assembler ist doch nicht übersichtlicher? > > Für dich! > > Aber ich gebe ihm insofern recht, wenn er sagt, bei Assembler tut der µC > genau das, was geschrieben steht. Bei einer Hochsprache bestimmt > letztendlich der Compiler, was der µC macht... Ich habe ja Anfangs auch Assembler programmiert. Heute erwische ich mich manchmal, wenn ich so vor mich hin programmiere folgendes: "Hättest du jetzt das alles in Assembler programmiert (STM32 mit 10000 Zeilen Code), dann hättest du für diese kleine Änderung womöglich Tage gebraucht und 1000 Folgefehler eingebaut. In C war es nun ein fehlerloses Klick, 1 Minute". Ich würde nicht mal mehr den kleinsten PIC in Asembler programmieren.
Soweit ich mich erinnere hat so ein AVR sowieso seltsame Verzweigungsbefehle. Man muss die Beschreibung eines bedingten Sprunges genauestens durchlesen, denn er kann bisweilen auf Bedingungen reagieren die nicht so offensichtlich sind. Ich habe den Sprung damals einfach aus einem Netz-Beispiel übernommen, genau verstanden habe ich es aber nicht - war auch mies beschrieben.
Genau schrieb: > Soweit ich mich erinnere hat so ein AVR sowieso seltsame > Verzweigungsbefehle. Es gibt eine Branchenkonvention, an die sich aber nicht alle halten: lower/higher = unsigned, less/greater = signed.
picfan schrieb: > A. schrieb: >> Warum tut man sich das heutzutage noch an? Also ein ganzes Programm in >> Assembler schreiben. Auch den Atmega8 kann man LOCKER in C schreiben. > > Ja, im nachhinein gesehen wär's einfacher gewesen, habe aber einen > fertigen, alten Assembler-code hervorgeholt, in der Hoffnung, diesen mit > ein paar klicks an meine Bedürfnisse anzupassen...... Wenn du weißt, was in diesem Assembler Code genau passiert, dann wäre es bestimmt leicht diesen schnell in C zu programmieren. Weniger Zeilen, lesbarer und in Zukunft schnell portierbar.
Genau schrieb: > Man muss die Beschreibung eines bedingten Sprunges > genauestens durchlesen, denn er kann bisweilen auf Bedingungen reagieren > die nicht so offensichtlich sind. Das SREG hat 8 Bits und daher gibt es 16 bedingte Sprungbefehle. Wenn Dir die Namen zu kompliziert sind, kannst Du im Sprungbefehl auch die Bitnummer (0..7) hinschreiben. BRBC 0, Ziel BRBS 7, Ziel Beachten muß man natürlich, daß nur bestimmte Befehle Bits setzen. Z.B. überlebt das C den INC-Befehl und das H den ADIW-Befehl. In der Praxis kann es daher passieren, daß der Sprung einige Befehle später erfolgt.
Zwölf M. schrieb: > Instruction manual fuer die AVR AVR Instruction Set Manual heißt das. (machts bei google einfacher)
Peter D. schrieb: > Das SREG hat 8 Bits und daher gibt es 16 bedingte Sprungbefehle. Wobei dieser direkte Zusammenhang zwischen SREG Bits und Sprungbedingungen eine Besonderheit der AVR Architektur ist. Andere Architekturen mit Statusregister haben kein S-Flag und müssen daher (N ⊕ V) als Teil des Sprungbefehls auswerten. Umgekehrt bedeutet es, dass andere Architekturen auch Bedingungen implementieren können, die AVR mangels passender SREG-Bits nicht beherrscht, wie etwa <= und > signed/unsigned. Die kamen u.U. ebenfalls auf 16 Bedingungen, aber ohne Zusammenhang mit dem Aufbau des Statusregisters.
:
Bearbeitet durch User
Beitrag #5310420 wurde von einem Moderator gelöscht.
c-hater schrieb im Beitrag #5310420: > Das Problem ist, dass Atmel (wohl zum Aufpushen der Zahl unterstützter > Instruktionen) fiktive Branch-Befehle für ihren Assembler erfunden hat, > die es in der Realität der Opcodes überhaupt nicht gibt. Das ist durchaus vernünftig. So entspricht beim AVR BRSH (same or higher) = BRCC, C=0 während der dazu äquivalente Befehl beim ARM BHS (higher or same) = BCS, also C=1 ist. Meint man den Vergleich ohne Vorzeichen, wird die Sprungrichtung bei BRSH/BHS sofort eindeutig, während man bei BRCC/BCS erst einmal über die unterschiedliche Arbeitsweise der Subtraktion nachdenken muss.
:
Bearbeitet durch User
A. K. schrieb: > c-hater schrieb im Beitrag #5310420: >> Das Problem ist, dass Atmel (wohl zum Aufpushen der Zahl unterstützter >> Instruktionen) fiktive Branch-Befehle für ihren Assembler erfunden hat, >> die es in der Realität der Opcodes überhaupt nicht gibt. > > Das ist durchaus vernünftig. So entspricht beim AVR > BRSH = BRCC, C=0 > während der dazu äquivalente Befehl beim ARM > BHS = BCS, also C=1 > ist. > > Meint man den Vergleich ohne Vorzeichen, wird die Sprungrichtung bei > BRSH/BHS sofort eindeutig, während man bei BRCC/BCS erst einmal über die > unterschiedliche Arbeitsweise der Subtraktion nachdenken muss. ??? Am Thema vorbei. Es geht um die Branches, bei denen in der vorhergehenden arithmetischen Operation Quell- und Ziel-Register getauscht werden müssen, damit das dem Namen nach zu erwartende Ergebnis bei der Verzweigung herauskommt...
c-hater schrieb: > Es geht um die Branches, bei denen in der vorhergehenden arithmetischen > Operation Quell- und Ziel-Register getauscht werden müssen, damit das > dem Namen nach zu erwartende Ergebnis bei der Verzweigung herauskommt... ???
c-hater schrieb im Beitrag #5310420: > Das Problem ist, dass Atmel (wohl zum Aufpushen der Zahl unterstützter > Instruktionen) fiktive Branch-Befehle für ihren Assembler erfunden hat, > die es in der Realität der Opcodes überhaupt nicht gibt. Selten so einen Quatsch gelesen. Natürlich gibt es die Opcodes. Wie sollte die Instruktion denn auch sonst ausgeführt werden? Und wie man auf so eine verquere Idee kommen kann, dass das Marketing den Befehlssatz festgelegt hätte, ist mir schleierhaft. Welchen Sinn hätte es denn gehabt, wenn man zwei separate Opcodes hat, die das selbe tun, vor allem, wo der Platz dafür eh recht knapp bemessen ist?
Es gibt für den selben Opcode mehrere Mnemonics, daran ist doch nichts schlimmes. Niemand muß Mnemonics benutzen, wenn er sie nicht mag. Deswegen muß man doch kein riesen Faß aufmachen. Aber so kennen wir unseren Hater. Der sieht Probleme, wo gar keine sind.
Rolf M. schrieb: > c-hater schrieb im Beitrag #5310420: >> Das Problem ist, dass Atmel (wohl zum Aufpushen der Zahl unterstützter >> Instruktionen) fiktive Branch-Befehle für ihren Assembler erfunden hat, >> die es in der Realität der Opcodes überhaupt nicht gibt. > > Selten so einen Quatsch gelesen. Natürlich gibt es die Opcodes. Wie > sollte die Instruktion denn auch sonst ausgeführt werden? Und wie man > auf so eine verquere Idee kommen kann, dass das Marketing den > Befehlssatz festgelegt hätte, ist mir schleierhaft. Vor allem ist das schon immer so, daß man auch mal zwei oder gar noch mehr Mnemonics für den gleichen Opcode hat. Die bedingten Sprungbefehle sind geradezu prädestiniert dafür, weil ein und das selbe Flag logisch durchaus etwas anderes bedeuten kann, je nachdem welche Operation das Flag gesetzt hat. Für das Zero-Flag gibt es typisch Mnemonics wie JREQ (Jump Relative when EQual) - sinnvoll zu verwenden nach einem Vergleich. Alternativ JRZ (Jump Relative on Zero) - z.B. nach dem Dekrementieren eines Schleifenzählers. Konkret sind das Menmonics für den Z8. Aber auch in 6502 Assembler gibt es das. Auch ganz nett ist CLR r als alternative Schreibweise für XOR r,r. Gestandene Assemblerprogrammierer kennen zwar diesen Trick, ein Register auf 0 zu setzen, aber beim Lesen des Codes ist der CLR Mnemonic eingängiger, weil er die Intention des Codes besser wiedergibt. Und der ganze Sinn der Assemblerprogrammierung mit Mnemonics statt der Opcodes (z.B. in Hexadezimal) ist ja Lesbarkeit
:
Bearbeitet durch User
Weniger nett sind allerdings CBR/SBR als Zweitverwertung von ANDI/ORI. Da wäre es besser gewesen, in Analogie zu CBI/SBI eine Bitnummer anzugeben, statt einer Maske. So wie jetzt kann ich nur empfehlen, diese Befehle nicht zu verwenden, um sich nicht versehentlich in den Fuss zu schiessen.
:
Bearbeitet durch User
Zu Assembler gegen C: Ich habe in einem youtube-Video gesehen dass ein freier COmpiler einen zusätzlichen PUSH-Befehl bei einem 8086-Programm in das Assembler-Ergebnis einbaute. Kann es sein dass man mit dieser extra-Nichtoptimierung Patent-Streitigkeiten aus dem Weg gehen will ?
Bla schrieb: > Kann es sein dass man mit dieser extra-Nichtoptimierung > Patent-Streitigkeiten aus dem Weg gehen will ? Wohl kaum. Du hast bei einem Compiler eine Anspruch auf korrekt umgesetzten Code, aber keinen Anspruch auf perfekt optimierten Code.
Axel S. schrieb: > Für das Zero-Flag gibt es typisch Mnemonics wie JREQ (Jump Relative when > EQual) - sinnvoll zu verwenden nach einem Vergleich. Alternativ JRZ > (Jump Relative on Zero) - z.B. nach dem Dekrementieren eines > Schleifenzählers. Konkret sind das Menmonics für den Z8. Aber auch in > 6502 Assembler gibt es das. Beim x86 ist das auch nicht anders. Da heißen sie JZ (jump if zero) und JE (jump if equal). > Auch ganz nett ist CLR r als alternative Schreibweise für XOR r,r. Ein anderes Beispiel wäre der Linksshift, für den man sich auch eine extra Opcode sparen konnte, da eine Addition eins Registers mit sich selbst das gleiche Ergebnis liefert. LSL rX ist daher identisch mit ADD rX, rX. Auch hier verbessert es die Lesbarkeit, wenn man das als Shift hinschreiben kann, statt als Addition.
A. K. schrieb: > Weniger nett sind allerdings CBR/SBR als Zweitverwertung von ANDI/ORI. Jo, da denkt der "normale" Programmierer eher in Masken und And und Or. > Da wäre es besser gewesen, in Analogie zu CBI/SBI eine Bitnummer > anzugeben, statt einer Maske. CBR/SBR können aber mehr als nur ein Bit auf 0/1 zu setzen. Bei Angabe von Bits bei SBR Rd,0xaa müsste man SBR Rd,1,3,5,7 hinschreiben. > So wie jetzt kann ich nur empfehlen, diese > Befehle nicht zu verwenden, um sich nicht versehentlich in den Fuss zu > schiessen. ACK. In diesem Falle ist der semantische Zucker überflüssig, stört aber auch nicht. Um ein Register zu Löschen schreiben wohl jeder CLR Rn Zucker anstatt EOR Rn,Rn sowie ROL Rn anstatt ADC Rn,Rn für Links-Rotieren.
Johann L. schrieb: > CBR/SBR können aber mehr als nur ein Bit auf 0/1 zu setzen. Bei Angabe > von Bits bei SBR Rd,0xaa müsste man SBR Rd,1,3,5,7 hinschreiben. Könnte man macher, aber ANDI/ORI ist ja nicht verboten, bloss weil es CBR/SBR gibt.
:
Bearbeitet durch User
A. K. schrieb: > ??? OK, du warst der einzige, der ohne die Hass-Reflexe der Nixwisser einfach nur die eigene Unkenntnis eingestanden hat. Also kriegst du auch eine sinnvolle Antwort. Es geht um das Problem, was ich im Anhang rot hervorgehoben habe. De facto gibt es die Hälfte der markierten Instruktionen nicht. Wie schon gesagt: das trifft auch noch auf viele weitere Instruktionen zu, aber hier, im Falle der conditionals ist es wirklich beschämend und unwürdig, denn hier kann nicht durch reine Assemblermagie am Ende doch das erwartete Ergebnis rauskommen, sondern man muss in der vorhergehenden Operation die Operanden tauschen. Das allein ist schon höchst fragwürdig, wäre aber vielleicht (je nach Leidensfähigkeit des Programmierers) für cp/cpc noch irgendwie akzeptabel (für cpi schon nicht mehr, denn da kann man die Operanden nicht einfach tauschen). Es ist aber vollkommen inakzeptabel für subi/sbci/sub/sbc, denn für die immediate-Varianten geht wiederum der Trick mit dem Operandentausch nicht, und bei dem Rest werden dann zwar die Flags entsprechend der Erwartungen gesetzt, aber es kommt numerisch schlicht das falsche Ergebnis raus (nämlich das Zweierkomplement des richtigen Ergebnisses). Und das ist ganz sicher vollkommen inakzeptabel. Zumal Atmel in seiner unerforschlichen Weisheit keine 'cpci'-Operation spendiert hat, man also beim Vergleich gegen Konstanten mit mehr als Byte-Größe sogar gezwungen ist, die potentiell destruktive Subtraktion zu benutzen.
c-hater schrieb: > De facto gibt es die Hälfte der markierten Instruktionen nicht. Diese Tabelle kannte ich überhaupt nicht. ;-). Die Mnemonics in der Tabelle gibts aber alle, nur die darin beschriebenen Sprungbedingungen gibts nicht alle. So gibts kein >/<= signed/unsigned. Die Tabelle bietet für diese Fälle nur eine Hilfestellung, was du tun musst, um diese Bedingungen dennoch nutzen zu können. Sie beschreibt keine Befehle. Und sie bezieht sich ausschliesslich auf Reg-Reg Vergleiche, da gibts diese Alternativen stets. > Zumal Atmel in seiner unerforschlichen Weisheit keine 'cpci'-Operation > spendiert hat, Tja, und die Moral von der Geschicht: Atmel hat nicht geschummelt, sondern hat nicht alle Befehle implementiert, die du gerne hättest. Für die fehlenden Bedingungen hätte es angesichts der Struktur der beiden einzigen echten bedingten Sprungbefehle BCLR/BSET ein 10 Bit Statusregister gebraucht. Eine Entscheidung der Basisarchitektur, nicht vom Marketing. Pech für die Kuh Elsa. So unerforschlich ist das übrigens nicht. In 16 Opcodebits passen keine 17 Bits rein. Reg-Immediate haben 12 Bits an Daten drin, weshalb jeder einzelne Befehl davon 1/16 des Opcode-Space frisst. Irgendwann ist voll: https://en.wikipedia.org/wiki/Atmel_AVR_instruction_set#Instruction_encoding
:
Bearbeitet durch User
A. K. schrieb: > Die Mnemonics in der Tabelle gibts aber alle Sie tuen nur nicht, was man erwarten dürfte. Jedenfalls nicht ohne massive Verbiegungen bei vorhergehenden Operationen und den Seiteneffekt des komplett falschen numerischen Ergebnisses, wenn man diese Verbiegungen tatsächlich unternimmt. Und genau das ist das Problem: es widerspricht dem Grundkonzept von Assembler. Das ist mehr sowas wie C. Irgendwas wird schon rauskommen, man muss nur hinreichend fest glauben, dass es auch richtig ist, dann passt das schon...
c-hater schrieb: > Sie tuen nur nicht, was man erwarten dürfte. Ich fürchte, dass du diese Tabelle völlig missverstehst. Sie beschreibt keine Befehle, keine Mnemonics. Sie beschreibt nur Bedingungen, mit denen man in Programmen mitunter zu tun hat. Die erste Spalte "Test" ist der Schlüssel der Tabelle, zusammen mit "Comment" für signed/unsigned. Der Rest ist eine sehr kurz gefasste Hilfestellung, mehr nicht. Besonders gelungen ist diese Darstellung allerdings wirklich nicht. Denk dir diese Tabelle einfach weg, reiss sie aus dem PDF raus. Dir geht dabei nichts verloren.
:
Bearbeitet durch User
A. K. schrieb: > Sie beschreibt keine Befehle. Und sie bezieht sich > ausschliesslich auf Reg-Reg Vergleiche, da gibts diese Alternativen > stets. Wo steht übrigens, dass sich diese Tabelle nur auf Register-*Vergleiche* bezieht? Die Stelle im DB musst du mir zeigen! OK, ich muss aber immerhin zugeben, dass das Immediate-Problem tatsächlich nicht von der Tabelle erfasst wird, denn sie setzt tatsächlich explizit auf Rd/Rr ab. Ist das gut? Wohl eher nicht, ist eher ein Armutszugnis für den Assembler. Der müsste dann nämlich konsequenterweise die Anwendung der entsprechenden Vergleiche als Fehler melden, wenn zuvor immediate-Operationen liefen. Das kann er nicht zuverlässig realisieren. Allein diese Tatsache zeigt die Unsinnigkeit dieser fiktiven Instruktionen! Und ganz sicher löst diese Einschränkung auch nicht das Hauptproblem des falschen numerischen Ergebnisses...
c-hater schrieb: > OK, du warst der einzige, der ohne die Hass-Reflexe der Nixwisser > einfach nur die eigene Unkenntnis eingestanden hat. Du hättest natürlich auch gleich dazuschreiben können, auf was du dich beziehst, statt erstmal so geheinminsvoll zu tun und irgendeinen Unsinn über Marketing-Verschwörungen zu verbreiten. c-hater schrieb: > De facto gibt es die Hälfte der markierten Instruktionen nicht. Dir ist aber aufgefallen, dass da einfach die selben Instruktionen zweimal stehen? Da wird also nirgends irgendeine Zahl an Instruktionen "aufgeputscht". Man hätte das allerdings wirklich in der Tabelle weglassen sollen - es verwirrt mehr, als dass es hilft. > Zumal Atmel in seiner unerforschlichen Weisheit keine 'cpci'-Operation > spendiert hat, man also beim Vergleich gegen Konstanten mit mehr als > Byte-Größe sogar gezwungen ist, die potentiell destruktive Subtraktion > zu benutzen. Das ist nicht "unerforschlich", sondern einfach der Tatsache geschuldet, dass man so eine Instruktion einfach nicht mehr hätte unterbringen können, bzw. man hätte dafür dann was anderes weglassen müssen. Du musst bedenken, dass bis auf ein paar wenige Ausnahmen alle Instruktionen 16 Bit breit sind, d.h. der - ich nenne es mal "Instruktionenraum" ist begrenzt (Ich meine damit die insgesamt 65.536 verschiedenen möglichen Kombinationen aus Opcode und Operanden). Gerade die Befehle mit Immediate-Werten belegen davon einen immens großen Teil, weil die Operanden soviel Platz in der Instruktion brauchen. Nehmen wir mal z.b. SUBI. Das wurde schon begrenzt auf die Hälfte der Register, weil es sonst überhaupt nicht mehr gepasst hätte. Es braucht damit 8 Bit für den übergebenen Immediate-Wert und 4 Bit für die Registerauswahl, also 12 Bit für die Operanden. Es bleiben lediglich 4 Bit für den Opcode. Das heißt diese eine Instruktion belegt 1/16 des gesamten Instruktionenraums. Man kann also nur eine begrenzte Menge davon unterbringen. Bei den Branch-Befehlen wurden 7 Bit für das Ziel reserviert und 3 Bit für die Art der Bedingung. Damit lassen sich also 8 verschiedene Branch-Befehle implementieren, und genau soviele gibt es auch. Bevor man über solche Begrenzungen schimpft, sollte man sich mal überlegen woher sie kommen, bzw. wie man es denn selber besser machen würde. Meist fällt einem dann auf, dass es durchaus Gründe gibt, warum es so ist. c-hater schrieb: > Wo steht übrigens, dass sich diese Tabelle nur auf Register-*Vergleiche* > bezieht? In der ganz linken Spalte. Da steht zu jeder Zeile, auf welchen Registervergleich sie sich ganz konkret bezieht. Oder was meinst du, was z.B. "Rd ≤ Rr" bedeutet?
:
Bearbeitet durch User
c-hater schrieb: > Wo steht übrigens, dass sich diese Tabelle nur auf Register-*Vergleiche* > bezieht? Die Stelle im DB musst du mir zeigen! Eben in besagter erster Spalte. "Rd > Rr". R=Register. Klar, steht auch "Zero" drin, aber da gibts auch kein Problem. Ich sag ja, die Tabelle ist etwas unglücklich dargestellt, weil sie versucht, 2 Fliegen mit einer Klappe zu erschlagen. Und dabei versehentlich dich erwischt. ;-) > eher ein Armutszugnis für den Assembler. Der müsste dann nämlich > konsequenterweise die Anwendung der entsprechenden Vergleiche als Fehler > melden, wenn zuvor immediate-Operationen liefen. Tut er doch auch, gewissermassen. Weil du schlicht nicht in der Lage bist, einen Vergleich <= oder > überhaupt in Assembler zu formulieren. Weil es kein Mnemonic dafür gibt. Spätestens wenn du sowas wie BRSL/BRLE für <= unsigned/signed hinschreibst, wird der Assembler dir sagen, dass es diese Mnemonics beim AVR nicht gibt. So würden sie vielleicht heissen, wenn es sie gäbe.
:
Bearbeitet durch User
Beitrag #5310980 wurde von einem Moderator gelöscht.
Beitrag #5310986 wurde von einem Moderator gelöscht.
Beitrag #5310988 wurde von einem Moderator gelöscht.
Beitrag #5310991 wurde von einem Moderator gelöscht.
Beitrag #5310994 wurde von einem Moderator gelöscht.
A. K. schrieb im Beitrag #5310994: > Programmiere lieber nicht in Assembler, wenn dich > solche einfachen Tabellen komplett aus der Kurve werfen. Nimm C. ;-) Hahaha, der ist gut. ;-)
A. K. schrieb im Beitrag #5310988: > Bring mir bitte ein Beispiel dafür, das wird mir zu abstrakt. Ich bin > nämlich nicht in der Lage, hinter > SUB r1,r2 > einen bedingten Sprungbefehl zu schreiben, der bei <= springt, egal ob > signed oder unsigned. Es existieren keine Befehle dafür, keine > Mnemonics. Nichts, wogegen ein Assembler etwas tun könnte oder sollte. > > Allerdings bin ich in der Lage, das umzudrehen. Also > SUB r2,r1 > BRGE target > Und genau das will dir die Tabelle sagen. Ja. Am Ende hast du richtig vezweigt, aber das falsche Ergebnis und obendrein im falschen Register... Ist dieses Mnemnonic das wert? Ich sage: es sollte dieses Mnemnonic überhaupt nicht geben. Genau das ist doch der Punkt. Es tut nur unter diversen Randbedingungen, was es tun soll und der Assembler ist nicht in der Lage, die Einhaltung dieser Randbedingungen zu kontrollieren. -> weniger als nutzlos->kontraproduktiv->überflüssig. Und weil mir vorgeworfen wurde, dass ich Marketing-Verschwörungstheorien erfinden würde: wer liefert den logisch zweifelsfreien Beweis für den Nutzen der fiktiven Mnemnonics. Ich bin bereits hochgespannt...
Beitrag #5311012 wurde von einem Moderator gelöscht.
Beitrag #5311016 wurde von einem Moderator gelöscht.
c-hater schrieb: > Ist dieses Mnemnonic das wert? Ich sage: es sollte dieses Mnemnonic > überhaupt nicht geben. Welchen? BRGE? Das wäre blöd. Wie mache ich dann einen Sprung, wenn ein Registerwert größer oder gleich einem anderen ist? > Genau das ist doch der Punkt. Es tut nur unter > diversen Randbedingungen, was es tun soll und der Assembler ist nicht in > der Lage, die Einhaltung dieser Randbedingungen zu kontrollieren. -> > weniger als nutzlos->kontraproduktiv->überflüssig. BGRE macht nicht das falsche, sondern genau das, was es soll. Die Tabelle sagt auch nicht, dass es etwas anderes tut, sondern sie sagt lediglich: Es gibt kein BRLE, also wenn du einen Vergleich auf kleiner oder gleich brauchst, nimm stattdessen BRGE mit vertauschten Operanden. Mehr will dir die Tabelle damit gar nicht sagen. c-hater schrieb im Beitrag #5311012: > Die schlichte Tatsache, das jeder Vergleich numerischer Werte implizit > eine Subtraktion ist. In Assembler ja. In der linken Spalte der Tabelle steht aber eine mathematische Darstellung, und da ist das nicht das gleiche.
c-hater schrieb: > A. K. schrieb im Beitrag #5310988: > >> Bring mir bitte ein Beispiel dafür, das wird mir zu abstrakt. Ich bin >> nämlich nicht in der Lage, hinter >> SUB r1,r2 >> einen bedingten Sprungbefehl zu schreiben, der bei <= springt, egal ob >> signed oder unsigned. Es existieren keine Befehle dafür, keine >> Mnemonics. Nichts, wogegen ein Assembler etwas tun könnte oder sollte. >> >> Allerdings bin ich in der Lage, das umzudrehen. Also >> SUB r2,r1 >> BRGE target >> Und genau das will dir die Tabelle sagen. Wenn du bitte die Güte hättest, hier nicht offen rumzulügen! Gib deinen Code als deinen Code aus, nicht als meinen. Das Bisschen copy&paste ist wohl zumutbar.
:
Bearbeitet durch User
sumo schrieb im Beitrag #5311016:
> Wenn das mal keine Gesprächskultur ist, dann weiss ich auch nicht! ;-)
Wenn man mit dem diskutiert, muss man sich wohl an solchen verbalen
Dünnpfiff gewöhnen. Ich hatte überlegt, an der Stelle abzubrechen, aber
mir war grad langweilig, also ignoriere ich die Entgleisungen mal
ausnahmsweise.
Rolf M. schrieb: >> Ist dieses Mnemnonic das wert? Ich sage: es sollte dieses Mnemnonic >> überhaupt nicht geben. > > Welchen? BRGE? Das wäre blöd. Wie mache ich dann einen Sprung, wenn ein > Registerwert größer oder gleich einem anderen ist? Vielleicht sollte es wirklich bloss BCLR und BSET geben und keinerlei verwirrende Aliase welcher Art auch immer. Das ist dann unzweifelhaft eindeutig. Und Assembler-Programmierung ist dann endlich wieder nur was für Experten wie ihn. ;-)
:
Bearbeitet durch User
A. K. schrieb: > Wenn du bitte die Güte hättest, hier nicht offen rumzulügen! Gib deinen > Code als deinen Code aus, nicht als meinen. Das Bisschen copy&paste > ist wohl zumutbar. Hätte mir aber mehr Arbeit gemacht. Ich bin faul. Aber deine allergische Reaktion zeigt doch überdeutlich, was ich zeigen wollte: Das ist Bullshit. Und es wäre genauso Bullshit, wenn ich korrekt zitiert hätte... Kannst du wenigstens das zugeben? Oder muss ich wirklich korrekt zitieren, die entprechenden Änderungen anbringen und dann sagen, dass das Ergebnis zeigt, dass diese Scheisse einfach nur Scheisse ist?
c-hater schrieb: > Ich bin faul. > Kannst du wenigstens das zugeben? Ja. ;-)
:
Bearbeitet durch User
c-hater schrieb: > De facto gibt es die Hälfte der markierten Instruktionen nicht. Die Instruktionen gibt es schon, nur eben nicht immer eine 1:1 Umsetzung von A <op> B zu Compare A,B + Branch<op>. > im Falle der conditionals ist es wirklich beschämend und > unwürdig, denn hier kann nicht durch reine Assemblermagie am Ende doch > das erwartete Ergebnis rauskommen, sondern man muss in der > vorhergehenden Operation die Operanden tauschen. "Reine Assemblermagie" kann eben nicht alle Probleme lösen. Hier ist man mit Hochsprache komfortabler. Zudem gibt es keinen Grund, eigens neue Opcodes einzuführen, wenn Compare B,A oder Compare A,const+1 oder Compare A,const-1 das Gewünschte auszudrücken vermag. Hier auf unnötige Opcodes zu verzichten ist weder "beschämend" noch "unwürdig", sondern gutes ISA-Engineering. Wenn dein Assembler über einen guten Präprozessor verfügt (wie z.B. der GNU-Assembler) kann dieser einen Großteil erledigen. Keine Not dafür neue Instruktionen oder Opcodes einzuführen und Silizium zu verpulvern. Ich geh mal davon aus, dass du als Assembler-Profi eine ungefähre Vorstellung davon hast, wie dicht oder dünn die AVR Opcode-Matrix besetzt ist. Genau. Und genau das ist auch der Grund, warum es zum Beispiel kein ADI oder ADCI gibt: Anstatt eine Konstante zu Addieren kann man deren Komplement subtrahieren = X+const = X-(-const) und -const aus const zu berechnen kostet nix da es nicht zur Laufzeit geschieht. > Das allein ist schon höchst fragwürdig, wäre aber vielleicht (je nach > Leidensfähigkeit des Programmierers) für cp/cpc noch irgendwie > akzeptabel (für cpi schon nicht mehr, denn da kann man die Operanden > nicht einfach tauschen). Braucht man auch nicht: a <= const ist gleichbedeutend mit a < const+1 a >= const ist gleichbedeutend mit a > const-1 a < const ist gleichbedeutend mit a <= const-1 a > const ist gleichbedeutend mit a >= const+1 Ausnahme sind die Intervallgrenzen: a <= 0xff ist a < 0x100, aber wenn a ein unsigend 8-Bit Wert ist dann ist der Vergleich trivial (dito für andere Werte an Intervallgrenzen). > Es ist aber vollkommen inakzeptabel für subi/sbci/sub/sbc, denn für die > immediate-Varianten geht wiederum der Trick mit dem Operandentausch > nicht, Siehe oben. > und bei dem Rest werden dann zwar die Flags entsprechend der > Erwartungen gesetzt, aber es kommt numerisch schlicht das falsche > Ergebnis raus (nämlich das Zweierkomplement des richtigen Ergebnisses). > Und das ist ganz sicher vollkommen inakzeptabel. Wenn es "vollkommen inakzeptabel" ist dann wirst du auf dieser Ebene nicht operieren da "vollkommen inakzeptabel". Also erübrigt sich jede inhaltliche Diskussion für dich und du kannst dich entspannt zurücklehnen. > Zumal Atmel in seiner unerforschlichen Weisheit keine 'cpci'-Operation > spendiert hat, Abermals: Es ist nicht beliebig viel Platz in der Opcode-Matrix, und Instruktionen mit Konstante wie ORI fressen 12 Bits d.h. 1/16 der Matrix! Alleine ANDI, ORI, SUBI, SBCI, CPI, RJMP, RCALL, LDD, STD, IN+OUT belegen jeweilt 1/16, zusammen also 10/16 > 60% aller Opcodes! > man also beim Vergleich gegen Konstanten mit mehr als > Byte-Größe sogar gezwungen ist, die potentiell destruktive Subtraktion > zu benutzen. Mit CPI+SBCI bleibt zumindest das LSB erhalten, oder man nimmt LDI+CPI+CPC. Irgendeinen Tod muss man sterben bei so einer kleinen Matrix...
Johann L. schrieb: > Hier auf unnötige Opcodes zu verzichten ist weder "beschämend" noch > "unwürdig", sondern gutes ISA-Engineering. Ich forderte nicht den Verzicht auf unnötige Op-Codes, sondern den Verzicht auf unnötige und fehlerhafte Mnemnonics! > Ich geh mal davon aus, dass du als Assembler-Profi eine ungefähre > Vorstellung davon hast, wie dicht oder dünn die AVR Opcode-Matrix > besetzt ist. Da kannst du tatsächlich getrost von ausgehen. Also von der Tatsache, dass mir nur zu bewußt ist, dass diese Matrix eben nicht gerade dünn besetzt ist. Ganz so, wie es bei einem RISC-Core auch sein sollte... > Genau. Und genau das ist auch der Grund, warum es zum > Beispiel kein ADI oder ADCI gibt ... Laber, laber, sülz. Erklärt alles nicht die fiktiven Branch-Ops! Genau das ist der Punkt, an dem meine "Verschwörungstheorie" als einzige mögliche Erklärung über bleibt, weil die Dinger halt tatsächlich keinerlei praktischen Nutzen haben, sondern eher kontraproduktiv sind. Und das hat mit der Besetzungsmatrix der tatsächlichen Opcodes auch absolut nix zu schaffen. Weil halt der Assembler fieserweise den Befehl auf den instruction space abbildet, der tatsächlich existiert, ohne aber zu kontrollieren, dass die Randbedingungen dafür eingehalten wurden. : Anstatt eine Konstante zu Addieren > kann man deren Komplement subtrahieren = X+const = X-(-const) und -const > aus const zu berechnen kostet nix da es nicht zur Laufzeit geschieht. > >> Das allein ist schon höchst fragwürdig, wäre aber vielleicht (je nach >> Leidensfähigkeit des Programmierers) für cp/cpc noch irgendwie >> akzeptabel (für cpi schon nicht mehr, denn da kann man die Operanden >> nicht einfach tauschen). > > Braucht man auch nicht: > a <= const ist gleichbedeutend mit a < const+1 > a >= const ist gleichbedeutend mit a > const-1 > a < const ist gleichbedeutend mit a <= const-1 > a > const ist gleichbedeutend mit a >= const+1 > > Ausnahme sind die Intervallgrenzen: a <= 0xff ist a < 0x100, aber wenn a > ein unsigend 8-Bit Wert ist dann ist der Vergleich trivial (dito für > andere Werte an Intervallgrenzen). > >> Es ist aber vollkommen inakzeptabel für subi/sbci/sub/sbc, denn für die >> immediate-Varianten geht wiederum der Trick mit dem Operandentausch >> nicht, > > Siehe oben. > >> und bei dem Rest werden dann zwar die Flags entsprechend der >> Erwartungen gesetzt, aber es kommt numerisch schlicht das falsche >> Ergebnis raus (nämlich das Zweierkomplement des richtigen Ergebnisses). >> Und das ist ganz sicher vollkommen inakzeptabel. > > Wenn es "vollkommen inakzeptabel" ist dann wirst du auf dieser Ebene > nicht operieren da "vollkommen inakzeptabel". Also erübrigt sich jede > inhaltliche Diskussion für dich und du kannst dich entspannt > zurücklehnen. > >> Zumal Atmel in seiner unerforschlichen Weisheit keine 'cpci'-Operation >> spendiert hat, > > Abermals: Es ist nicht beliebig viel Platz in der Opcode-Matrix, und > Instruktionen mit Konstante wie ORI fressen 12 Bits d.h. 1/16 der > Matrix! Alleine ANDI, ORI, SUBI, SBCI, CPI, RJMP, RCALL, LDD, STD, > IN+OUT belegen jeweilt 1/16, zusammen also 10/16 > 60% aller Opcodes! > >> man also beim Vergleich gegen Konstanten mit mehr als >> Byte-Größe sogar gezwungen ist, die potentiell destruktive Subtraktion >> zu benutzen. > > Mit CPI+SBCI bleibt zumindest das LSB erhalten, oder man nimmt > LDI+CPI+CPC. Irgendeinen Tod muss man sterben bei so einer kleinen > Matrix...
c-hater schrieb: > Erklärt alles nicht die fiktiven Branch-Ops! Kann es auch nicht, denn die sind nur in deinem Kopf und sonst nirgends auf der Welt. Damit trifft "fiktiv" es immerhin ganz gut, denn du bildest dir sie nur ein. Du bist aber der einzige, der die sieht. > Weil halt der Assembler fieserweise den Befehl auf den instruction space > abbildet, der tatsächlich existiert, ohne aber zu kontrollieren, dass die > Randbedingungen dafür eingehalten wurden. Wenn du einen BRGE hinschreibst, bildet er auch den genau ab. Es gibt weder irgendeinen anderen Mnemonic, der auf den selben Opcode abgebildet wird, noch gibt es irgendeinen anderen Opcode, auf den BRGE abgebildet wird. Deine "fiktiven Instruktionen" bildest du dir wie gesagt nur ein!
Beitrag #5311108 wurde von einem Moderator gelöscht.
Rolf M. schrieb: > Kann es auch nicht, denn die sind nur in deinem Kopf und sonst nirgends > auf der Welt. Damit trifft "fiktiv" es immerhin ganz gut, denn du > bildest dir sie nur ein. Du bist aber der einzige, der die sieht. Ähemm. Atmel selber sah es so und dokumentierte es explizit. Nämlich in genau dem Ding, was ich geposteted habe. Du verweigerst hier aber ganz schon die Realität, wenn du nichtmal die Original-Dokumentation des Herstellers des Zielsystems gelten läßt...
c-hater schrieb: >> Kann es auch nicht, denn die sind nur in deinem Kopf und sonst nirgends >> auf der Welt. Damit trifft "fiktiv" es immerhin ganz gut, denn du >> bildest dir sie nur ein. Du bist aber der einzige, der die sieht. > > Ähemm. Atmel selber sah es so und dokumentierte es explizit. Nämlich in > genau dem Ding, was ich geposteted habe. Nein! Da sind weder fiktive Befehle dokumentiert, noch welche, die was anderes tun als man erwarten würde. Wie gesagt: Einbildung deinerseits. > Du verweigerst hier aber ganz schon die Realität, Du merkst offenbar nicht, dass du der einzige hier bist, der das tut. Mir gehen aber langsam die Ideen aus, wie ich dir das klar machen könnte. Ich hab's jetzt mehrmals versucht, aber das prallt wohl einfach nur ab.
Beitrag #5311167 wurde von einem Moderator gelöscht.
Wolfgang schrieb: > Der hater redet sich wiedermal um Kopf und Kragen. Herrlich. Ja, ganz großes Kino. Da geht man mal für ein paar Stunden an die frische Luft und verpaßt sowas :)
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.