Forum: Mikrocontroller und Digitale Elektronik AVR Assembler Frage


von Frank (Gast)


Lesenswert?

Wie bekomme ich folgenden Pseudocode am besten in AVR Assembler 
verpackt?

IF (r16 == 0 AND r17 == 0) THEN rjmp target

Grundsätzlich geht es mir um Sprünge, wenn ein AND-Konstrukt wahr ist 
und lesbar sollte es auch noch sein. Mit cpi kann man ja leider nur 
einen Wert vergleichen.

Mit cp r16,r17 kann ich zwar prüfen, ob sie gleich sind, aber nicht, ob 
sie gleich und 0 sind.

von Jonas B. (jibi)


Lesenswert?

nimm c

von Oliver S. (oliverso)


Lesenswert?

Jonas B. schrieb:
> nimm c

und schau dir dann an, was der Compiler draus macht.

Oliver

von Peter D. (peda)


Lesenswert?

Du kannst einfach nach einem Vergleich zum nächsten Vergleich springen.
Oder beide Register verodern und dann springen.
Oder den Test auf 0 mit CPC kaskadieren.

von Prokrastinator (Gast)


Lesenswert?

Frank schrieb:
> Mit cp r16,r17 kann ich zwar prüfen, ob sie gleich sind, aber nicht, ob
> sie gleich und 0 sind.

Du hast Dich aber schon mal mit dem ASM Mnemonics beschäftigt?
Bedingte Spünge, Zero flag etc. sind Dir ein Begriff?

von Thomas R. (r3tr0)


Lesenswert?

1
                          MOV A, @R16
2
                          CLR C //Clear Carrybit
3
                          SUB A, #00H
4
                          JZ ZweiterCompare // Springe falls 0
5
                          /*Mache etwas, wenn Vergleich nicht richtig*/
6
7
          ZweiterCompare: MOV A, @R17
8
                          CLR C //Clear Carrybit
9
                          SUB A, #00H 
10
                          JZ ErfolgreicherVergleich // Springe falls 0
11
                          /*Mache etwas, wenn Vergleich nicht richtig*/
12
  
13
  ErfolgreicherVergleich: /*Mache etwas, wenn Vergleich richtig*/

: Bearbeitet durch User
von Fips Asm (Gast)


Lesenswert?

Peter D. schrieb:
> Du kannst einfach nach einem Vergleich zum nächsten Vergleich springen.

genau.

tst r16
brne nicht_null
tst r17
brne nicht_null
beide_null

von Falk B. (falk)


Lesenswert?

Frank schrieb:
> Wie bekomme ich folgenden Pseudocode am besten in AVR Assembler
> verpackt?
>
> IF (r16 == 0 AND r17 == 0) THEN rjmp target
>
> Grundsätzlich geht es mir um Sprünge, wenn ein AND-Konstrukt wahr ist
> und lesbar sollte es auch noch sein. Mit cpi kann man ja leider nur
> einen Wert vergleichen.
>
> Mit cp r16,r17 kann ich zwar prüfen, ob sie gleich sind, aber nicht, ob
> sie gleich und 0 sind.

Doch, denn es gibt ja das Zero-Flag

or r16, r17
brne target

von Fips Asm (Gast)


Lesenswert?

Falk B. schrieb:
> or r16, r17
> brne target

... was aber nur für den Fall von beide Null feststellt daß die Register 
gleich sind!

von Per (Gast)


Lesenswert?

Frank schrieb:
> Grundsätzlich geht es mir um Sprünge, wenn ein AND-Konstrukt wahr ist

Dafür langt cp r16,r17.

Frank schrieb:
> aber nicht, ob sie gleich und 0 sind.

Wenn sie beide Null sind sind sie auch gleich.

von LostInMusic (Gast)


Lesenswert?

>IF (r16 == 0 AND r17 == 0) THEN rjmp target

clr  r0
cp   r16, r0
cpc  r17, r0
breq target

von Frank (Gast)


Lesenswert?

LostInMusic schrieb:
>>IF (r16 == 0 AND r17 == 0) THEN rjmp target
>
> clr  r0
> cp   r16, r0
> cpc  r17, r0
> breq target

