Atmega8, Carry-Flag

Gast #5309851
Lesenswert?

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
Gast #5309869
Lesenswert?

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.
#5309890
Lesenswert?

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.
#5309909
Lesenswert?

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.
Gast #5309911
Lesenswert?

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
#5309926
Lesenswert?

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.
Gast #5309939
Lesenswert?

>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.
Gast #5309944
Lesenswert?

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......
Gast #5309970
Lesenswert?

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!
Gast #5309983
Lesenswert?

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...
Gast #5310079
Lesenswert?

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.
Gast #5310184
Lesenswert?

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.
Gast #5310201
Lesenswert?

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.
#5310229
Lesenswert?

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.
#5310254
Lesenswert?

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.
Beitrag #5310420 wurde von einem Moderator gelöscht.
#5310438
Lesenswert?

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.
Gast #5310456
Lesenswert?

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...
#5310726
Lesenswert?

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?
#5310741
Lesenswert?

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.
#5310759
Lesenswert?

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
#5310767
Lesenswert?

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.
Gast #5310796
Lesenswert?

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 ?
#5310854
Lesenswert?

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.
Persönliche Seite #5310862
Lesenswert?

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.
Gast #5310922
Lesenswert?

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.
Angehängte Dateien:
#5310950
Lesenswert?

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
Gast #5310956
Lesenswert?

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...
#5310962
Lesenswert?

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.
Gast #5310969
Lesenswert?

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...
#5310970
Lesenswert?

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?
#5310978
Lesenswert?

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.
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.
Gast #5311006
Lesenswert?

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.
#5311020
Lesenswert?

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.
#5311025
Lesenswert?

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.
#5311027
Lesenswert?

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.
#5311032
Lesenswert?

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. ;-)
Gast #5311039
Lesenswert?

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?
Persönliche Seite #5311063
Lesenswert?

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...
Gast #5311092
Lesenswert?

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...
#5311105
Lesenswert?

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.
Gast #5311115
Lesenswert?

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...
#5311125
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren