Hallo Leute, ich hab da nochmal eine Frage zu den AVR Opcodes. Es scheinen ein paar Opcodes mehrfach belegt zu sein, z.B. haben die ASM-Befehle BRBC und BRCC den selben Opcode. An anderer Stellen habe ich das Gefühl, dass sich Opcodes aufgrund der Argumente überschneiden können, so z.B. die Befehle BRBS, BRCS und BRLO. Für BRBS gilt der Opcode: 1111 00kk kkkk ksss <- 0 <= s <= 7; -64 <= k <= +63 Für BRCS gilt der Opcode: 1111 00kk kkkk k000 <- -64 <= k <= +63 Sind jetzt die Argumente für BRBS beide 0 und für BRCS auch 0 so erhält man die gleichen Opcodes. So jetzt die Fragen: Wie unterscheidet die CPU diese Befehle? Ist eine Unterscheidung überhaupt notwendig? Und wie sieht es aus, wenn man das ganze umdreht: Man hat ein Hex-File das man interpretieren möchte (z.B. ein Emulator). Wenn ich in dem Hex-File auf einen entsprechenden Opcode treffe, kann ich mir dann einfach aussuchen ob ich nun BRBS, BRCS oder BRLO nehme? Wäre schön, wenn Ihr mir helfen könntet :) Grüße
Die Unterscheidung ist nicht nötig. Die mehrfach vorkommenden Opcodes sind spezielle Fälle, die es dem Nutzer einfacher machen sollten. Der BRBS Befehl ist die allgemeine Form, dazu gibt es dann je nach Flag noch spezielle Namen. Neben den Sprüngen gibt es da noch ein paar andere Spezialfälle die andere Namen bekommen. Etwa AND mit sich selbst heißt auch TST oder EOR mit sich selbst als CLR.
Sie haben soeben das Geheimnis von Atmels "131 Powerful Instructions" gelüftet: da hat's einige Dubletten drin. Zum Beispiel auch sbr und ori, oder cbr und andi.
> Es scheinen ein paar Opcodes mehrfach belegt zu sein, z.B. haben die > ASM-Befehle BRBC und BRCC den selben Opcode. Jein. BRCC ist halt einfach BRBC(carry). Weil man BRBC(carry) häufig braucht kann man dafür auch ein neues Mnemonic einführen. Das nennt man dann BRCC und definiert das zu prüfende Bit als carry.
> Für BRBS gilt der Opcode: > 1111 00kk kkkk ksss <- 0 <= s <= 7; -64 <= k <= +63 > > Für BRCS gilt der Opcode: > 1111 00kk kkkk k000 <- -64 <= k <= +63 Das ist keine Doppelbelegung, BRCS ist schlicht ein Spezialfall von BRBS, nämlich BRBS auf Bit 0 (= Carry). Das ist nur um den Assembler Code besser lesbar zu machen. Aus dem Maschinencode kannst du dann natürlich nicht mehr schließen, was in den Assemblerquellen stand.
BRBS – Branch if Bit in SREG is Set BRCS – Branch if Carry Set Carry ist Bit 0 im SREG BRLO bezieht sich auf das Ergebnis eines Vergleichs ohne Vorzeichen. Bei "lower" ist danach Carry gesetzt.
:
Bearbeitet durch User
BRBS Label,0 branch on status bit set und BRCS Label branch on carry set Sind deswegen identisch, weil Carry im Bit0 des SREG liegt. Solche "Abkürzungen" gibt's für alle Status Bits. Zu lang getippt ;-)
:
Bearbeitet durch User
Kaj G. schrieb: > Es scheinen ein paar Opcodes mehrfach belegt zu sein, z.B. haben die > ASM-Befehle BRBC und BRCC den selben Opcode. Du siehst das unter dem falschen Betrachtungwinkel. Es ist nämlich einfach nur so, dass Atmel etliche fiktive Instruktionen geschaffen hat, die es nur auf Asm-Quelltextebene gibt. Der Sinn der Sache war reines Marketing. Man konnte halt dann in's DB schreiben dass z.B. 112 Instruktionen unterstützt werden, obwohl es de facto nur 70 oder so sind. Tatsächlich schnurrt das deutlich zusammen, wenn man es auf die echten Opcodes reduziert. Bei vielen dieser Instruktionen merkt man es garnicht, das sind echte (also wirklich vollständig nutzlose) Alias-Instruktionen. Z.B. "ori" vs. "sbr". Oder auch "ldi reg,-1/255/$ff" vs. "ser". Einige andere sind nur wenig intelligenter, z.B. "andi" vs. "cbr". Tatsächlich macht der Assembler still und heimlich einfach aus dem "cbr reg,immediate" ein "andi reg,~immediate". Was von der Wirkung her absolut dasselbe ist. Bei den Branch-Instruktionen ging es aber nicht so einfach zu vertuschen, dass viele der angeblichen Instruktionen eigentlich garnicht wirklich existieren, das Dokumentation der Branches im "instruction set reference manual" versucht aber immerhin noch, die Sache möglichst undurchsichtig zu gestalten, so dass man eine Weile braucht, eh' man dahinterkommt, was hier wirklich Phase ist... > So jetzt die Fragen: > Wie unterscheidet die CPU diese Befehle? Garnicht. Sie bekommt sie ja nie zu sehen, weil sie nicht wirklich existieren, sondern nur im Auftrag der Marketingfritzen vorgegaukelte Potjomkinsche Dörfer sind. > Und wie sieht es aus, wenn man das ganze umdreht: > Man hat ein Hex-File das man interpretieren möchte (z.B. ein Emulator). Natürlich düster. Wo es de facto keinen Unterschied gibt, gibt es natürlich auch keine Information im Binärcode. D.h.: du musst die Sache auf den Umfang des tatsächlich verfügbaren reduzieren und dich für eine der möglichen (funktional sowieso absolut gleichwertigen) Quelltextrepresentationen entscheiden.
Ich danke euch :) Das macht es dann doch etwas einfacher. Grüße
c-hater schrieb: >> Es scheinen ein paar Opcodes mehrfach belegt zu sein, z.B. haben die >> ASM-Befehle BRBC und BRCC den selben Opcode. > > Du siehst das unter dem falschen Betrachtungwinkel. Es ist nämlich > einfach nur so, dass Atmel etliche fiktive Instruktionen geschaffen hat, > die es nur auf Asm-Quelltextebene gibt. Der Sinn der Sache war reines > Marketing. Man konnte halt dann in's DB schreiben dass z.B. 112 > Instruktionen unterstützt werden, obwohl es de facto nur 70 oder so > sind. Das ist Blödsinn. Gerade bei den Instruktionen, die der TE zeigt, ist es einfach so, daß die gleiche Konstellation der Flags je nach Kontext verschiedene Bedeutung haben kann. Mnemonics sollen aber gerade einprägsam sein. Dann ist es durchaus logisch und zielführend, zwei verschiedene Mnemonics für die gleiche Operation einzuführen. Und das gab es schon vor den AVR. Beispiel 6502: da gibt es einen bedingten Sprung, der bei gesetztem Carry-Flag genommen wird. Den kann man jetzt wahlweise als
1 | BCS label |
oder
1 | BGE label |
schreiben. Das erste Mal ist es Branch if Carry Set (springe, wenn Carry gesetzt) und man würde es typisch nach einer arithmetischen oder logischen Operation ausführen, wenn man den Überlauf ins Carry-Flag behandeln will. Die zweite Variante meint Branch when Greater or Equal (springe, wenn größer oder gleich) und man würde es typischerweise nach einer arithmetischen Vergleichsoperation ausführen. Der Prozessor würde in jedem Fall das gleiche machen: kucken ob das C-Flag gesetzt ist, und wenn ja, den Sprung ausführen. Und deswegen wird das natürlich auch durch den gleichen Opcode codiert. Ein anderer Kandidat wäre die Operation, ein Register zu löschen. Wenn es bereits einen Opcode gibt, der zwei Register XOR-verknüpft:
1 | XOR r1, r2 |
dann wäre es durchaus sinnvoll, dem Programmierer einen Mnemonic
1 | CLR r1 |
zur Verfügung zu stellen, der intern als
1 | XOR r1, r1 |
codiert ist. Auch hier ist das Ziel nicht das Marketing "meiner hat mehr Opcodes als deiner!!1elf!" sondern die bessere Lesbarkeit des Programmcodes.
Das war jetzt aber etwas fies - mit dem 6502 ausgerechnet einen Prozessor einzuflechten, der bei Subtraktion/Compare das Carry andersrum setzt als AVR. ;-)
>Bei den Branch-Instruktionen ging es aber nicht so einfach zu vertuschen, Deine Antipathie gegen die redundanten Mnemonics finde ich übertrieben. Hersteller von CPUs erfinden solche weder zum Spaß noch in unlauterer Absicht, sondern schlicht, um Assembler-Quelltexte leichter lesbar zu machen (für Menschen). >also wirklich vollständig nutzlose Nein, denn ich benutze die Mnemonics CLR, TST und BREQ etc. - oft und gerne. Damit sind sie für mich (wie für viele andere sicher auch) nicht nutzlos. Schreibst Du wirklich immer "EOR r16, r16" statt "CLR r16" und "AND r16, r16" statt "TST r16"? Den Erklärungen von A. Schwenke schließe ich mich an.
Axel S. schrieb: > Beispiel 6502: da gibt es einen bedingten Sprung, der bei gesetztem > Carry-Flag genommen wird. Den kann man jetzt wahlweise als > BCS label : Branch if Carry Set > oder > BGE label : Branch if Greater or Equal Hier sieht man dass der ARM der 6502 Nachfolger ist, da ist es genauso :-) BCS : Branch if Carry set oder BHS : Branch if Higher or same
A. K. schrieb: > Das war jetzt aber etwas fies - mit dem 6502 ausgerechnet einen > Prozessor einzuflechten, der bei Subtraktion/Compare das Carry andersrum > setzt als AVR. ;-) Heh, das war mir noch gar nicht aufgefallen :) Das macht meine Erklärung ja noch einsichtiger. Denn wenn ich BGE oder BLT (Branch when Less Than) benutze, dann muß ich mich ja genau nicht damit herumschlagen wie herum CMP die Subtraktion [1] macht und ob ich jetzt auf gesetztes oder gelöschtes Carry-Flag testen muß. [1] die meisten Architekturen implementieren den Vergleich (CMP) als Subtraktion, bei der das Ergebnis einfach nirgendwohin gespeichert wird. So gesehen ist der CMP Mnemonic auch redundant.
Axel S. schrieb: > So gesehen ist der CMP Mnemonic auch redundant. Nein, redundant wäre er nur, wenn es beim SUB-Befehl die Option gäbe, das Ergebnis nicht zu speichern.
@ Axel Schwenke (a-za-z0-9) >Das macht meine Erklärung ja noch einsichtiger. Denn wenn ich BGE oder >BLT (Branch when Less Than) benutze, dann muß ich mich ja genau nicht >damit herumschlagen wie herum CMP die Subtraktion [1] macht und ob ich >jetzt auf gesetztes oder gelöschtes Carry-Flag testen muß. Daran erkennt man, daß sogar Assembler eine überaus abstrakte Hochsprache ist ;-) >[1] die meisten Architekturen implementieren den Vergleich (CMP) als >Subtraktion, bei der das Ergebnis einfach nirgendwohin gespeichert wird. >So gesehen ist der CMP Mnemonic auch redundant. Ja, aber mit diesen Details will sich nicht mal der ASM-Programmierer herumschlagen, das kann der Assembler (die Software) deutlich besser. Außer vielleicht Leuten, die PIC-Assembler programmieren 8-0
Zur Carry-Logik: Wenn man such vor Augen hält, daß eine Subtraktion eigentlich auch nur die Addition des negierten (= 2er-Komplement) Wertes ist, finde ich den AVR hier etwas "unlogischer". Bit-Manipulation: Kommt man von Architekturen mit tatsächlich vorhandenen Bit-Set und -Reset Befehlen, fällt man in der Regel erstmal drauf rein, daß beim AVR das Status-Register beeinflusst wird.
:
Bearbeitet durch User
Axel S. schrieb: > Beispiel 6502: da gibt es einen bedingten Sprung, der bei gesetztem > Carry-Flag genommen wird. Den kann man jetzt wahlweise als > BCS label > oderBGE label Hmm, BGE habe ich nie kennengelernt. Welchen Assembler hattest Du denn verwendet. Ich kenne vom 6502 nur: BCC/BCS, BEQ/BNE, BPL/BMI, BVC/BVS. Diese Sprungbefehler bezogen sich alle direkt auf die Flags. Als Assemberproigrammierer da redundante Befehle reinzumogeln finde ich nicht sehr sinnvoll. Wenn ich Assembler programmiere, weiß ich was ich tue. Aber ok, meist hatte ich den 6502 in Maschinensprache programmiert. (Handübersetzt anhand der Op code Liste ;-) ) Gruß Andreas
LostInMusic schrieb: > Schreibst Du wirklich immer "EOR r16, r16" statt "CLR r16" und "AND r16, > r16" statt "TST r16"? <flamewar> Ich persönlich beschäftige mich lieber mit der Aufgabe und überlasse dem Compiler solche Spitzfindigkeiten ;-) </flamewar>
Lurchi schrieb: > Neben den Sprüngen gibt es da noch ein paar andere Spezialfälle die > andere Namen bekommen. Etwa AND mit sich selbst heißt auch TST oder EOR > mit sich selbst als CLR. Selbst der left-Shift ist nur eine Addition eines Registers mit sich selbst.
@ Rolf Magnus (rmagnus) >> Neben den Sprüngen gibt es da noch ein paar andere Spezialfälle die >> andere Namen bekommen. Etwa AND mit sich selbst heißt auch TST oder EOR >> mit sich selbst als CLR. >Selbst der left-Shift ist nur eine Addition eines Registers mit sich >selbst. Wenn es nur um ein Bit ist, ja. Diesen Trick nutzt sogar der avr gcc manchmal. Trotzdem sind es beim AVR verschiedene Op-Codes und im Silizium verschiedene Operationen.
>Trotzdem sind es beim AVR verschiedene Op-Codes und im Silizium verschiedene
Operationen.
Abgesehen davon, dass das H-Flag selten genutzt wird, gibt es
diesbezüglich einen weiteren Unterschied: Bei ADD wird es gegebenenfalls
gesetzt, bei LSL nie.
Falk B. schrieb: > @ Rolf Magnus (rmagnus) > >>> Neben den Sprüngen gibt es da noch ein paar andere Spezialfälle die >>> andere Namen bekommen. Etwa AND mit sich selbst heißt auch TST oder EOR >>> mit sich selbst als CLR. > >>Selbst der left-Shift ist nur eine Addition eines Registers mit sich >>selbst. > > Wenn es nur um ein Bit ist, ja. Der AVR hat nur ein-Bit-Shifts. > Diesen Trick nutzt sogar der avr gcc manchmal. Trotzdem sind es beim AVR > verschiedene Op-Codes und im Silizium verschiedene Operationen. Nein, sind sie nicht. LSL rX und ADD rX,rX sind die selbe Operation. LostInMusic schrieb: > Abgesehen davon, dass das H-Flag selten genutzt wird, gibt es > diesbezüglich einen weiteren Unterschied: Bei ADD wird es gegebenenfalls > gesetzt, bei LSL nie. Auch das stimmt nicht.
:
Bearbeitet durch User
Andreas B. schrieb: > Axel S. schrieb: >> Beispiel 6502: da gibt es einen bedingten Sprung, der bei gesetztem >> Carry-Flag genommen wird. Den kann man jetzt wahlweise als >> BCS label oder BGE label > > Hmm, BGE habe ich nie kennengelernt. Welchen Assembler hattest Du denn > verwendet. Ist lange her. Vermutlich Professional Ass, mit dem habe ich damals das meiste gemacht: http://csdb.dk/release/?id=139650 > Ich kenne vom 6502 nur: > BCC/BCS, BEQ/BNE, BPL/BMI, BVC/BVS. > Diese Sprungbefehler bezogen sich alle direkt auf die Flags. Schon klar. Ich hatte ursprünglich eigentlich etwas anderes im Gedächtnis und jetzt ist es mir wieder eingefallen: Z8 Assembler. Da gibt es für bedingte Sprünge auch redundante Mnemonics. Z.B. JRZ == JREQ und JRNZ == JRNE. Mit (N)Z für (Non)Zero und EQ/NE für EQual/Not Equal. Das JR steht für Jump Relative. Für die Carry-bedingten Sprünge gab es auch jeweils zwei Varianten.
>Auch das stimmt nicht.
OK, Punkt für Dich - der Simulator im AVRStudio hat die Frage zu Deinen
Gunsten entschieden. Zur Entschuldigung meines Irrtums verweise ich auf
die Instruction Set Summaries in den Datenblättern zum ATmega8/16/32 +
88/168/328 + 13 + 25/45/85 (mehr habe ich mir nicht angesehen). Darin
ist nämlich die LSL-Instruktion offensichtlich falsch beschrieben (*).
Wer ahnt denn sowas? :-( Die Angaben im Atmel Instruction Set und in der
Doku zum AVRAssembler sind dagegen korrekt.
(*)
Der Eintrag für LSL in den Instruction Set Summaries lautet (Operation
und beeinflusste Flags):
Rd(n+1) ← Rd(n), Rd(0) ← 0
Z,C,N,V
Richtig wäre:
Rd ← Rd + Rd
Z,C,N,V,H
@ Rolf Magnus (rmagnus) >> Diesen Trick nutzt sogar der avr gcc manchmal. Trotzdem sind es beim AVR >> verschiedene Op-Codes und im Silizium verschiedene Operationen. >Nein, sind sie nicht. LSL rX und ADD rX,rX sind die selbe Operation. Tatsache! Hätte ich nicht gedacht. >> Abgesehen davon, dass das H-Flag selten genutzt wird, gibt es >> diesbezüglich einen weiteren Unterschied: Bei ADD wird es gegebenenfalls >> gesetzt, bei LSL nie. >Auch das stimmt nicht. Naja, also ist auch die elementar erscheinende Funktion lsl ein Pseudo-ASM Befehl!!!!
Falk B. schrieb: >>Nein, sind sie nicht. LSL rX und ADD rX,rX sind die selbe Operation. > > Tatsache! Hätte ich nicht gedacht. Um noch das Letzte zu ergänzen: ROL Rn = ADC Rn,Rn
Axel S. schrieb: > Gerade bei den Instruktionen, die der TE zeigt, ist es einfach so, daß > die gleiche Konstellation der Flags je nach Kontext verschiedene > Bedeutung haben kann. Mnemonics sollen aber gerade einprägsam sein. Und einprägen kann man sich was wohl besser: kleine Listen von Memnonics oder große Listen? Das was du meinst, ist was ganz anderes. Und es hilft nur Leuten, die mit der binären Mathematik auf Kriegsfuss stehen und deswegen nicht die Semantik erfassen, die die Operation an gerade der Stelle des Codes hat, an der sie steht. Und selbst denen hilft es nicht wirklich, denn den ganzen Zauber der Pseudoinstruktionen könnte man genausogut mit Makros abhandeln, das muss nicht in den Assembler selber rein, da hätte der Hersteller auch einfach einen Set entsprechender Makros mitliefern können, wenn seine primäre Intention tatsächlich nur gewesen wäre, unbedingt den Usern helfen zu wollen. Dann hätten die, die es brauchen oder für nützlich halten, einfach diese Makros benutzen können. Und alle anderen hätten es eben einfach nicht getan. Oder ihre eigenen Makrosets verwendet... Aber dann hatten sie eben die Zahl der tatsächlich unterstützten Instruktionen in's DB schreiben müssen, was marketingtechnisch halt nicht so gut gekommen wäre... > Beispiel 6502: da gibt es einen bedingten Sprung, der bei gesetztem > Carry-Flag genommen wird. Den kann man jetzt wahlweise als > >
1 | > BCS label |
2 | > |
> oder >
1 | > BGE label |
2 | > |
> > schreiben. Unsinn. Zufällig hatte ich mal einen Atari800XL, den ich natürlich auch in Assembler programmiert habe. Und das Gute war bei dem Ding gerade, dass eine 1:1-Beziehung zwischen Mnemnonic und OpCode bestand. Ähem, eigentlich was das aber auch schon fast das einzig Gute an der Architektur. Trotzdem habe ich das Ding damals mit Begeisterung beackert. Naja, gerade beim 8Bit-Atari war ja auch nicht die CPU der Kracher, sondern die Fähigkeiten der Custom-Chips. So ähnlich wie später beim Amiga. Wobei ich den 68k doch schon sehr nett fand, kein Vergleich mit der 6502-Gurke des Atari. War bloss ein wenig niedrig getaktet und in den tatsächlich verbreiteten Systemen auch noch zusätzlich durch den langsamen RAM ausgebremst, bei dem er sich die Bandbreite mit den Custom-Chips teilen musste. Gab's eigentlich beim 68k-Assembler solche redundanten Pseudo-Instruktionen? Kann mich nicht mehr 100%ig erinnern, aber ich bin fast sicher: nein, diesen Schwachsinn gab es dort auch nicht.
Thomas E. schrieb: > Zur Carry-Logik: Wenn man such vor Augen hält, daß eine Subtraktion > eigentlich auch nur die Addition des negierten (= 2er-Komplement) Wertes > ist, finde ich den AVR hier etwas "unlogischer". Sieh es so: AVR addiert das Zweierkomplement, 6502 das Einerkomplement.
c-hater schrieb: > Und einprägen kann man sich was wohl besser: kleine Listen von Memnonics > oder große Listen? Weder noch: Logische Listen von Mnemonics. Mich interessiert es nicht, wie ADD, SUB oder CMP mit Carry/Overflow umgehen, daher möchte ich einen Satz Branch-Mnemonics für Arithmetik (größer/kleinergleich, signed/unsigned) und einen Satz Branch-Mnemonics für die Flags. Und wenn man sich die Mnemonics jederzeit herleiten kann, weil der Assembler alle Möglichkeiten kennt, dann brauche ich mir die auch nicht einprägen. > Zufällig hatte ich mal einen Atari800XL, den ich natürlich auch > in Assembler programmiert habe. Und das Gute war bei dem Ding gerade, > dass eine 1:1-Beziehung zwischen Mnemnonic und OpCode bestand. Das hängt schlicht von deinem Assembler ab. Verschiedene Assembler haben verschiedene Mnemonics, auch auf der gleichen/kompatiblen Architektur (vgl. 8085- vs. Z80-Mnemonics, Intels 8086-Assembler im 8085-Kompatiblitätsmodus, oder Intel vs. AT&T auf x86). > Gab's eigentlich beim 68k-Assembler solche redundanten > Pseudo-Instruktionen? Kann mich nicht mehr 100%ig erinnern, > aber ich bin fast sicher: nein, diesen Schwachsinn > gab es dort auch nicht. Wenn das Instruktion Set vollkommen orthogonal ist, dann hast du sogar verschiedene Opcodes (und damit verschiedene Mnemonics) für die gleiche Funktionalität...
:
Bearbeitet durch User
>ROL Rn = ADC Rn,Rn
Dann dürfte das die komplette (?) Liste sein:
1 | CLR (→ EOR) |
2 | SER (→ LDI) |
3 | |
4 | SBR (→ ORI) |
5 | CBR (→ ANDI) |
6 | |
7 | LSL (→ ADD) |
8 | ROL (→ ADC) |
9 | |
10 | TST (→ AND) |
11 | |
12 | SEC, SEN, SEZ, SEI, SES, SEV, SET, SEH (→ BSET) |
13 | CLC, CLN, CLZ, CLI, CLS, CLV, CLT, CLH (→ BCLR) |
14 | |
15 | BREQ, BRCS, BRSH, BRMI, BRGE, BRHS, BRTS, BRVS (→ BRBS) |
16 | BRNE, BRCC, BRLO, BRPL, BRLT, BRHC, BRTC, BRVC (→ BRBC) |
LostInMusic schrieb: > Dann dürfte das die komplette (?) Liste sein: Fast: BRCS = BRLO BRCC = BRSH BRCS/LO, BREQ, BRMI, BRVS, BRLT, BRHS, BRTS, BRIE (→ BRBS) BRCC/SH, BRNE, BRPL, BRVC, BRGE, BRHC, BRTC, BRID (→ BRBC)
Schon witzing, worüber sich Atmel so Gedanken gemacht hat. Schlimmer, worüber man sich keine Gedanken gemacht hat: Es geht hierbei um die Befehle: LD, LDI, ST, MOV, OUT, IN Hier wäre es meiner Meinung nach wichtig gewesen, dass der Assembler dies dem Programmierer gegenüber mit nur einem Befehl abbildet. Der 8051 hat es mit MOV vorgemacht. Der Assembler entscheidet anhand der Quellen/Ziele, welcher Maschinenbefehl benutzt wird. Gruß Jobst
Dann gibt es also insgesamt 7 + 2·8 + 2·9 = 41 Alias-Mnemonics:
1 | CLR (→ EOR) |
2 | SER (→ LDI) |
3 | |
4 | SBR (→ ORI) |
5 | CBR (→ ANDI) |
6 | |
7 | LSL (→ ADD) |
8 | ROL (→ ADC) |
9 | |
10 | TST (→ AND) |
11 | |
12 | SEC, SEN, SEZ, SEI, SES, SEV, SET, SEH (→ BSET) |
13 | CLC, CLN, CLZ, CLI, CLS, CLV, CLT, CLH (→ BCLR) |
14 | |
15 | BRCS/LO, BREQ, BRMI, BRVS, BRLT, BRHS, BRTS, BRIE (→ BRBS) |
16 | BRCC/SH, BRNE, BRPL, BRVC, BRGE, BRHC, BRTC, BRID (→ BRBC) |
Das Instruction Set Summary des ATMega 48/88/168 listet genau 111 Mnemonics auf (wenn man die Varianten von LD, LDD, ST, STD und LPM nur einmal zählt). Damit beläuft sich der Anteil der redundanten auf ca. 37 %.
c-hater schrieb: > Aber dann hatten sie eben die Zahl der tatsächlich unterstützten > Instruktionen in's DB schreiben müssen, was marketingtechnisch halt > nicht so gut gekommen wäre... Also ich hab ja schon so manche Verschwörungstheorie gehört, aber das ist dann doch arg albern. Du glaubst allen Ernstes, dass Atmel sich mehrere Namen für die gleiche Instruktion ausgedacht hat, damit mehr Leute den AVR gegenüber anderen Architekturen bevorzugen, weil er mehr Instruktionen kennt? Offenbar hast du keine Ahnung, nach welchen Kriterien Entwickler ihre µCs auswählen. > Unsinn. Zufällig hatte ich mal einen Atari800XL, den ich natürlich auch > in Assembler programmiert habe. Und das Gute war bei dem Ding gerade, > dass eine 1:1-Beziehung zwischen Mnemnonic und OpCode bestand. Das wäre jetzt auf meiner Liste der "Features" einer CPU-Architektur so ziemlich das letzte, was mich diese gegenüber einer anderen bevorzugen ließe. Jobst M. schrieb: > Schon witzing, worüber sich Atmel so Gedanken gemacht hat. > Schlimmer, worüber man sich keine Gedanken gemacht hat: > > Es geht hierbei um die Befehle: LD, LDI, ST, MOV, OUT, IN > Hier wäre es meiner Meinung nach wichtig gewesen, dass der Assembler > dies dem Programmierer gegenüber mit nur einem Befehl abbildet. Der 8051 > hat es mit MOV vorgemacht. Ist beim x86 ja auch so. Da fand ich das aber irgendwie blöd, dass bestimmt ein Dutzend eigentlich verschiedene Befehle alle den selben Namen hatten.
c-hater schrieb: >> Beispiel 6502: da gibt es einen bedingten Sprung, der bei gesetztem >> Carry-Flag genommen wird. Den kann man jetzt wahlweise als >> >>
1 | >> BCS label |
2 | >> |
>> oder >>
1 | >> BGE label |
2 | >> |
>> >> schreiben. > > Unsinn. Zufällig hatte ich mal einen Atari800XL, den ich natürlich auch > in Assembler programmiert habe. Tja, hättest Du mal ein bisschen gespart und Dir einen Apple ][ geleistet. Da hat eigentlich jeder Assembler BLT (Branch on Less Than) and BGE (Branch on Greater than or Equal) als Synonym für BCC und BCS akzeptiert. Und Apple hat diese in ihren Quellcodes (die damals ja noch in den Handbüchern abgedruckt waren) auch verwendet.
Jobst M. schrieb: > Hier wäre es meiner Meinung nach wichtig gewesen, dass der Assembler > dies dem Programmierer gegenüber mit nur einem Befehl abbildet. Die sind aber unterschiedlich schnell. Zudem ist es grundlegende Charakteristik einer RISC & Load-Store-Architektur, dass die eben nicht gleich sind, und man für Speicher Zugriffe extra Befehle.hat.
Dr. Sommer schrieb: > Die sind aber unterschiedlich schnell. Zudem ist es grundlegende > Charakteristik einer RISC & Load-Store-Architektur, dass die eben > nicht gleich sind, und man für Speicher Zugriffe extra Befehle.hat. Ich denke, Du hast die Problematik nicht verstanden, denn der Controller sieht ja gar keinen Unterschied. Es geht um den Assembler. Das Programm auf dem PC, welches Dein Programm in Maschinenbefehle umsetzt. Ich finde, dieses sollte mir die Arbeit abnehmen, aus MOV PORTD, R3 -> OUT PORTD, R3 MOV R16, #7 -> LDI R16, 7 MOV TWSR, temp -> STS TWSR, temp MOV R3, R4 -> MOV R3, R4 zu machen. Gruß Jobst
Jobst M. schrieb: > denn der Controller sieht ja gar keinen Unterschied. Zumindest der AVR Controller sieht einen dramatischen Unterschied zwischen mov, ldr, in. Und dieser wird nunmal auch in der Assembler Sprache abgebildet, genau wie beim ARM. Nicht zuletzt um zu sehen welche der grundverschiedenen Instruktionen genutzt werden und somit wie schnell diese sind... Zumal kann man auch Zahlen statt der Register/Adress Aliase übergeben, und dann ist völlig unklar welche Instruktion jetzt tatsächlich gemeint ist. Aber anstelle über so etwas zu diskutieren kann man auch einfach richtige Programmiersprachen wie C++ benutzen und so einen Unsinn dem Compiler überlassen.
Dr. Sommer schrieb: > Aber anstelle über so etwas zu diskutieren Was machst Du dann hier? Du hast es immernoch nicht verstanden. Gruß Jobst
Man kann unterschiedliche Operanden-Typen einer gleichartigen Operation über verschiedene Mnemonics unterscheiden (8080 Assembler), oder über verschiedene Darstellungen der Operanden (Z80 Assembler). An den Befehlen ändert das nichts. Und wie üblich wird es unterschiedliche Geschmäcker geben. Also ob man es lieber für jeden Opcode getrennt hat, oder vereinheitlicht.
A. K. schrieb: > Und wie üblich wird es unterschiedliche > Geschmäcker geben. Also ob man es lieber für jeden Opcode getrennt hat, > oder vereinheitlicht. Jo, und es läßt sich schon vortrefflich darüber streiten, ob ein Register in ein anderes kopieren, einen Immediate-Wert in ein Register laden und ein Speicherzugriff als gleichartige Operationen gelten sollten oder nicht. Wem die verschiedenen Mnemonics zu viel sind, der kann ja einen OISC-Prozessor nehmen ;-) https://en.wikipedia.org/wiki/One_instruction_set_computer
Rolf M. schrieb: > Wem die verschiedenen Mnemonics zu viel sind, der kann ja einen > OISC-Prozessor nehmen ;-) > https://en.wikipedia.org/wiki/One_instruction_set_computer Dafür kann man dann ja Makros schreiben. ;-) Gruß Andreas
Kaj G. schrieb: > Es scheinen ein paar Opcodes mehrfach belegt zu sein, z.B. haben die > ASM-Befehle BRBC und BRCC den selben Opcode. Kann es sein das die Begriffe Mnemonic und Opcode verwechselst? Assemblersprache und OpCode ist nicht dasgleiche. Schau mal: https://de.wikipedia.org/wiki/Assemblersprache#Beschreibung
C. A. Rotwang schrieb: > Kann es sein das die Begriffe Mnemonic und Opcode verwechselst? Nein. Lass es mich anders formulieren: Aus Mnemonic A wird Opcode X erzeugt. Aus Mnemonic B wird ebenfalls Opcode X erzeugt. Sprich: Ein Opcode wird von zwei oder mehr Mnemonics belegt -> doppelte/mehrfache belegung des Opcodes.
Kaj schrieb: > Ein Opcode wird von zwei oder mehr Mnemonics belegt -> > doppelte/mehrfache belegung des Opcodes. "Orange" und "Apfelsine" sind zwei Mnemonics für die gleiche Frucht. Deswegen ist die Frucht noch lange nicht doppelt belegt.
>"Orange" und "Apfelsine" sind zwei Mnemonics für die gleiche Frucht. >Deswegen ist die Frucht noch lange nicht doppelt belegt. Ähhh......? <irritiertbin> Was verstehst Du denn dann unter einer Namens-Doppelbelegung? Kannst Du mal ein Beispiel angeben, wo Deiner Meinung nach irgendwas durch Namen/Mnemonics doppelt belegt ist?
S. R. schrieb: > "Orange" und "Apfelsine" sind zwei Mnemonics für die gleiche Frucht. > Deswegen ist die Frucht noch lange nicht doppelt belegt. Im Sinne des TO schon. Exakt darum ging es -- zwei verschiedene Namenswörter beschreiben den gleichen Zustand.
Hallo, ASM-Mnemotics sind Merkhilfen. Die CPU-hersteller haben für Ihre Assembler versucht, möglichst merkbare Abkürzungen zu finden. Kurz mußten sie auch noch sein, Speicherplatz für den Sourcecode war knapp. 65xx und Z80 sind da eben völlig verscheidene Wege gegangen. Bei waren Merkbar, man hat sich daran gewöhnt. Ob LDI für load immediate nun merkbarer ist als LD für load und das nachschauen, was geladen wird weil # vor dem Operanden steht, mag jeder selbst entscheiden. mov hat mich eigentlich immer gestört, war bei mir gedanklich immer näher an verschieben als an kopieren. Wenn ich scheiben oder rotieren will, will ich einen ROL, ROR, LSL usw. haben und mir nicht den Kopf darüber zerbrechen, ob es mit EOR x,x oder ADD x,x ober SUB x,x ja auch ginge. Naja, inzwuschen muß man ja eher auf Klammerei und vergessene Semikolon achten. ;) Gruß aus Berlin Michael
Michael U. schrieb: > Wenn ich scheiben oder rotieren will, will ich einen ROL, ROR, LSL usw. > haben und mir nicht den Kopf darüber zerbrechen, ob es mit EOR x,x oder > ADD x,x ober SUB x,x ja auch ginge. Vor Allem will ich aber beim ROL oder ASL auch nur Z und C beeinflusst wissen, und nicht irgenwelche anderen Nebenwirkungen, die noch nicht mal im Datenblatt stehen! (Super, ATMEL!)
Michael U. schrieb: > Die CPU-hersteller haben für Ihre Assembler versucht, möglichst merkbare > Abkürzungen zu finden. Nicht immer. NEC hat für die V20/30/... Varianten von Intels 8086er Serie einen komplett eigenen Befehlssatz ersonnen, was Mnemonics und Registernamen betrifft. Möglicherweise aus Sorge um Urheberrecht, oder sowas in der Art. Hat natürlich nie jemand genutzt, aber das musste offenbar mit Gewalt anders sein. Zilog hatte sich davor auch schon bemüht, sich von Intels 8080 Bezeichnungen abzuheben. Hier sind die Motive nicht ganz so eindeutig, weil das Ergebnis summarum klar besser ist. Aber wer nennt einen Store-Befehl schon Load (LD), wenn ihm kein Anwalt im Genick sitzt? > Wenn ich scheiben oder rotieren will, will ich einen ROL, ROR, LSL usw. > haben Wobei ROL/ROR etwas hakt, weil sich aus dem Mnemonic nicht erschliesst, ob das Carry-Flag Teil der Runde ist oder nicht. Das ist je nach CPU mal so mal so.
@ Thomas Elger (picalic) >Vor Allem will ich aber beim ROL oder ASL auch nur Z und C beeinflusst >wissen, und nicht irgenwelche anderen Nebenwirkungen, die noch nicht mal >im Datenblatt stehen! (Super, ATMEL!) Welche denn? Das H-Flag, da so oder so bestenfalls in hömiopatischen Dosen für BCD-Arithmetik genutzt wird?
Thomas E. schrieb: > Vor Allem will ich aber beim ROL oder ASL auch nur Z und C beeinflusst > wissen, Mit solcher Minimalistik hatte sich Intel gründlich in die Scheisse geritten. Es ist schon schlimm genug, dass jeder Befehl einen anderen Set aus insgesamt 3 Flag-Gruppen beeinflusst. Aber um das Mass voll zu machen sind die auch auf die exquisit bescheuerte Idee verfallen, ein Flag bei Shifts nur dann zu verändern, wenn die Anzahl nicht 0 ist. Denn sobald man Befehle nicht mehr streng im Gänsemarsch ausführt, wächst die Komplexität der Flagverarbeitung durch solche Mätzchen massiv an und man erhält unbeabsichtigte Abhängigkeiten von Befehlen. Das hat beispielsweise alten Code beim Pentium 4 bös verlangsamt und mancher x86 hat bei Shifts mit n=0 den Befehl gleich zweimal ausgeführt - das erste Mal in der Annahme n!=0 und das zweite mal viel langsamer aber richtig. Also wenn schon Flags, dann alle oder keines, wenn man nicht bloss bis zum nächsten Laternenmast denkt.
:
Bearbeitet durch User
Michael U. schrieb: > Wenn ich scheiben oder rotieren will, will ich einen ROL, ROR, LSL usw. > haben... Wenn ich etwas bei den Assemblermnemonics vermisse, dann sind es ROFL und LOL. :) MfG Paul
Paul B. schrieb: > Wenn ich etwas bei den Assemblermnemonics vermisse, dann sind es ROFL > und LOL. Tröste dich, beim 1802 und den 6800ern gibt es dafür SEX! Aber das waren eben die liberalen 70er, da konnte man noch.
:
Bearbeitet durch User
Kaj schrieb: > C. A. Rotwang schrieb: >> Kann es sein das die Begriffe Mnemonic und Opcode verwechselst? > Nein. > > Lass es mich anders formulieren: > Aus Mnemonic A wird Opcode X erzeugt. > Aus Mnemonic B wird ebenfalls Opcode X erzeugt. > > Sprich: > Ein Opcode wird von zwei oder mehr Mnemonics belegt -> > doppelte/mehrfache belegung des Opcodes. Nein aus einem Mnemonic wird nichts erzeugt, du darfst das nicht mit einem Compiler verwechseln. Etwas Geschichte: Bei den ersten CPUS würde nicht mit assembler gearbeitet sondern direkt gecodet. Mit einem Monitorprogramm hat man die Programmcode - die Hexzahlen an die gewünschte Speicheraddressen geschrieben. Es war im ROM und RAM einfach nicht genüg Platz für einen Assembler. Die Mnemonics hat man nur verwendet um den Code in lesbarer Form festzuhalten. Die Programmierer damals haben den code dann per tabelle (reference card) oder im Kopf umgesetzt . Beispiel für eine solche Tabelle dort: http://www.ballyalley.com/ml/z80_docs/Z80_Instant_Reference_Card.pdf Zu dieser Zeit war ein "aufgeräumter" Befehlssatz und gute Mnemonics extrem wichtig, denn nur so kann man Fehlerarm im Kopf assemblieren. Irgendwo hab ich mal von einen Prozessor gelesen, dessen Vorteil gegenüber den Vorgänger in einer Änderung der Memonic betstands. Deteils find ich grad nicht, vielleicht war es die Trennung von alles MOV auf MOV und LOAD je nach Quelloperand (register oder Mem subsystem) was es deutlich einfacher macht die Ausführungszeit der Code-abschnitte abzuschätzen. Irgendwann hatte man die Hardware für brauchbare Assembler, insbesonders die sogenannten Makro-assembler. Daraus hat sich dann eine Assemblersprache entwickelt die im gewissen Sinne Architektur-unabhängig ist. beispielsweise GNU-Assembler https://sourceware.org/binutils/docs/as/GNU-Assembler.html#GNU-Assembler Bei denen besteht nun die Möglichkeit die operation etwas "allgemeiner" und leicht verständlicher zu formulieren". Man muss nun also nicht mehr wissen, od der Prozesor "Bit - set" oder "bit clear" oder "bit - load" oder "AND -immediate" Operationen unterstützt. Der Cross-Platform assembler bastelt selbst daraus die passenden Codes. Der Opcode ist also keinesfalls mehrfach belegt wie im Sinne einer mehrfachen Tastbelegung (je nach Context (Status SHIFT/WIN/Ctrl/ALTGr-Taste) andere "ergebniss"). Es wird (beim AVR) immer der selbe Opcode auf die selbe Weise ausgeführt egal wie der Mnemonic dazu lautet. (Einschränkung: es gibt allerdings prozessoren bei denen der OPcode contextabhängig unterschiedlich ausgeführt wird, beispiels priviliegierte Befehle die im Supervisor-mode ordentlich abgearbeitet werden, aber im User-Mode zu eine Exception führen - da )
C. A. Rotwang schrieb: > Nein aus einem Mnemonic wird nichts erzeugt, du darfst das nicht mit > einem Compiler verwechseln. Ein Assembler erzeugt aus einem Mnemonic einen Opcode. Genau dafür ist er da. Du tippst in Deiner Assembler-Source die Mnemonics "MOV Status1, A" ein und der Assembler erzeugt daraus im Hexfile den Opcode "F5 35". Und selbstverständlich kann man für einen Opcode mehrere verschiedene Mnemoics verwenden. Es gibt sogar Assembler, die Macro-Definitionen erlauben. Da kannst Du den MOV-Befehl Horst und den JMP-Befehl Uwe nennen. Und Horst und Uwe liefern trotzdem die gleiche Opcodes im Hexfile wie MOV und JMP.
A. K. schrieb: > Paul B. schrieb: >> Wenn ich etwas bei den Assemblermnemonics vermisse, dann sind es ROFL >> und LOL. > > Tröste dich, beim 1802 und den 6800ern gibt es dafür SEX! > Aber das waren eben die liberalen 70er, da konnte man noch. Da musst Du jetzt aber sehr traurig sein.
soul e. schrieb: > Und selbstverständlich kann man für einen Opcode mehrere > verschiedene Mnemoics verwenden. Es gibt sogar Assembler, > die Macro-Definitionen erlauben. Da kannst Du den MOV-Befehl > Horst und den JMP-Befehl Uwe nennen. Und Horst und Uwe > liefern trotzdem die gleiche Opcodes im Hexfile wie MOV > und JMP. Genau deshalb ist die Ursprungsfrage unsinnig. Die CPU muss nix unterscheiden, denn sie soll ja immer genau das gleiche machen. Da die genau gleiche Operation aber in unterschiedlichem Kontext verschiedene Bedeutung haben kann, möchte der Mensch der Bedeutung angepasste - also verschiedene - Namen für dieselbe Sache haben.
soul e. schrieb: > C. A. Rotwang schrieb: > >> Nein aus einem Mnemonic wird nichts erzeugt, du darfst das nicht mit >> einem Compiler verwechseln. > > Ein Assembler erzeugt aus einem Mnemonic einen Opcode. Genau dafür ist > er da. Ich beziehe mich auf die Zeit vor dem Assembler, Mnemonics gab es bereits bevor es Assembler gab. Mnemonics und assembler code code ist in meiner Betrachtung nicht dasselbe, insbesnonders wenn man den Schritt zu crossplattform assembler macht. Der feine Unterschied zwischen Mnemonics wird von Jungspunden die einen Hex-Monitor nicht von einem 4k-Monitor unterscheiden können, gern missachtet.
Falk B. schrieb: > Welche denn? Das H-Flag, da so oder so bestenfalls in hömiopatischen > Dosen für BCD-Arithmetik genutzt wird? Echte Assemblerprogrammierer nutzen das Halfcarry natürlich immer dann, wenn es sich zur Nutzung förmlich anbietet. Und das passiert auch abseits der BCD-Arithmetik durchaus des öfteren mal... Manchmal ist es sogar so: Man organisiert Daten absichtlich so, dass das H-Flag sich taktsparend einsetzen läßt. Typisches Beispiel hierfür wären DoubleBuffer-Mechanismen mit Buffern <= 16 Elementen. Nicht gerade selten und obendrein recht häufig im exklusiven Teil von ISRs verwendet, wo jeder einzelne verschissene gesparte Takt vielfach zählt, weil er die Performance und Latenz des Gesamtsystems runterzieht. Aber ja, für Heizungsteuerungen u.ä. kann man auch problemlos drauf verzichten...
Thomas E. schrieb: > Michael U. schrieb: >> Wenn ich scheiben oder rotieren will, will ich einen ROL, ROR, LSL usw. >> haben und mir nicht den Kopf darüber zerbrechen, ob es mit EOR x,x oder >> ADD x,x ober SUB x,x ja auch ginge. > > Vor Allem will ich aber beim ROL oder ASL auch nur Z und C beeinflusst > wissen, Warum? > und nicht irgenwelche anderen Nebenwirkungen, die noch nicht mal im > Datenblatt stehen! (Super, ATMEL!) Das ist alles haarklein im AVR Instruction Set Manual beschrieben. Atmel hat sich nur dagegen entschieden, dessen Inhalt komplett in jedes einzelne Datenblatt zu kopieren - in der Annahme, die Benutzer wären intelligent genug, das auch so zu finden.
Ok, WELCHE Flags beeinflusst werden sollten oder nicht, scheint jeder etwas anders zu sehen. Für mich wäre ein Schiebe-Befehl eben in erster Linie ein Schiebebefehl und keine Addition mit sich selbst. Wenn Atmel meint, den Additionsbefehl dafür verwenden zu müssen, um Opcodes zu sparen, habe ich aber nichts degegen, wenn sie es RICHTIG dokumentieren. Rolf M. schrieb: > Das ist alles haarklein im AVR Instruction Set Manual beschrieben. Atmel > hat sich nur dagegen entschieden, dessen Inhalt komplett in jedes > einzelne Datenblatt zu kopieren - in der Annahme, die Benutzer wären > intelligent genug, das auch so zu finden. Dann sollten sie es konsequent aus dem Datenblatt 'raushalten, statt in jedem einzelnen Datenblatt eine offenbar falsche Kombination an beeinflussten Status-Flags anzugeben. Als Entwickler möchte ich mich auf gemachte Angaben in der original-Doku des Herstellers verlassen können und nicht an verschiedenen Stellen suchen müsen, ob da noch etwas anderes steht!
Thomas E. schrieb: > Dann sollten sie es konsequent aus dem Datenblatt 'raushalten, statt in > jedem einzelnen Datenblatt eine offenbar falsche Kombination an > beeinflussten Status-Flags anzugeben. Ich hab mal exemplarisch das vom ATMEGA8 geöffnet, und da scheint bei mehreren Instruktionen die Liste der beeinflussten Flags fehlerhaft zu sein. Du hast natürlich recht, dass das nicht so sein sollte.
Etwas befremdlich finde ich auch, daß in der Befehlsreferenz bei Befehlen, wie "BRLT", "BRGE" usw., knallhart vorgegaukelt wird, der Befehl würde das N und V Flag miteinander verknüpfen. In Wahrheit wird aber natürlich nur das S-Flag geprüft. Ich würde mir von einer Referenz eher technische Fakten wünschen, als diese Verschleierung...
C. A. Rotwang schrieb: > Ich beziehe mich auf die Zeit vor dem Assembler, Mnemonics gab es > bereits bevor es Assembler gab. Dann erklär mal einem Jungspund die Steinzeit, bitte. Meine Welt sagt: Ein Opcode beschreibt einen Befehl der CPU, und ein Mnemonic ist eine menschenfreundliche Merkhilfe für diesen Opcode. "NOP" ist einfacher zu merken als "F9" und kürzer als "No OPeration". > Mnemonics und assembler code code ist in meiner Betrachtung nicht > dasselbe, insbesnonders wenn man den Schritt zu > crossplattform assembler macht. Was soll denn bitte Crossplattformassembler sein? Der kleinste gemeinsame Nenner aus Z80, x86 und 6502?
S. R. schrieb: > Was soll denn bitte Crossplattformassembler sein? Das nennt sich sehr prägnant "C". SCRN. :-)
S. R. schrieb: > Was soll denn bitte Crossplattformassembler sein? Der kleinste > gemeinsame Nenner aus Z80, x86 und 6502? Es gab Compiler, welche Maschinencode von CPU A auf Maschinencode vom CPU B übersetzten. Gruß Jobst
Jobst M. schrieb: > Es gab Compiler, welche Maschinencode von CPU A auf Maschinencode vom > CPU B übersetzten. Maschinencode != Assembler. Als dynamic code translation ist das sehr aktuell. Beim 8086 gab es die Möglichkeit, 8080 Asm-Code auf 8086 Code umzusetzen, weil die 8086 passend gebaut war. Weiss aber nicht, ob das ein Asm war, oder ein Umsetzprogramm auf Quelltextebene Ein Assembler, der die Befehle auf verschiedene Zielmaschinen umsetzt, ist aber allenfalls dort sinnvoll, wo eine enge Verwandschaft besteht. Also die exakt gleichen Befehle in verschiedenen Modellen unterschiedlich codiert sind.
:
Bearbeitet durch User
A. K. schrieb: > Also die exakt gleichen Befehle in verschiedenen Modellen > unterschiedlich codiert sind. Etwas komplexer war das schon ... Eine einfache 1:1 Umsetzung war das nicht. Wenn auf der Zielplattform für die selbe Aufgabe 2 Befehle nötig waren, welche auf der Quellplattform mit nur einem Befehl erledigt wurde, dann wurden das eben 2 Befehle. Und umgekehrt. Gruß Jobst
S. R. schrieb: > C. A. Rotwang schrieb: > Was soll denn bitte Crossplattformassembler sein? Der kleinste > gemeinsame Nenner aus Z80, x86 und 6502? Der Gnu-assembler ist beispielsweise ein crossplattformassembler, er er verwndwt sog. Pseudo-Ops und direktiven für Architekturabhängigkeiten (machine-dependencies) https://sourceware.org/binutils/docs/as/GNU-Assembler.html#GNU-Assembler Bei ARM ist es nicht viel anders, anders als allgemein bekannt gibt es über die verschiedenen ARM-familien erhebliche Unterschiede in der Architektur, oder alternative Befehlssätze (THUMB) deshalb hat sich ARM die Unified Assembly Language -> UAL einfallen lassen. Ein crossplatform asembler verwendet also im Kern einen Assemblersprache die sich auf die jeweiligen instruction sets 1:1 abbilden lässt plus direktiven für die maschinen-extras. das Userinterface (bspw. command line options/Fileformate) ist auch möglichst gleich. Das kann mensch beispielsweise ganz gut an den GNU-toolchains für avr und arm sehen.
S. R. schrieb: > C. A. Rotwang schrieb: >> Ich beziehe mich auf die Zeit vor dem Assembler, Mnemonics gab es >> bereits bevor es Assembler gab. > > Dann erklär mal einem Jungspund die Steinzeit, bitte. Die Jugend lässt sich nach meiner Erfahrung nichts erklären, die Jugend nutz google oder stirb dumm. Also schlau machen musst du dich schon selber, genügend Literatur zu Thema Computerarchitektur gibt es. Mein Empfehlung Patterson, Hennessy, > > Meine Welt sagt: Ein Opcode beschreibt einen Befehl der CPU, und ein > Mnemonic ist eine menschenfreundliche Merkhilfe für diesen Opcode. "NOP" > ist einfacher zu merken als "F9" und kürzer als "No OPeration". Schau dir einfach mal einen Arithmetik befehl und die möglichen adressierungen an, dann sollte klar werden das das Mnemonic mehr ist als eine Merkhilfe sondern eine Menge über die zugrundeliegende Architektur verrät (addressierung der Register) mit einen gut formulierten memonic kann man sich die Instruction gut im Kopf zusammenbassteln, fiktives Beispiel MOV r1, r15 -> "101010" "00" "0001" "1111" -> 651f; also OpCode für Move & Befehlsmodifikator & Adresse dest & Adresse source
S. R. schrieb: > Dann erklär mal einem Jungspund die Steinzeit, bitte. https://en.wikipedia.org/wiki/MIX Sieht aus wie ein Aprilscherz, war aber keiner. Noch Anfang der 80er war das ein gängiger Weg, Inf-Studenten Assembler beizubringen. Das Teil ist frühen Architekturen durchaus nahe, also circa jenen vor IBM 360. Die bin/dez Doppelnatur widerspiegelt das, denn es gab anfangs beides, binäre und dezimale Maschinen. Der erste in relativ grossen Stückzahlen verkaufte Computer war dezimal (IBM 650), obwohl bereits Zuse binär arbeitete.
:
Bearbeitet durch User
C. A. Rotwang schrieb: >> Meine Welt sagt: Ein Opcode beschreibt einen Befehl der CPU, und ein >> Mnemonic ist eine menschenfreundliche Merkhilfe für diesen Opcode. "NOP" >> ist einfacher zu merken als "F9" und kürzer als "No OPeration". > > Schau dir einfach mal einen Arithmetik befehl und die möglichen > adressierungen an, dann sollte klar werden das das Mnemonic mehr ist als > eine Merkhilfe sondern eine Menge über die zugrundeliegende Architektur > verrät (addressierung der Register) mit einen gut formulierten memonic > kann man sich die Instruction gut im Kopf zusammenbassteln, Zum einen sagst du hier ziemlich genau das gleiche wie dein Vorredner - Mnemonics werden so designt, daß sie sich leicht merken und verstehen lassen. Was übrigens schon im Wort steckt: https://de.wikipedia.org/wiki/Mnemonic Zum zweiten ist es einen Binsenweisheit, daß Mnemonics Besonderheiten der Architektur widerspiegeln, denn sie werden ja gezielt für die Zielarchitektur entwickelt. Eine Architektur, bei der immer der Akku das Ziel einer ALU-Operation ist, wird bspw. für ALU-Operationen immer nur einen (oder gar keinen) Operand benötigen. Eine Architektur ohne Stack hat keine PUSH und POP Mnemonics. etc. pp. Zum dritten widerspreche ich deiner Behauptung: C. A. Rotwang schrieb: > Ich beziehe mich auf die Zeit vor dem Assembler, Mnemonics gab es > bereits bevor es Assembler gab. Denn Mnemonics sind für die (damals neue) Technik der Assembler- programmierung entwickelt worden. Und das Merkmal dieser Technik ist nun mal, daß das Programm als Aufreihung von Mnemonics geschrieben und dann automatisiert -von einem Assembler- in Maschinensprache übersetzt wird. Weder Assembler noch Mnemonics sind älter als der jeweils andere. Die Existenz des einen ist Grundlage für die Existenz des anderen. Die Mnemonics als symbolische Beschreibung der Möglichkeiten einer Prozessorarchitektur sind weitgehend nutzlos, wenn es keinen Assembler gibt, der sie in Maschinencode übersetzt. Und ein Assembler ist weitgehend nutzlos, wenn er nicht die Mnemonics wenigstens einer Zielarchitektur implementiert. PS: weil abzusehen ist, daß dieser Einwand kommt: aus dem von mir gesagten geht hervor, daß Mnemonics in einen gewissen Sinn natürlich vor dem Assembler existieren müssen, der sie implementiert. Auch wieder eine Binsenweisheit. Aber ich dachte ich sage es wieder explizit, bevor jemand versucht, daraus einen Widerspruch zu konstruieren.
:
Bearbeitet durch User
Axel S. schrieb: > Eine Architektur, bei der immer der Akku das > Ziel einer ALU-Operation ist, wird bspw. für ALU-Operationen immer nur > einen (oder gar keinen) Operand benötigen. In vielen früheren Architekturen wurde ein Operand im Mnemonic angegeben. Auch Akku-Architekturen haben meist mehrere Register, weil man schon sehr früh den Wert mehrerer Indexregister erkannte. In dieser Tradition steht 6800/6500, bei denen eben nicht die generische Form INC X MOV Y,A definiert wurde, sondern deutlich kryptischer INX TAY Heute neigt man eher zur generischen lesbareren Form. Das Mnemonic definiert die Operation, irgendwelche Operanden folgen dahinter. Solche Assemblersprache ist auch dann leidlich verständlich, wenn man der Architektur zum ersten Mal begegnet. Beispielsweise bei Lektüre fremden Codes - Wartbarkeit ist wichtiger als Sparsamkeit bei Quellcode-Bytes. In diesem Sinn ist auch Zilogs Neudefinition der Assemblersprache im Rahmen der Z80 als Fortschritt zu sehen. Das ist klar übersichtlicher als Intels Minimalistik bei der 8080 CPU.
:
Bearbeitet durch User
C. A. Rotwang schrieb: >> Meine Welt sagt: Ein Opcode beschreibt einen Befehl der CPU, und ein >> Mnemonic ist eine menschenfreundliche Merkhilfe für diesen Opcode. "NOP" >> ist einfacher zu merken als "F9" und kürzer als "No OPeration". > > Schau dir einfach mal einen Arithmetik befehl und die möglichen > adressierungen an, dann sollte klar werden das das Mnemonic mehr ist als > eine Merkhilfe sondern eine Menge über die zugrundeliegende Architektur > verrät (addressierung der Register) Die Mnemonics gehören zu einer bestimmten Architektur, insofern sollte es nicht überraschen, dass sie etwas über diese Architektur aussagen... Auch, wenn viele Architekturen gleichlautende Mnemonics kennen (NOP, ADD, ...), sind es nicht die gleichen Mnemonics, denn sie funktionieren unterschiedlich. > mit einen gut formulierten memonic kann man sich die Instruction > gut im Kopf zusammenbassteln, fiktives Beispiel > > MOV r1, r15 -> "101010" "00" "0001" "1111" -> 651f; > > also OpCode für Move & Befehlsmodifikator & Adresse dest & Adresse > source Du vermischst Mnemonic und Codierung eines Befehls. Ein Mnemonic wie in deinem Beispiel sagt über die Codierung schlicht nichts mehr aus. "MOV r1, 15" und "MOV r1, r15" nutzen zwei verschiedene Formate, und es ist nicht zwingend, dass "r1" an der gleichen Stelle im Bitstrom gleich codiert wird. Weder muss die Codierung eines Befehls eindeutig sein (zwei Bitsequenzen dürfen auch dasselbe tun), noch muss ein Befehl eindeutig einem Mnemonic zugeordnet werden können (Pseudobefehle). C. A. Rotwang schrieb: > Die Jugend lässt sich nach meiner Erfahrung nichts erklären, die Jugend > nutz google oder stirb dumm. Ich wollte gerne wissen, wo deine Sichtweise anders ist als meine Sichtweise. Das kriege ich mit Google nicht raus. Muss ich wohl dumm sterben.
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.