Guter Trick! Das kann man sogar auch noch für komplexere ANDs erweitern.
1
IF (r0 == 12 AND r1 == 20 AND r2 == 24) THEN rjmp target
2
3
ldi r0,12
4
ldi r1,20
5
ldi r2,24
6
cp r16,r0
7
cpc r17,r1
8
cpc r18,r2
9
breq target

Auch super lesbar. Genau sowas habe ich gesucht.

von Frank (Gast)


Lesenswert?

Zu schnell getippt. Korrektur:
1
IF (r16 == 12 AND r17 == 20 AND r18 == 24) THEN rjmp target
2
ldi r20,12
3
ldi r21,20
4
ldi r22,24
5
cp r16,r20
6
cpc r17,r21
7
cpc r18,r22
8
breq target

von LostInMusic (Gast)


Lesenswert?

Du brauchst nur ein Zwischenregister:

ldi r20, 12
cp  r16, r20
ldi r20, 20
cpc r17, r20
ldi r20, 24
cpc r18, r20
breq target

Man kann die "ldi" problemlos dazwischenschieben, weil "ldi" ja keine 
Flags verändert.

von Sascha W. (sascha-w)


Lesenswert?

Fips Asm schrieb:
> Falk B. schrieb:
>> or r16, r17
>> brne target
>
> ... was aber nur für den Fall von beide Null feststellt daß die Register
> gleich sind!
aber genau was er wollte - beide 0
Die Aktion ändert allerdings den Wert in r16, falls man den noch braucht 
also ggf. vorher umkopieren.

Sascha

von Fips Asm (Gast)


Lesenswert?

> IF (r16 == 12 AND r17 == 20 AND r18 == 24) THEN rjmp target

LostInMusic schrieb:
> Du brauchst nur ein Zwischenregister:
> ldi r20, 12
> cp  r16, r20
> ldi r20, 20
> cpc r17, r20
> ldi r20, 24
> cpc r18, r20
> breq target


Das ist doch Unsinn.

Lass R16=14 sein -> 14-12 -> Kein Z, Kein C
Lass R17=22 sein -> 22-20 -> Kein Z, Kein C
Wenn R18=24 -> 24-24 -> Z gesetzt -> SPRUNG!
Und das obwohl R16 und R17 ihre Bedingung nicht erfüllen.

von Fips Asm (Gast)


Lesenswert?

Sascha W. schrieb:
> aber genau was er wollte - beide 0
> Die Aktion ändert allerdings den Wert in r16, falls man den noch braucht
> also ggf. vorher umkopieren.

Und genau deshalb braucht

Fips Asm schrieb:
> tst r16
> brne nicht_null
> tst r17
> brne nicht_null
> hier sind beide_null

auch nicht mehr Code.

Allgemein für den Fall
IF (r16 == 12 AND r17 == 20 AND r18 == 24)
werden r16,r17,r18 nacheinander mit cpi 12,20,24 getestet und bei einer 
Ungleichheit rausgesprungen = Bedingung nicht erfüllt. Kürzer geht es 
nicht!

von michael_ (Gast)


Lesenswert?

Per schrieb:
> Frank schrieb:
>> aber nicht, ob sie gleich und 0 sind.
>
> Wenn sie beide Null sind sind sie auch gleich.

Ja.
Aber bei anderen Werten auch.

Ich glaube, dass ich damals das mit XOR gemacht habe.

von LostInMusic (Gast)


Lesenswert?

>Wenn R18=24 -> 24-24 -> Z gesetzt -> SPRUNG!
>Und das obwohl R16 und R17 ihre Bedingung nicht erfüllen.

Du hast keine Ahnung. Lies in der Hilfe/Doku nach, wie es sich mit dem 
Z-Flag bei "cpc" verhält. Danach verstehst Du, warum meine Variante 
funktioniert.

von Fips Asm (Gast)


Lesenswert?

LostInMusic schrieb:
> wie es sich mit dem
> Z-Flag bei "cpc" verhält

"Previous value remains unchanged when result is zero,
cleared otherwise"

Hast Recht. CPC kann das Z-Flag höchstens löschen. CP kann beides. Böse 
Wissenslücke meinerseits. Danke.

von Peter D. (peda)


Lesenswert?

Noch ne Variante:
1
  movw r25:r24, r17:r16
2
  adiw r25:r24, 0
3
  breq both_zero

von Fips Asm (Gast)


Lesenswert?

Peter D. schrieb:
> Noch ne Variante:
>   movw r25:r24, r17:r16
>   adiw r25:r24, 0
>   breq both_zero

Du bist ja immer noch beim Null-Testen.
Es ging doch längst schon um

Frank schrieb:
> IF (r16 == x AND r17 == y AND r18 == z) THEN rjmp target

Außerdem brauchts zusätzliche Register.
Das einfache tst mag langweilig ausschaun ist aber am sparsamsten.

von M. Н. (Gast)


Lesenswert?

Fips Asm schrieb:
> Falk B. schrieb:
>> or r16, r17
>> brne target
>
> ... was aber nur für den Fall von beide Null feststellt daß die Register
> gleich sind!

Das war doch auch die Anforderung?!
Der obige Code tut genau, was gefordert wird. Er springt, sobald einer 
der beiden werte nicht null ist. Für den fall r16 == 0 && r17 == 0 ghet 
es einfach weiter.

von Fips Asm (Gast)


Lesenswert?

M. H. schrieb:
> Fips Asm schrieb:
>
>> Falk B. schrieb:
>>> or r16, r17
>>> brne target
>>
>> ... was aber nur für den Fall von beide Null feststellt daß die Register
>> gleich sind!
>
> Das war doch auch die Anforderung?!
> Der obige Code tut genau, was gefordert wird. Er springt, sobald einer
> der beiden werte nicht null ist. Für den fall r16 == 0 && r17 == 0 ghet
> es einfach weiter.

Ja. Aber speziell nur für den Null-Test.
Nicht für den allgemeineren Vergleich anderer und mehrerer Werte.
Und es wurde schon gesagt, dieser Nulltest hat einen dicken Pferdefuß: 
Er kann r16 verändern.

von LostInMusic (Gast)


Lesenswert?

>"Previous value remains unchanged when result is zero, cleared otherwise"

Yes, Sir. Darauf basiert das "richtige" Funktionieren von cpc, sbc und 
sbci.

> tst r16
> brne nicht_null
> tst r17
> brne nicht_null
> hier sind beide_null

Was auch in dieser Modifikation seinen Zweck erfüllen täte:

tst  r16
brne PC+2
tst  r17
brne PC+2
rjmp target

von Fips Asm (Gast)


Lesenswert?

LostInMusic schrieb:
> Darauf basiert das "richtige" Funktionieren von cpc, sbc und sbci.

CPC und SBC hatte ich bislang nur beim Vergleich /Subtraktion von 16 Bit 
Werten im Einsatz. Dabei steht ja eher das C-Flag im Mittelpunkt.

In der Verliebtheit in tricky Lösungen lässt sich übrigens leicht 
übersehen, daß das einfache cpi + brne immer noch kürzer UND 
register-sparsamer UND vor allem leichter zu überblicken ist. Sir. ;-)

von Norbert (Gast)


Lesenswert?

1
IF (r16 == 0 AND r17 == 0) THEN rjmp target

> Falk B. schrieb:
> or r16, r17
> brne target

Sollte es nicht:
1
or r16, r17
2
beq target
heißen?

Und die Anforderung das auf irgend etwas anderes als auf ›0‹ getestet 
werden soll, sowie die Anforderung das Register erhalten bleiben müssen 
wurde nirgends gestellt.

von Fips Asm (Gast)


Lesenswert?

Norbert schrieb:
> Und die Anforderung das auf irgend etwas anderes als auf ›0‹ getestet
> werden soll,

Frank schrieb:
> Grundsätzlich geht es mir um Sprünge, wenn ein AND-Konstrukt wahr ist



Norbert schrieb:
> sowie die Anforderung das Register erhalten bleiben müssen
> wurde nirgends gestellt

Da hast Du Recht. Ist von Fall zu Fall verschieden. Unnötige/unbemerkte 
Veränderung bleibt aber unschön und kann von Fall zu Fall zur Falle 
werden ...

von Peter D. (peda)


Lesenswert?

Fips Asm schrieb:
> Unnötige/unbemerkte
> Veränderung bleibt aber unschön und kann von Fall zu Fall zur Falle
> werden ...

Deshalb muß man sich als Assemblerprogrammierer zuerst mal einige Regeln 
aufstellen. Z.B. welche Register als zerstörbare Arbeitsregister 
verwendet werden, welche zur Parameterübergabe, welche als Returnwerte 
usw.
Man kann sich auch einige Register für Interrupts reservieren, das spart 
dann Push/Pop-Orgien.

von Fips Asm (Gast)


Lesenswert?

IF (r16 == 0 AND r17 == 0) THEN rjmp target

Norbert schrieb:
> Sollte es nicht:
> or r16, r17
> beq target
> heißen?

breq target. Genau. Nur wenn beide Null sind wird das Z Flag gesetzt und 
Target angesprungen. Statt bei brne/breq könnte der Gedankenfehler aber 
auch beim (falschen) target gelegen haben.

von Fips Asm (Gast)


Lesenswert?

Peter D. schrieb:
> Deshalb muß man sich als Assemblerprogrammierer zuerst mal einige Regeln
> aufstellen. Z.B. welche Register als zerstörbare Arbeitsregister
> verwendet werden, welche zur Parameterübergabe, welche als Returnwerte
> usw.

Behutsame Register-Spezialisierung tut sicher ganz gut, das kann aber 
schnell in unflexibel und unnötig einschränkend ausarten, womit man sich 
einiger Freiheiten beraubt die gerade das Assembler-Programmieren so 
anregend macht.
Es gilt einfach die Übersicht zu bewahren!

von Fips Asm (Gast)


Lesenswert?

Peter D. schrieb:
> Man kann sich auch einige Register für Interrupts reservieren, das spart
> dann Push/Pop-Orgien.

Ich sichere dazu X,Y,Z (die Perlen unter den Registern) schnellstmöglich 
(denn Speed hat hier Priorität) mit movw in r10-r15 und versuche dann 
damit im Interrupt auszukommen. Oft gelingts.

von MCUA (Gast)


Lesenswert?

>das kann aber schnell in unflexibel und unnötig einschränkend ausarten, womit man 
sich einiger Freiheiten beraubt ..

Man muss sich zu jedem Zeitpunkt über die Register-Belegung im klaren 
sein, um nicht hier und da Register mit Werten (falsch) zu überschreiben 
und damit Fehler zu produzieren. (Bsp. ein paar Register nur für Temp. 
reservieren)

von Peter D. (peda)


Lesenswert?

Fips Asm schrieb:
> Es gilt einfach die Übersicht zu bewahren!

Ohne Regeln ist es nur ungemein schwerer, die Übersicht zu behalten und 
die Fehlerhäufigkeit steigt stark an. Man ist dann nur am Fehler 
ausbessern und der Code ist kaum wartbar und erweiterbar.
Oder der Code besteht zu >50% aus Push/Pop, weil ja jedes Register 
woanders auch verwendet werden könnte.

Ich würde Assembler aber auch nicht mehr für produktiven Code verwenden, 
das ist einfach zu aufwendig und zeitraubend. Die Zeit kann man viel 
besser in die Optimierung des Ablaufs und der Algorithmen stecken.

von chris (Gast)


Lesenswert?

add R16,R17
tst R16
breq target

von Fips Asm (Gast)


Lesenswert?

Peter D. schrieb:
> Ohne Regeln ist es nur ungemein schwerer, die Übersicht zu behalten und
> die Fehlerhäufigkeit steigt stark an.

Nun, man sollte auch nicht vergessen daß wir hier nur von 
vergleichsweise einfachen 8Bittern reden. Und es ist es wie überall 
Übungssache.

> Oder der Code besteht zu >50% aus Push/Pop, weil ja jedes Register
> woanders auch verwendet werden könnte.

Zum Glück hat der AVR wirklich reichlich Register als daß man diese 
Quote jemals auch nur zu einem Bruchteil erreichen müsste.

Peter D. schrieb:
> Ich würde Assembler aber auch nicht mehr für produktiven Code verwenden

Das Wörtchen "Ich" ist dabei entscheidend. Und (nicht genannt) Hobby.

> Die Zeit kann man viel
> besser in die Optimierung des Ablaufs und der Algorithmen stecken.

Gerade die Kenntnis des Ablaufs kombiniert mit totaler Code-Freiheit 
kombiniert mit besserer Controller-Kenntnis bringt das Quentchen mehr 
Optimierungspotential. Die andere Frage ist natürlich ob es in der 
konkreten Anwendung überhaupt drauf ankommt. Allein die Möglichkeit dazu 
ist aber etwas was so manches "Ich" fasziniert und inspiriert.

von Fips Asm (Gast)


Lesenswert?

chris schrieb:
> add R16,R17
> tst R16
> breq target

verändert doch auch r16. wenns nicht drauf ankommt
dann lieber gleich "or r16,r17 + breq target"

von Norbert (Gast)


Lesenswert?

chris schrieb:
> add R16,R17
> tst R16
> breq target

Das scheint mir doch etwas Problem-behaftet zu sein.
In genau 2*255 Fällen.
Wenn R16+R17 zu 256 (0)+carry addieren.

von Norbert (Gast)


Lesenswert?

Ups, ich korrigiere mal nach oben…
Da TST auf Z or N Flag testet, kommen noch die Situationen hinzu in 
denen eine Addition >127 ergibt.

von Peter D. (peda)


Lesenswert?

Fips Asm schrieb:
> Gerade die Kenntnis des Ablaufs kombiniert mit totaler Code-Freiheit
> kombiniert mit besserer Controller-Kenntnis bringt das Quentchen mehr
> Optimierungspotential.

Ist auch meine Erfahrung. Optimierung auf Assemblerebene bringt nur 
wenig (ein Quentchen) im Vergleich zum Zeitaufwand. Ich nenne das 
Mikrooptimierung.
Optimierung durch Durchdenken des Ablaufs bringt dagegen oft erheblich 
mehr.
Z.B. sieht man nicht selten, daß die gleiche Zahl im Multiplexinterrupt 
immer wieder neu zerlegt wird (mittels Divisions-Lib), um das nächste 
Digit anzuzeigen. Deutlich effektiver ist es, die Zahl nur neu zu 
zerlegen, wenn sie sich auch geändert hat.
Es lohnt sich also, darüber nachzudenken, ob zeitintensiver Code nicht 
unnötig oft aufgerufen wird (Profiling).

von LostInMusic (Gast)


Lesenswert?

>Da TST auf Z or N Flag testet

tst testet überhaupt keine Flags, sondern den Operanden. Der Flag-Test 
kommt erst beim breq.

>kommen noch die Situationen hinzu in denen eine Addition >127 ergibt.

Nein, weil für breq nur das Z-Flag relevant ist.

Anyway erfüllt "add-tst-breq" natürlich nicht die Anforderung des TO.

von Norbert (Gast)


Lesenswert?

LostInMusic schrieb:
> tst testet überhaupt keine Flags, sondern den Operanden. Der Flag-Test
> kommt erst beim breq.

Ja, stimmt. TST setzt das Z-Flag wenn das Register 0x00 ist.
Das macht aber der davor stehende ADD R16,R17 auch schon.
Also ist - in diesem Fall - der TST ein prima NOP ;-)

von Fips Asm (Gast)


Lesenswert?

Peter D. schrieb:
> Optimierung auf Assemblerebene bringt nur
> wenig (ein Quentchen) im Vergleich zum Zeitaufwand

Dieses Verhältnis ist schon sehr "Ich" - bezogen.
Also erfahrungsabhängig und abhängig von vorhandenem Code.

> Optimierung durch Durchdenken des Ablaufs bringt dagegen oft erheblich
> mehr.

Ganz klar- hier springt am meisten an Gewinn raus.
Ganz egal mit welcher Sprache.

von Jan (Gast)


Lesenswert?

Fips Asm schrieb:
> Zum Glück hat der AVR wirklich reichlich Register als daß man diese
> Quote jemals auch nur zu einem Bruchteil erreichen müsste.

Also eigentlich(tm) hat er nur 16 Stück 16-Bit Register, die als 32 
Halbregister präsentiert werden. Deshalb sind die Register X Y Z auch so 
bezeichnet und man greift für gewöhnlich via XL XH auf die untere bzw. 
obere Hälfte zu.

Wenn man jetzt darauf besteht, dass die kleinen AVRs 32 Register haben, 
dann müsste man den 32-Bittern eigentlich 64 Stück 8-Bit Register 
zugestehen ;)

von Fips Asm (Gast)


Lesenswert?

Jan schrieb:
> dann müsste man den 32-Bittern eigentlich 64 Stück 8-Bit Register
> zugestehen

Gerne. Da kann dann viel verschwendet werden, bei den 8Bittern muß man 
schneller auf den Punkt kommen. Für ihre Zwecke reichts aber dicke.

von Oliver S. (oliverso)


Lesenswert?

Jan schrieb:
> Wenn man jetzt darauf besteht, dass die kleinen AVRs 32 Register haben,
> dann müsste man den 32-Bittern eigentlich 64 Stück 8-Bit Register
> zugestehen ;)

Na ja, der AVR ist nunmal ein 8-Bitter, da ergeben 8 bit schon ein 
vollwertiges Register.

Oliver

von Jan (Gast)


Lesenswert?

Oliver S. schrieb:
> Na ja, der AVR ist nunmal ein 8-Bitter, da ergeben 8 bit schon ein
> vollwertiges Register.

Naja, ist schon nicht so einfach. Dann würde es Befehle wie adiw und 
sbiw ja nicht geben können. Nungut, man kann sagen, dass das Fake ist, 
da die Befehle zwei Takte brauchen. Aber der Befehl movw bewegt 16 Bit 
in einem Takt. Wie erklärst du dir das mit dem Argument, der (kleine) 
AVR ist ein 8-Bitter?

von Karl B. (gustav)


Lesenswert?

Hi, werfe mal in die Debatte:
statt einfachem addierem add -> addieren mit carry.
adc
Dann das Carrybit mit ror wieder in den "Ziffernbereich"
und weiter...comparen. Und zurück.

ciao
gustav

: Bearbeitet durch User
von Oliver S. (oliverso)


Lesenswert?

Jan schrieb:
> Aber der Befehl movw bewegt 16 Bit
> in einem Takt. Wie erklärst du dir das mit dem Argument, der (kleine)
> AVR ist ein 8-Bitter?

Ach je, nur weil da im Befehlssatz noch Platz für drei Befehle mit 16 
Bit Breite war, wird der nicht gleich zum 16-Bit Prozessor. Das ist und 
bleibt ein reiner 8Bit Prozessor. Das man auch auf dem mit größeren 
Wortbreiten hantiert, wenn es erforderlich ist, ändert da nichts daran.
Spätestens, wenn die 16-Bitbwerte in den Speicher zurückmüssen, geht es 
wieder brav Byte für Byte.

Oliver

von c-hater (Gast)


Lesenswert?

Oliver S. schrieb:

> Das ist und
> bleibt ein reiner 8Bit Prozessor.

Jepp.

Sinnvollerweise macht man das allein an der Breite der Integer-ALUs 
fest. Mit allem anderen ergibt sich keinerlei sinnvolle 
Klassifikations-Struktur. Schon seit Jahrzehnten nicht mehr...

Und falls jetzt irgensoein Schlaumichel bezüglich AVR8 mit adiw/sbiw 
daherkommt: Bitte erstmal darüber nachdenken, warum die wohl zwei Takte 
brauchen. Ganz genau so, als würde man es zu Fuß aus add/adc bzw. 
sub/sbc zusammenbauen...

von c-hater (Gast)


Lesenswert?

Jan schrieb:

> Aber der Befehl movw bewegt 16 Bit
> in einem Takt.

Dabei ist die ALU nicht involviert.

von Peter S. (cbscpe)


Lesenswert?

[code]

     subi  r16, 0
     sbci  r17, 0
     brne  PC+2
     rjmp  target

[\code]

von Maxim B. (max182)


Lesenswert?

Frank schrieb:
>
1
> IF (r16 == 12 AND r17 == 20 AND r18 == 24) THEN rjmp target
2
> ldi r20,12
3
> ldi r21,20
4
> ldi r22,24
5
> cp r16,r20
6
> cpc r17,r21
7
> cpc r18,r22
8
> breq target
9
>

Man kann aber auch anders, um keine Register zusätzlich nehmen zu 
müssen:
1
  cpi r16,12
2
  brne PC+6
3
  cpi r17,20
4
  brne PC+4
5
  cpi r18,24
6
  brne PC+2
7
  rjmp target
Das wird auch meistens schneller. Zweite Vorteil: rjmp schießt weiter 
als breq.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

c-hater schrieb:
> Sinnvollerweise macht man das allein an der Breite der Integer-ALUs
> fest.

Bei dem Versuch, eine klare Definition zu finden, die nicht irgendwo 
versagt, wirst du scheitern. Oder ist die Z80 ein 4-Bitter? ;-)

Es hat auch schon bitserielle 8-Bitter gegeben.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.