Gut, ja, also, diese Woche wird es in,
inzwischen zwölften Kapiteln, also darum gehen, wie jetzt Befehlssätze für Rechner aussehen, wo Norman die so ein bisschen unterscheiden kann.
Da werden dann also auch relativ viele unterschiedliche Begriffe fallen,
die sie, also sagen wir zumindest, qualitativ irgendwie erklären und beziehungsweise wissen sollten,
nicht darum geht das jetzt darum und Ja,
im nächsten Kapitel wird dann noch mal ein bisschen spezieller in Bezug auf Befehle beziehungsweise beziehungsweise Befehlsätze,
dann also auf den Assembler-Quote von X86-Prozessoren geguckt,
wobei auch das steht dann hier, also des Öfteren auf den Folien beziehungsweise auch gerade in der aktuellen Übungsaufgabe.
Es geht nicht darum, also jetzt irgendwie Assembler-Quote programmieren zu lernen,
kann ich auch nicht, sondern darum,
dass man einfach mal so ein paar Grundprinzipien kennenlernt,
wie das Ganze letztendlich abgearbeitet wird, sprich wie das,
was ich hier irgendwo als Software laufen habe,
auf dem Befehlssatz beziehungsweise auf der drunter liegenden Hardware dann wirklich dazu führt,
dass der Computer eben auch wirklich rechnet oder irgendwas macht.
Ja, bislang haben wir uns ja, also irgendwo,
wie so in diesem Bereich aufgehalten, also ein bisschen Schaltnetze,
Schaltwerke, da ist man also irgendwo hier,
das, was jetzt noch so ein bisschen folgt,
ist dann eben letztendlich genauso hier diese Trennlinie,
so ein bisschen Erklärungs-Anstruction-Set-Architecture und dann eben ganz am Ende werden,
also zumindest ein paar Grundlagen zu Betriebssystemen,
dann also auch noch entsprechend erläutert,
allerdings auch da muss man dann immer sagen,
wie bei vielen anderen Sachen, aufgrund des doch eingeschränkten Zeitkontingenz,
wer geht es da dann eigentlich eher um so ein paar allgemeine Grundlagen und jetzt weniger um spezielles Wissen für Betriebssystem XY, wie dort irgendwas implementiert ist.
Ja, ansonsten, wie gesagt,
wie die Folie hier schon ein im Prinzip andeutet,
wir bewegen uns also jetzt im Prinzip insgesamt mit Rechnerstrukturen eben irgendwie bis zu dieser Grenze,
beziehungsweise jetzt also hier noch so ein bisschen drüber,
aber ansonsten Softwareentwicklung, beziehungsweise das,
was sonst eben teilweise noch an der Informatik an Programmiersachen angeboten wird,
da erstmal natürlich dann also entsprechend hier auf den höheren Abstraktionsebene.
Gut, was ist jetzt mit Instruction Set Architecture,
nehme ich jetzt mal als Abkürzung, beziehungsweise ISA,
also Befehlsatzarchitektur eigentlich gemeint, rein praktisch können wir mal sagen, alles das,
was der Programmierer jetzt, wenn er ein Programm schreibt,
von dem Rechner, von der Rechnerarchitektur wissen muss.
Also einmal der nackte Befehlssatz, also sprich,
wenn ich jetzt also irgendwie in Assembler irgendwie was schreibe,
wie ist der Speicher organisiert?
Welche Datentypen habe ich zur Verfügung? Wie sind da dann,
also letztendlich die Syntax von den Befehlen,
also Befehlssatzbefehlsformate und wie funktionieren eben sowas wie jetzt also irgendwelche Datenzugriffe?
Daneben, was man dann auch immer noch wissen muss,
ist letztendlich sowas wie so eine grobe Hardware-Architektur.
Also das ist jetzt hier die eine Grafik,
die ich jetzt im Prinzip letzte Woche schon mal irgendwie dann kurz aufgelegt hatte.
Also sprich, dass man eben weiß, wie vielleicht welche Komponenten zusammenhängen.
Und gerade in Bezug auf die Hardware beziehungsweise was sich dann
eben auch aus den Befehlen selber ergibt.
Welche Register habe ich in meinem Prozessor zur Verfügung?
Wie spreche ich die Ahnen? Wie ist beispielsweise die Speicherhierarchie organisiert,
sollte man zumindest im Hinterkopf wissen? Also solche Sachen. Gut,
ansonsten hier eine Grafik aus dem Unterlagen von Patterson, Hennessey,
wo man dann sieht, okay, also was macht die Hardware?
Die stellt also letztendlich die Basis bereit in Form des Befehlssatzes,
wo sich dann die Software drauf tummelt. Und ja,
was dort dann eigentlich als Begriffe beziehungsweise als Inhalt des Befehlssatzes dann eigentlich mit reinkommt,
ist, dass man eben erstmal wissen muss, wie sieht das mit dem Speicher aus?
Wie ist der organisiert? Wird jetzt also hier auch gleich das erste Thema sein,
dann so ein bisschen was zu den Arten der Rechner,
zu den Registern, dann eben in Bezug auf den Befehlssatz,
wie dort die Befehle organisiert wird,
also sprich mit welchen Befehlen kann ich auf Register oder auf Speicher drauf zugreifen,
habe ich ein oder zwei oder null Adressbefehle oder drei Adressbefehle,
solche ganzen Sachen.
Was dann später in Bezug auf Betriebssysteme beziehungsweise ab Erwartungen noch ein bisschen kommen wird,
ist dann eben ein bisschen noch was zu Systemsoftware beziehungsweise dann eben zu einer Ausgabe und Interraps. Ja,
ansonsten das, was jetzt hier irgendwie mal alles mit angesprochen wird,
sind grob gesagt jetzt eigentlich immer gefundene Architekturen,
also zum einen werde ich dann immer relativ viel,
war das nachher auch bei dem Kapitel Pipelining dann noch mit auftauchen wird,
zu dem Mips-Rechner sagen, weil das also quasi das Standardmodell eines Rissgerechners ist,
Reduced Instruction Set Computer werde ich nachher nochmal ein bisschen wiederholen, nochmal ein bisschen genauer erklären, was damit dann eigentlich gemeint ist.
Nicht dann diejenigen, die es, also das Praktikum schon durch haben,
beziehungsweise jetzt also im ersten Teil bis Freitag sind ja die letzten Termine,
dort, also dann bis zur vierten Aufgabe vorgekommen sind,
da wird dann dann also im Prinzip ja mit so einem kleinen Demo-Rechner,
aber in 16 Bild Mikro programmiert und ja, das,
was im nächsten Kapitel dann eben als Beispiel ist,
als Beispiel von Sisk-Architektur, also das, was X86 ist,
ursprünglich ja also auch mal ganz früher 16 wird,
dann 32, bildet mich inzwischen 64 Bild,
wenn man jetzt also irgendwie in der Literatur guckt oder bei den Prozessorherstellern findet man einmal unterschiedliche Bezeichnungen,
also von X86, 64 oder X64 oder nicht, also bei den Linux-Paket-Verwaltung heißen, heißen die 64 Bit-Pakete dann typischerweise AMD 64, bei AMD
Im Prinzip die ersten 64-Bit-Prozessoren oder Architekturen gebaut hat,
als entweder noch Platz 32-Bit war.
Nicht also solche Sachen. Ja, ansonsten wird dann
eben im nächsten Kapitel noch so ein bisschen was zu Assembler-Programmierungen, wie gesagt, gebracht.
Da geht es aber eher darum, auch solche Sachen,
wie werden zum Beispiel Datenstrukturen, wenn nicht sie in Hochsprachen, also beschreibe.
Also zum Beispiel sind C irgendein RAI mache oder irgendwelche Datenstrukturen. Wie wird das im Speicher abgelegt? Weil ich denke mal,
das wird jetzt also nicht zwingend in der Softwareentwicklung noch irgendwo vorgestellt,
auf der anderen Seite ist das auch irgendwo so eine Sache,
die also entscheidend die Performance eines Programms beeinflussen kann und wo man zumindest grob im Hinterkopf haben sollte,
wenn ich jetzt also meine Datenstrukturen so und so aufbaue oder so und so verwalte,
ist das eben entsprechend effizient von den Speicherzugriffen oder eben vielleicht nicht so gut.
Nicht solche Sachen, dann geht das eben auch darum,
um sowas wie Stack, ich weiß auch,
das ist dann immer irgendwie so eine Sache,
wo man jetzt also zum Beispiel jetzt betriebssystemseitig dann eben sagt,
okay,
wie realisiert die Hardware sowas wie Unterprogrammaufrufe
Beziehungsweise in diesem Fall dann ganz konkret,
was ist also mit den Parametern bei Unterprogrammen aufrufen,
wie kriege ich das hin,
Rekursionen aufzubauen, wo ich also jetzt nicht Apreori weiß,
wie viele Verschachtelungstiefen auftauchen,
wo ich letztendlich dann der Mitgliederrekursionsstufe im Prinzip immer gleiche Argument oder gleichnamige Argumente,
lokale Datenstrukturen irgendwo als Platz im Speicher irgendwo anlegen muss,
wie das dann entsprechend verwaltet ist.
Ansonsten, wie gesagt, also ein paar Architekturen werden dann
also hier beispielshaft nochmal so ein bisschen genauer gesagt.
Ansonsten muss man immer sagen, das,
was eigentlich den Großteil an Rechnern oder Rechensystemen ausmacht,
hat ja schon gesagt, sind eben eigentlich nicht PCs oder Server,
sondern Mikrocontroller beziehungsweise all das, was man so als Embedded Systems bezeichnet,
eben von irgendwelchen Chips auf irgendwelchen Telefonkarten.
Alles, was im Automotive-Bereich verbaut, ist medizintechnik. Gut,
jetzt muss es hier nicht so ein alter Nokia-Knochen sein,
aber eben ein Smartphone und, und, und.
Nicht da geht es dann eben auch darum,
dass man also wirklich von sehr einfachen Mikroprozessoren mit 8-Bit-Wortbreite dann eben bis zu entsprechend komplizierteren Architekturen dann eben arbeitet,
nicht also im Smartphone-Bereich, muss man sagen,
es ist inzwischen eigentlich eine ähnliche Hardware oder Hardwarearchitektur wie das,
was wir also auf dem oder Laptop-Bereich letztendlich benutzen.
Also sprich auch mehr Kernprozessoren, Superskalarerechner und, und, und. Das ist das Einzige,
was da dann natürlich noch ein bisschen Unterschied macht, ist,
dass sie dann eben nochmal speziell auf Strom verbraucht bzw. Leistungsaufnahme entsprechend optimiert sind,
dass man da dann eben, sag mal,
mit etwas spezielleren Techniken dafür sorgen kann,
dass er eben entsprechend wenig Leistung verbraucht wird.
Ja, und ansonsten eben, wie gesagt,
bei all diesem, was wirklich von billigst Einsatz,
wo also im Prinzip der Prozess und nicht mehr als irgendwie ein Bruchteil vom Cent kosten darf,
bis zu irgendwelchen entsprechend aufwendigen, Systemen geht,
ist eben wirklich ein Großteil von unterschiedlichen Architekturen da.
Was viele dieser Systeme dann ja auszeichnet, ist,
dass sie eben allein schon an Ein- und Ausgabe gar nicht das haben,
was wir ja so vom Computer gewöhnt sind. Das heißt,
Monitor gibt es nicht, die Tastatur gibt es nicht,
sondern eben teilweise was wie vielleicht Taster oder eben noch irgendwie so ein paar Status oder Kontrollinformationen,
aber das ist dann eben doch entsprechend sehr stark unterschiedlich.
Und generell kann man eben sagen, das was da dann letztendlich immer Ausschlag geben.
Es sind eben die teilweise sehr speziellen Anforderungen, die sich dann eben an solche Systeme ergeben. Also sprich,
wie teuer darf das sein, wie groß darf das sein,
wie viel Leistung darf das aufnehmen, wie sieht das aus mit Sicherheitsanforderungen,
einmal in Bezug auf den ständigen Betrieb,
dass das System jetzt also irgendwie nicht kaputt geht,
einmal in Bezug auf die Sache,
wenn das also in irgendeinem größeren System,
also in irgendeiner Maschine verbaut ist,
dass dort letztendlich für den Benutzer,
kein Schaden entsteht.
Das ist dann immer das, was also Armer Safety,
Armer Security heißt. Dann eben solche Sachen wie Echtzeitanforderungen,
die man teilweise hat. Also sprich, wenn ich im Automotive-Bereich,
also irgendwas verbaue, sicherheitstechnisch oder Flugzeugtechnik, Avionik,
nicht, dann muss das eben wirklich mit harten Zeitbedingungen zurechtkommen.
Sicherheit, Sicherheitsaspekte dann eben auch noch in dem Sinne,
wie sieht das aus mit der Datensicherheit kann das System
von außen irgendwie kompromittiert werden und, und, und nicht.
Also es ist dann eben wirklich ein extrem großes Spektrum mit
sehr vielen sehr unterschiedlichen Anforderungen. Also wie gesagt,
dies hier so am normalsten Beispiel dienen,
also für einige so Klassen, dass man sich sowas überlegt.
Gut, aber kommen wir jetzt wieder zurück zu dem Thema Instruction Set Architecture.
Was muss man da eigentlich grob wissen? Der erste Abschnitt
wird sich jetzt also nochmal so ein bisschen mit der Speicherorganisation befassen.
Nicht da tauchen dann im Prinzip als Stichworte irgendwo so diese Begriffe
Letztendlich mit auf einige andere Sachen in Bezug auf Speicherorganisationen
folgen dann also in dem Kapitel Rechnerarchitektur 2,
beziehungsweise dann zumindest in Bezug auf die Sicherheit dann eben teilweise noch bei dem Betriebssystem.
Gut, ja, wie gesagt, Speicher,
was soll von den Programmen aus irgendwo gespeichert werden?
Jetzt natürlich irgendwo meine Daten,
typischerweise arbeiten die Systeme immer so,
dass man ja letztendlich als minimalen oder kleinsten Datentyp also irgendwie einbyte,
acht Bit irgendwie hat und dann eben irgendwelche anderen Datenformate
vielfache davon sind
Habe ich also schon zuhauf an Beispielen vorgestellt. Ich sage das
also irgendwie in der Zeichendarstellung, sei das in den Zahndarstellungen,
wo dieses Format ja dann eben in der Regel dann 16,
32, 64 Bit irgendwie letztendlich umfassen.
So, und jetzt geht es eben noch darum,
wie wird dieser Speicher im Prinzip adressiert,
weil auch das hat sich ja schon arm eingangs mal erwähnt,
die Adressierung des Speichers erfolgt in der Regel beidweise.
Auf der anderen Seite physikalisch ist der Speicher, das,
was sich da also letztendlich an Speicherbaustein irgendwo in meinem Rechner verbaue,
dann nicht weitweise aufgebaut, sondern mit 32 oder 64 Bit Speicherworten.
Und da kommt man dann eben schon dazu,
dass man letztendlich natürlich sagen kann, wie ist überhaupt der Speicherpartitioniert,
also hier zum Beispiel aus dem Tarnenbaumbuch,
nicht wo man sagt, okay, also ich kann,
wenn ich jetzt rein beidweise vorgehe, natürlich sagen,
okay, 96 Bit hier als Beispiel,
sind zwölfmal acht Bit, also zwölf Byte.
Ich kann aber natürlich auch sagen, das sind sechs,
mal 16 Bit oder eben das also noch beliebig anders irgendwie aufbauen.
Nicht in der Regel wird man rein logisch bei sowas bleiben,
rein praktisch, dann eben bei 32 oder 64 Bit Speicherworten.
Beispiele dazu folgen auch. Gut, ansonsten, wie gesagt,
inzwischen ist das eigentlich alles relativ stark für einheitlich,
gerade so in den Anfängen der Computertechnik war,
konnte man teilweise wirklich einzelne Bits adressieren.
Ansonsten sieht man hier also wirklich alle möglichen und unmöglichen rum Formate,
die beispielsweise jetzt für irgendwelche komischen Fließkummer-Formate,
die damals also verwendet worden sind, dann also irgendwie benutzt worden.
Wie gesagt, heute interessieren eigentlich, also wenn ich jetzt X86-Architektur nehme,
byte, als 8-Bit, Word, 16-Bit,
32-Bit oder 64-Bit, womit man dann eben eigentlich auch entsprechend gut,
sowohl mit sämtlichen Zahnformaten als auch mit eben irgendwelchen Zeichendarstellungen arbeiten kann.
Ja, nochmal zu der Abbildung, wie ich jetzt eigentlich
mit den Adressen arbeite. Wenn ich jetzt den Speicher beidweise adressiere,
dass wir dann also in dem zuvor geht es also quasi
immer hier ein Byte als ein so ein Kästchen mit den entsprechenden zugehörigen Adressen. Und dann sieht das eben so aus,
dass wenn ich ein 32-Bit-System bzw. Wortbreite im Speicher habe,
ich also quasi mit einer Adresse immer genau einen kompletten Block aus 32-Bit beziehungsweise bei 64-Bit dann ebenentsprechend den hier auslese,
was dann rein technisch jetzt gesehen aber wieder heißt,
aufeinanderfolgende Speicheradressen, wenn ich jetzt also nicht bei der Bartweisenadressierung bin,
sondern bei dem, was wirklich physikalisch passiert,
unterscheiden sich hier dann eben immer entsprechend um vier,
beziehungsweise wenn ich 64-Bit habe, um acht, weil ich dann natürlich logischerweise immer acht weit mit einer Speicheradresse heraus adressiere.
Gut, die andere Sache ist dann eben auch immer noch,
wie Sie das dann mit den Daten aus,
wenn ich jetzt eben irgendwie einbeit, hier irgendwo aus der Mitte herauslesen möchte,
wenn ich jetzt also beispielsweise ein einzelnes Zeichen habe,
auch da muss man jetzt eben sagen,
das ist dann eben wieder davon abhängig, wie sind die Speicherworte,
beziehungsweise Objekte dann also im Speicher angeordnet und dann sorgt eben bei irgendwelchen Datenzugriffen letztendlich der Assembler,
beziehungsweise in einem Assembler-Quote dafür,
dass dann eben quasi ein Speicherwort rausgelesen wird und dann eben beispielsweise das entsprechende Byte dann also technisch gesehen dann eben raus maskiert wird und dann rausgelesen werden kann.
Ansonsten, die Folilaca also auch schon mal auf,
in einem der früheren, ich glaube,
im zweiten Kapitel, also Datentypen auf Maschinenebene,
wo man dann eben auch sehen kann, also bei typischen 32-Bit-Systemen,
also in diesem Fall, also hier bezogen auf C,
habe ich da also immer quasi beispielsweise für ein Integer dann entsprechend Vierbyte,
Long Enteger beim 32-Bit-System eigentlich auch, wenn ich ein 64-Bit-System habe,
früher war das mal Deck Alpha,
inzwischen gibt es ja also schon lange nicht mehr,
hätte ich dann eben entsprechend Long Enteger dann entsprechend mit 8
Das heißt, was man da dann eben immer gucken muss,
ist dann eben wirklich teilweise abhängig von Programmiersprache beziehungsweise abhängig vom Compiler.
Das ist also das,
was ja auf dieser Folie dann also darauf war,
dass zumindest in See,
wo das jetzt also nicht im Sprachstandardfest definiert ist,
irgendwelche Wortgrößen sich teilweise hinsichtlich der Architektur,
also 32 oder 64 Bild und auch hinsichtlich der Betriebssysteme,
dann eben schon unterscheiden können
Bei Java haben wir das Problem nicht, da ist das Ganze ja
so wirklich im Sprachstandard vordefiniert. Ansonsten bei C muss man,
sowas dann eben beispielsweise über entsprechende Herder bzw. Entblutdateien,
also quasi abfragen, wo dann also im Prinzip Maxi,
also Maxint, Min-End, entsprechend vordefiniert sind,
die man dann eben abfragen kann, um daneben zu gucken,
wie groß sind dann jeweils die größten bzw. kleinsten Werte.
Nicht jedenfalls, also nur, dass man da im Hinterkopf hat,
da kann es eben wirklich abhängig von System entsprechende Unterschiede hinsichtlich der Wortbreiten kriegen.
Gut, etwas, was uns dann auch immer begegnet und
was dann also auch immer gerne irgendwelche Kopfzerbrechen bereitet,
ist also die Frage nach der sogenannten White-Order.
Und zwar, wenn ich jetzt vier,
meinetwegen also eins, 32 Bit-Indiger habe, belegt jetzt,
also quasi so ein 32-Bit-System,
also hier vier Aufnahmen
erfolgende Speicheradressen
So, und jetzt geht es bei der White-Order
dann eben letztendlich darum, bei den aufeinanderfolgenden Speicheradressen,
mit welchem Byte in meinem 32-Bit-Wort fange ich an.
Also sprich, wenn ich hier jetzt also irgendwie ein
32-Bit-Wort habe und ich sage mal, also das hier ist
das niederwärtigste Byte und hier habe ich dann eben das höchstwertigste
Und die werden jetzt also quasi auf Speicheradressen aufgeteilt,
kriegt der hier die Adresse null? 1, 2,
3. Oder kriegt der hier die Adresse null?
Und der HDA-A-Adresse 3, das heißt,
fange ich mit dem höchstwertigsten Wahrheit an oder fange ich mit dem niederwärtigsten Wahrheit an,
dass er so quasi jetzt auf Aufeinanderfolgende Adressen abzubilden.
Und das Ganze nennt sich dann immer Big Indien und Little Indien,
ist im Prinzip, aus dem Englischen geht das also quasi auf Gullivers Reisen zurück,
wo man dann eben sagen kann, okay,
beim Big Indien man sich dann immer dadurch merken,
fängt dann quasi mit den höchstwertigsten Bits an und die kriegen die niedrigste Adresse.
Das heißt, da habe ich dann hier null eins, zwei, drei als Adressen.
Beim Little Andien ist es eben genau umgekehrt, dann habe ich diese Badreihenfolge. So,
hier ist das Ganze eben auch nochmal angedeutet,
wenn ich jetzt also hier diese 32 Bit habe,
Big Andien, fange ich also quasi mit der niedrigsten Adresse,
also der Adresse null, mit den höchstwertigsten Bad eines Wortes an,
gehe dann eben bis zu den niederwertigsten Bad,
beim Little Andien ist es eben
genau umgekehrt
Man findet da dann also auch immer irgendwie sowas wie String-Reihenfolge und Zahnreihenfolge,
wo man dann also auch mal so ein bisschen sehen kann.
Nicht mal ist das so, mal ist das so organisiert.
Letztendlich kann man sagen, haben beide Varianten vor, beziehungsweise Nachteile. Wenn ich dabei bin,
also Zahlen arathmetisch zu berechnen,
dann bieten sich im Prinzip Little-Andien-Systeme an,
weil ich dann eben beispielsweise mit den niederwärtigsten bereits anfange und
wie ich das jetzt also zum Beispiel in der Arrithmetik mache,
ich also von den niederwertigsten Stellen dann also quasi beispielsweise bei der Addition mich dann zu den höherwertigsten Stellen vorarbeite,
um dann eben sowas wie Carrie oder sowas zu berücksichtigen.
Nicht deswegen da Zahnreihenfolge bei Strinks ist eigentlich genau andersrum,
wenn ich Zahlen vergleichen will, ist es eigentlich auch sinniger,
also mit den höherwertigen Bits wieder anzufangen.
Also deswegen kann man sagen, also mal ist das eine,
mal ist das andere besser.
Das, was man eigentlich dann auch immer macht und was
also ständig dann auch im Hintergrund irgendwo stattfindet,
ist,
dass sowas
automatisch konvertiert wird
So, wo begegnet uns das jetzt oder heutzutage eigentlich immer noch?
Also zum einen habe ich die Sache mit diesem Bite-Ordern.
Im Prinzip ist natürlich, wenn ich unterschiedliche Rechner oder Rechnerarchitekturen haben.
Also im Prinzip X8686-Architektur oder Alpha sind Little-Andien-Systeme. Das heißt,
wenn ich also hier die Zahl 15.213 habe, Hexerdizimal,
also irgendwie jetzt hier für die unteren Bits dann
3 B6D. Dann würde ich also quasi mit diesem Wald
hier anfangen als niederwertigste Adresse, dann 3b.
Und wenn ich jetzt also 32-Bit-System habe, würden dann also
quasi 2 Nullen folgen. Bei anderen Rechnerarchitekturen oder Prozessoren,
also gibt es inzwischen nicht mehr, aber Firma Sun Microsystems,
die dann also irgendwann ja mal von Oracle aufgekauft worden ist.
Das war ein Big-Andien-System, da ist das dann eben letztendlich
genau andersrum
Vertauscht. Gut, hier ist das Ganze nochmal für eine Zweier-Komplimentszahl.
Also auch da sieht man dann eben entsprechend genau diese um niederwertigstes,
höchstwertigstes bald beim Big Andien. Es ist eben genau umgekehrt.
Hier dann nochmal der Übergang von 32 auf 64 Bit,
wie gesagt, heutzutage kommen wir eigentlich von sowas dann immer ausgehen.
Gut, hier mal ein Beispiel, zumindest vor ein paar
Jahren konnte ich das ja nochmal irgendwie dann selber programmieren.
Da hatten wir nämlich noch irgendwelche Sun-Rechner. Also In Szene Datenstruktur.
Ich habe hier also quasi irgendwie jetzt so einen Rekord,
wo ich also beispielsweise also irgendwie ein Integer von Angestellten,
oder nein, also das Alter von einem Angestellten,
also quasi einem Integer spare ich ja das Gehalt irgendwie noch speicher und dann eben irgendwie den Namen mit einer begrenzten Länge,
was also dann auch nur bedingt schlau ist, aber okay.
So und da soll es jetzt also quasi einen Datensatz geben von dem Kollegen Jimmy,
der im Prinzip 23 alt ist, 50.000 was auch immer verdient. Und Jim Smith heißt. So,
und wenn man das Ganze quasi jetzt übersetzt, beziehungsweise kompiliert,
in diesem Fall dann also ein 32-Bit-Coach für einen X-36. Sie dann also im Prinzip die Data-Section,
also das heißt, der Teil des Assembler-Codes,
wo im Prinzip Konstanten gespeichert sind, so aus,
wenn man sich das jetzt also hier wirklich mal auf Bit-Ebene mit einem Hex-Editor irgendwo ansieht,
dass hier genaue Formness ist, also für die Zahlen,
also sprich die Das Alter, die 23 bzw. die 50.000,
exerdezimal dann als 1.7 bzw. C3, 5.0.
Die tauchen dann eben hier einmal für das Alter und hier das Gehalt auf. Wie man sieht,
das ist ein Little-Andien-System, weil ich fange hier mit dem niederwertigsten Byte an,
habe dann eben hier noch die drei Folgebyte,
hier dann einem das Gehalt,
wenn ich das Ganze jetzt für einen Spark-Rechner mache,
was also ein Big-Andien-System ist und mir das ansehe,
dann sieht man also hier bei den Zahlen,
wie das eben jetzt in dem Fall dann ein Big-Indian-System ist.
Das heißt also, die Zahl dann eben entsprechend hier vertauscht ist.
So, und wo das dann eben wirklich eklatant auffällt,
sind dann eben solche Sachen, wo dann eben hier aus
dem 50C3 dann das natürlich dann einfach jetzt immer noch nur beidweise vertauscht wird.
Das heißt, da habe ich dann eben C3, 50.
Das heißt also, wenn man jetzt also wirklich irgendwie mal
in die Verlegenheit kommen sollte, Binär-Editor oder wie auch immer.
Also jetzt wirklich bildweise in den Programmen herumzukratzen und dann auch irgendwelchen Daten oder Werten zu suchen.
Dann wird man im Prinzip auf solche Sachen und solche Probleme stoßen,
beziehungsweise dann sollte man eben wissen,
ist das ein Big oder ist das ein Little-Endian-System.
Wo und sowas dann auch immer noch begegnet,
ist bei der sogenannten Netzwerk-Byte-Order.
Auch das hatte ich schon mal kurz angesprochen und
zwar bei der Datenübertragung
Internetprotokoll wird ein Big-Andien-Format verwendet. Das ist glücklicherweise immerhin standardisiert,
weil sonst könnten wir also im Prinzip da nämlich überhaupt keine Datenübertragung machen,
weil das dann also beliebig kreuz und quer falsch laufen würde.
So, jetzt habe ich ja gerade gesagt, x,86 Architektur,
also sprich, wenn ich jetzt also hier irgendwie meinen Laptop nehme,
ist ein Little in ihrem Format.
Das heißt, wenn ich jetzt irgendwelche Daten übers Internet verschicke,
ich sah das jetzt Mail,
sah das aus irgendwelchen anderen Protokollen,
sah das Netzwerkdateisysteme und,
und,
Da muss dann eben immer eine Konvertierung passieren bei diesen ganzen Formaten.
Gut, das passiert in der Regel automatisch über das Betriebssystem.
Das heißt, da muss man sich jetzt nicht selber drum kümmern.
Es seien, man guckt also beispielsweise hier beim Linux-Mann in die Colonel Queren rein. Da wird man nämlich genau das finden,
wo im Prinzip dann, also das hier,
die Spitesworp, hatte ich also schon mal gezeigt,
als ich hier so im Prinzip mal diese Schiebeoperation und Maskierung,
also die bitweisen Operationen vorgestellt habe,
wo dann eben genau sowas hier definiert ist,
wo ich dann also quasi aus dem 33 Bit X,
das also quasi jetzt mit diesem Ausdruck einmal entsprechend vertausche,
um daraus aus Big Andien, Little Andiens zu machen oder umgekehrt.
Nicht, also da ist dann so was implizit letztendlich mit drin. Ansonsten,
um jetzt zu gucken, also bei einem eigenen System,
wie sie das da mitarbeitet, order aus, findet man also relativ viele Programme,
die im Prinzip einem jetzt einfach von irgendwelchen Daten oder Datenstrukturen das quasi beidweise ausgeben können.
Also hier zum Beispiel jetzt aus dem Brian und du Helleron und gesagt,
das, was dort dann im Prinzip einfach nur passiert,
ist, dass das Ganze dann eben wirklich breitweise gelesen würden,
wenn man weiß, was an der Stelle jetzt für eine Zahl drin ist,
würde man dann eben letztendlich genau sehen,
ist die in der einen oder anderen Weise kodiert.
So eine andere Sache, die in dem Zusammenhang mit der Speicherorganisation dann auch noch wichtig ist,
wie ist das jetzt bei dieser Abbildung von irgendwelchen Datenstrukturen auf wirklich das, was physikalisch an Speicherworten stattfindet.
Weil wenn ich jetzt sage, ich habe ein System,
wo ein Speicherwort jetzt 64-Bit breit ist,
das heißt acht Breit umfasst,
Und ich habe jetzt beispielsweise ein 8-Byte-Wort, also ein 64-Bild-Datentyp,
also was weiß ich jetzt, also irgendein Fließkommazahlung oder so,
dann kann ich jetzt natürlich sagen, wunderbar,
passt hier genau in ein Speicherwort und ich kann das dann eben wirklich so als ein Wort mit einem Speicherzugriff auslesen.
Das ist natürlich das, was man sich dann also immer vorstellt oder wie das Ganze funktioniert.
Theoretisch kann ich aber natürlich auch sagen, ja,
niemand sagt, dass also hier diese 64-Bild,
jetzt also quasi meine Longzahl irgendwie ausmachen,
oder nehmen ein Long, nicht ein Double,
dass die jetzt wirklich im Speicher an einer Wortgrenze beginnen,
sondern die können im Prinzip auch über zwei Speicherworte verschmiert sein,
so wie hier.
Demzufolge spricht man dann von Aligned bzw. Non-Aline-Zugriff.
Und auch da kann man sich jetzt eben fragen,
okay, wie gehen die Systeme damit um?
Theoretisch kann X-86-Architektur, also sprich Intel-AMD-Prozessoren und so weiter,
so was hier machen. Auch da muss man sagen,
das ist letztendlich natürlich so ein bisschen historisch motiviert.
Weil also früher Arztspeicher teuer war, hat man natürlich gesagt,
naja, die 640 Kilobyte, die ich an Hauptspeicher habe,
die möchte ich auch irgendwie möglichst gut ausnutzen.
Demzufolge kam es dann eben vor,
dass letztendlich die Datenstrukturen wirklich im Speicher aufeinanderfolgend irgendwo abgelegt wurden
und es dann eben zu solchen Verschnittssituationen gekommen ist
Für die Performance ist sowas natürlich tödlich,
weil wenn ich jetzt also hier quasi dieses eine Wort rauslesen will,
muss ich nicht nur einmal aus dem Speicher was rauslesen,
sondern wirklich von zwei unterschiedlichen Adressen zweimal.
Nicht nur das Ganze dann also über irgendwelche Maskier- und Schiebeoperationen
wieder zu irgendeiner Datenstruktur oder zu irgendeinem Wert zusammenbauen. Wie gesagt,
theoretisch würden X6-Nazi-Prozessoren das machen, rein praktisch,
muss ich sagen, kenne ich ja inzwischen keinen Compiler,
der sowas mehr irgendwie erzeugen würde,
sondern das wird inzwischen gesagt nicht, okay,
ich habe mehrere Gigabyte Hauptspeicher und wenn dann eben hier irgendwo ein Teil leer bleibt,
weil ich jetzt also hier nur entsprechend kleinere Datenstrukturen habe oder so weiter.
Gut, so what, nicht das nächste Speicherwort,
landet dann eben auch immer dann wieder hier. Wie gesagt,
bei anderen Prozessoren, also bei Spark-Prozesse war es so,
also da war sowas gar nicht möglich,
da würde das dann also auch mit irgendeiner Sparcherschutzverletzung letztendlich aussteigen.
Gut, eine andere Sache, die dann in den Zusammenhang
mit dem Speicher dann eben auch noch wichtig ist,
ist dann der Begriff der Memory Map.
Dazu muss man jetzt einfach nur wissen, wenn ich jetzt sage,
ich habe beispielsweise jetzt bei einer 32-Bit-Architektur die 32-Bit zur Verfügung,
um damit breitweise Speicher zu adressieren.
Kann ich demzufolge 2 hoch 32 Byte Hauptspeicher adressieren?
So, das sind vier Gibibyte. So, inzwischen haben wir
aber nicht mehr 32-Bit-Architekturen, sondern 64-Bit-Architekturen. Das heißt,
das, was ich theoretisch an Speicher adressieren kann,
finde ich selbst in irgendwelchen riesengroßen Servern oder Workstations nicht praktisch verbaut,
weil das eigentlich niemand bezahlen kann und kein System letztendlich so viel speichert als linear adressieren,
wann spare ich ja hart.
Das heißt, das,
was man daran erst mal wissen muss, ist das,
was ich im Prinzip an Speicheradressen in den Programmiersprachen machen kann,
größer ist als das, was ich physikalisch als Speicher verbaut habe.
Das, was dann auch immer noch passiert,
ist, dass im Prinzip über die Hardware,
das hatte ich also letzte Woche auch schon kurz vorgestellt,
beispielsweise sowas wie Reed Wright und Reed-Only-Bereiche quasi in den Speicheraddressen getrennt sind.
Also das war dann also am Beispiel des Arm-Prozesses vorgestellt,
wo man sagt, okay, ich habe hier meinen eigentlichen Arbeitsspeicher als Rahmen.
Ich habe da noch irgendwie einen Speicherbereich als Rahmen.
Da kommt dann eben quasi sowas wie Bootloader,
Start-up-Code oder eben irgendein festes Programm mit rein,
dass man sowas da dann entsprechend mit reinbringen kann. Das,
was man dann typischerweise auch immer noch macht, ist,
dass Dadurch, dass ich eigentlich von den Adressen her sehr viel mehr Speicher habe als das,
was verbaut wird, dass eben beliebige,
ein Ausgabegeräte quasi in den Hauptspeicherbereich eingeblendet werden.
Das ist das, was sich dann eigentlich Memory Map nennt. Das heißt,
ich habe dann eben bestimmte Adressen oder Adressbereiche,
mit denen spreche ich dann eben nicht den Hauptspeicher an,
sondern mit denen spreche ich die Grafikkarte an oder mit denen
spreche ich die irgendeine serielle Schnittstelle mit an
Das hat eben den Vorteil, dass im Prinzip lese Befehle,
beziehungsweise teilweise eben auch Schreibbefehle, je nachdem, was da nun Sinn macht.
Theoretisch auf den Hauptspeicher passieren, rein praktisch,
ich damit dann aber eben beliebig viele Geräte ansprechen kann und
ich in meinem Befehlssatz jetzt nicht für jedes Gerät oder Geräteklasse irgendwelche Spezialbefehle habe oder haben muss,
um zu sagen,
sprich mir mal die serielle Schnittsteller oder die USB-Schnittstelle an,
an der die Maus hängt,
sprechen wir mal die Schnittstelle an,
an der das und das sein und Ausgabegerät geht
Hängt, sondern das passiert dann eben alles über den Hauptspeicher,
weil also quasi sämtliche Geräte in diesem Fall dann eben in
Form der Gerätetreiber quasi in den Speicherbereich eingeblendet werden.
Das ist das, was man dann als Memory Map IO bezeichnet. So,
und das, was die Betriebssysteme dann eben im Prinzip machen,
ist, dass sie zum einen eben die Adressen zu dem
physikalisch vorhandenen Speicher irgendwie zuordnen und dass sie eben wirklich sämtliche Hardware-Komponenten Eben dadurch,
dass die Treiber das letztendlich machen, dann eben auch in den gesamten Adressraum mit einblenden.
Also wie gesagt, dies war jetzt,
dass ich nochmal diese Folie von dem Arm,
hatte ich ja im Prinzip letztes, letzte Woche ja kurz aufliegen,
wo man sieht, okay, also ich habe hier Essrahmen,
ich habe hier Rom in diesem Fall unterscheidet sich,
er saß jetzt also hier überein, hat Restbild,
was da gemacht wird,
ich würde dann eben letztendlich in Hardware gemacht.
Gut, hier als Beispiel nochmal, wie jetzt also von
Seiten der Betriebssysteme, Speicher verwaltet oder adressiert wird.
Also hier ein Beispiel natürlich nicht mehr so ganz aktuell.
Windows 95, als ein Beispiel jetzt für ein 32-Bit-System,
also 32-Bit, kann ich vier GB letztendlich mit adressieren.
Und da war es halt eben so,
dass man gesagt hat, okay, in dem unteren Bereich,
das ist jetzt nochmal irgendwie Kompatibilität zu den Rechnern von vor 30 Jahren.
Dann gab es also im Bereich,
war ich dann immer irgendwie auf gerade Adressen kommen musste,
wurde eigentlich dann also nicht weiter benutzt
Also wie gesagt, früher hatten die Rechner eben 20-Bit-Adressen.
Nicht deswegen, da komme ich dann eben genau bis hier.
Dann kommen nochmal knapp zwei Gewiebite für Anwendung.
Das ist dann eben das, wo dann also letztendlich also
irgendwelche Datenstrukturen aus den Programmen quasi abgelegt werden.
Und dann gibt es eben nochmal ein GB für gemeinsam genutzte Bibliotheken.
Das, was in Windows, diese DLL,
Dynamic Link Driverys sind, beziehungsweise ANGB,
wo dann also letztendlich das eigentliche Betriebssystem sich mit verbirgt
Und wenn man da dann eben guckt, beispielsweise dann über die Systemsteuerung,
dann kann man eben ganz gut also eigentlich sehen,
wie jetzt also hier irgendwelche, ein Ausgabegeräte,
nicht also Systemplatine, das hier ist also PCI-Bus,
das wäre also eine Grafikkarte gewesen, in Speicheradressen abgebildet werden.
Und die Zuordnung passiert dann eben teilweise von Bios dann teilweise natürlich dann eben auch entsprechend vom Betriebssystem,
wo dann letztendlich jeder Treiber da irgendwo geladen wird,
dann eben in irgendeinem Speicherbereich hier in diesem Bereich dann eben letztendlich dann nachher landen wird.
Gut, jetzt kann man sagen, na gut,
Windows 95 nicht mehr so ganz aktuell,
hier das Ganze mal als Screenshot vom heimischen Windows 10-Rechner.
Also auch da sieht das so aus,
dass sie mir also hier im Gerätemanager einmal angucken kann,
Arbeitsspeicher und sehe dann, wenn man das also hier entsprechend aufklappt,
unter welchen Adressen, also hier sieht man schon ein 64-Bit-System,
da sind die Adressen ein bisschen länger,
unter welchen Adressen,
welche Teile Hardware dann also irgendwo quasi eingeblendet werden
Gut, und das geht dann also hier unten noch beliebig weiter.
Nicht hier habe ich dann eben eine Ausgabe hinterrab und,
und, und. Also alles passiert dann eben bei dem Betriebssystem,
also nicht nur Windows, sondern auch Linux machen das so,
bei dem Betriebssystem dann also quasi über diese Speichereinblendung.
Und das, was dann sich da dann eben immer noch funktional jetzt erstmal vorstellen muss,
ist, dass das Ganze eben natürlich eine mehrstufige Abbildung ist.
Das heißt, zum einen werden im ersten Schritt also Hardware-Komponenten an Ausgabeeinheiten und Interraps,
also irgendwo in den gesamten 64-Bit-Adressbereich, passend verteilt.
Und zum anderen ist da natürlich das Betriebssystem, das jetzt also sagt,
okay, was ist jetzt dann eben noch physikalischer Speicher?
Und das, was ich jetzt eben wirklich an physikalischem Speicher
jetzt für Programme oder für das Betriebssystem nutze,
wie wird das dann eben noch entsprechend abgebildet?
Ich hatte hier dann auch noch mal so einen Zugriff,
wo man dann also sehen kann, wie jetzt,
also in diesem Fall auch Windows, jetzt hier so ein insgesamt,
also der physikalisch vorhandene Speicher, benutzt wird.
Also hier unten, das sieht man halt kaum was,
also ein bisschen was, was also in diesem Fall dann
also irgendwie so hart war, AO ist.
Nicht dann das, was jetzt also vom Betriebssystem und von
Programmen benutzt wird. Und dann eben noch letztendlich,
also in diesem Fall viel freier Speicher und so ein paar Sachen,
die dann also noch so quasi als Zwischenspeicher vorgehalten werden,
bei Linux-Rechner sieht das Ganze im Prinzip genauso aus.
Also ich habe hier im Hintergrund dann immer irgendwie diesen So ein XOS-VU nicht,
wo man dann eben auch sieht, also in diesem Fall,
dass wir jetzt hier unter Mem, der Hauptspeicher,
also entsprechend der Teil hier wird jetzt wirklich rein praktisch benutzt.
Welchen Tal ist dann eben vom Betriebssystem noch entsprechend verwaltet und
ansonsten ist hier noch relativ viel frei oder Teil der,
also auch nicht benutzt wird in das Betriebssystem auch nochmal quasi als ein Zwischenspeicher für andere Sachen noch mit.
Also in diesem Fall Datei, Ein- und Ausgaben dann
als Cash verwendet
Gut, generell, hier auch noch mal, also die Folie wird
sich also auch noch ein paar Mal wiederholen. Aufgezeichnet,
also im Prinzip das, was man erst mal so als Speicherhierarchie bezeichnet,
wo man eigentlich immer sagen kann, okay,
ich fange hier mit sehr schnellem Speicher an,
auf den ich quasi mit voller Prozessorgeschwindigkeit zugreifen kann.
Der ist aber eben vergleichsweise klein und ist vergleichsweise teuer in einem System,
nämlich das, was ich also jetzt wirklich als Register in Form von Flipflops in meiner CPU drin habe.
Nicht dann habe ich Esram-Speicher, wow, haben wir letzte Woche gelernt, was das ist. Esram-Speicher,
also spreche ein bisschen aufwendiger, sechs Transistoren pro Speicherzelle,
mit denen ich dann also quasi meinen sogenannten Cash-Speicher mache,
der dann eben quasi von Level 1 bis Level 3 dann eben immer größer wird,
dann eben das, was wir eigentlich als Hauptspeicher bezeichnen,
nämlich dann das DRAM bzw. SDRAM, also Synchron ist DRAM,
was dann also mit solchen Eintransistor-Speicherzellen arbeitet.
Und dann kann ich eben noch sagen, okay,
ich habe dann noch Entweder Magnetfestplatten oder SSDs als lokalen Massenspeicher,
beziehungsweise das ist dann auch der Speicher,
den ich dann natürlich nur noch zur Verfügung habe,
wenn das System quasi stromlos ist, weil alles bis hier wird er nämlich vergessen.
Und im weiteren Sinne kann ich dann natürlich irgendwie sowas wie irgendwelche Webdienste,
Cloud-Anbieter und, und, und dann noch mit dazunehmen und sagen,
also damit habe ich dann eben noch entsprechend noch günstigeren Speicher,
wo dann aber,
was man hier eigentlich auch immer sieht,
jedes Mal dann die Zugriffszeiten,
also auch immer entsprechend deutlich größer werden
Nicht, das ist also das, was dann immer als Speicherhierarchie bezeichnet wird.
Wie gesagt, Cash-Speicher ist hier auch nochmal eine Folie,
wird sie nachher dann nochmal wiederholen. Deswegen würde ich das
hier relativ schnell machen. Cash-Speicher ist eben letztendlich das,
wo ich sagen kann,
ich habe hier in der Alu mit voller Prozessorgeschwindigkeit meiner Register,
mit denen ich oder in der CPU mit voller Geschwindigkeit meiner Register,
auf die ich zugreifen kann.
Der Hauptspeicher hier ist eben um den Faktor 100 ungefähr langsamer und
eben um diesen Geschwindigkeitsunterschied auszugleichen, sieht man eben zu,
dass die Programme in der Regel entweder nur mit Registern arbeiten oder mit Daten,
die sich also hier drin befinden.
Und dann eben über immer langsamer werdende Speicher dann, also quasi First-Level-Senken,
Level-Third-Level-Cash dann irgendwann nachher das Ganze dann eben in den Hauptspeicher quasi eingeblendet wird.
Und was man jeder natürlich immer schon sieht oder was da so ein bisschen die Problematik bei dem Ganzen ist,
dass ich natürlich immer sagen kann, gut, Diesen Tal hier,
nicht, das ist der Speicher, wo ich sage,
wunderbar, hier in dem Rechner sind also irgendwie 8 Gigabyte Speicher drin.
Auf der anderen Seite ist der Cash-Speicher natürlich nicht so groß.
Wenn ich jetzt aber vom meinem Programm bzw. von allen laufenden Prozessen,
vom Betriebssystem, mehr Speicher benötige als das,
was eigentlich der Cash-Speicher zur Verfügung stellt,
nach welchen Kriterien wird jetzt eben ausgewählt,
welche Daten quasi in den Cash kommen sollen,
beziehungsweise wenn der Cash irgendwie voll ist und ich jetzt also irgendwelche anderen Daten brauche,
was kann ich hier von rausschmeißen?
Sprich, das ist dann eben nur noch im Hauptspeicher und
ich habe dann eben hier diesen entsprechend kleineren Speicher dann eben auch irgendwie sinnvoll gefüllt.
Denn das ist dann etwas,
was dann eben dem Teil Rechnerarchitektur 2 dann nochmal so ein bisschen beleuchtet wird,
wo es dann darum geht, wie solche Abbildungen stattfinden,
wie der Cash beispielsweise mal rein technisch funktioniert und sowas
Ja gut, ansonsten,
wie gesagt,
kann man eben immer nur sagen,
also auch dies im Hintergrund so ein bisschen Wissen zum Speicherspeicher,
die Hierarchie sollte man wissen als Programmierer beziehungsweise im Hinterkopf haben,
um zum einen jetzt also erstmal überhaupt vielleicht seine Programme so zu schreiben,
dass sie also nicht andauernd irgendwo mit irgendwelchen Datenstrukturen Speicher aluziieren und nie freigeben.
Dann hat man
das berühmte Speicherleck
Wenn ich viel Speicher habe und das Programm nur kurz läuft,
dann stört das natürlich nicht weiter. Wenn ich sowas in irgendein Programm rein programmiere,
was also irgendwo auf dem Satelliten in Orbit geschossen wird,
habe ich also ein massives Problem,
weil irgendwann geht mir dann der Speicher aus,
weil also das Programm, also immer neuen Speicher anfordert,
aber irgendwelche Sachen oder Datenstrukturen, die nicht mehr benötigt werden,
dann also quasi nie wieder freigibt.
Nicht, dass man sowas macht. Da muss man eben auch sagen,
also das sind dann eben auch gerade diese Sachen, sowas herauszufinden,
zu debuggen, ist dann eben auch nicht so ganz einfach,
sollte man sich dann eben entsprechend deswegen dann also auch sorgfältig damit umgehen.
Ja, dann, wie gesagt,
hat man Zwischenspeichersystem und Programmen eben auch einiges an möglichen Wechselwirkungen,
eben in Bezug auf die Performance,
weil sowohl Cash als auch die Konzepte von Virtual Memory
können dann eben entsprechend die Programmleistung doch relativ stark beeinflussen.
Deswegen sollte man das eben zumindest grob im Hinterkopf haben
Gut, ja, das war es jetzt eigentlich erst mal an dieser Stelle zum Speicher.
Wie gesagt, was man wissen soll, Big Andy,
Little Andien, Alignment, generell so diese Probleme,
was da passieren kann, im Remaped IO,
nicht also mit denen begriffen sollte man dann eigentlich jetzt was anfangen können.
Gut, kommen wir jetzt zu dem Befehlssätzen. Dazu würde ich jetzt
also erst mal nochmal so auch nochmal wieder relativ schnell,
weil Wiederholung, den Befehlszyklus vorstellen,
da noch ein bisschen was zu den Befehlsklassen sagen und dann eben nachher dann noch auf die Adressierungsarten entsprechend eingehen.
Ja, Befehlszyklus basiert eigentlich von der Idee her eben ja auch immer auf diesem Fonorman-Prinzip.
Ich habe Daten und Befehle gemeinsam Speicher, Befehl wird abgearbeitet,
dadurch, dass ich quasi der Reihe nach dem Befehl hole,
Befehl dekodiere, Operanten hole, das, was der Befehl macht,
quasi das Berechnen ausführe und gegebenenfalls dann eben den nächsten Befehl mache.
Das, was man dafür rein technisch braucht, wie gesagt,
diejenigen, die das Praktikum jetzt schon gemacht haben,
wären das also dann natürlich schon Wissen für den Deko-Prozessor,
dass man sagen kann, also in dem Steuerwerk,
das heißt also in dem Tal, der die Befehle abarbeitet,
brauche ich natürlich sowas wie überhaupt erstmal einen Befehlszähler und eben das ein oder mehrere Instruktionsregister,
wo dann also quasi der Befehl,
der aus dem Hauptspeicher gelesen wird, landet.
Und in dem Rechenwerk kann man jetzt eben sagen,
brauche ich zumindest sowas wie so ein Register am Ausgang der Alu,
um Zwischenergebnisse bevor ich das Ganze wieder irgendwie in den Speichel zurückschreibe,
zwischen zu speichern, das, was sie also Akkumulator nennt.
Rein technisch kann man das heutzutage streichen. Da hat man eigentlich
eine Registerbank mit 32 oder noch mehr Registern zur Verfügung,
mit denen man dann also quasi dann mit entsprechenden Registern direkt arbeiten kann.
Ja, Befehlszyklus, wie gesagt, wie muss man das jetzt mal vorstellen?
Also bauen wir viel holen. Ich habe den Programmzähler,
da steht eben drin, welcher Befehl soll als nächster ausgeführt werden.
Damit wird der Speicher adressiert, der Befehl wird von dieser Speicheradresse geladen,
landet im Befehlsregister und gegebenenfalls entweder hier oder eben vielleicht auch später,
wird dieser Programmzähler inkrementiert. Wenn ich einen 32-Bit-System habe,
passiert also quasi Speicherzugriff, Inhalt von Programmzähler lesen,
auf Instruktionsregister schreiben und dem Befehlszähler um vier inkrementieren,
weil in diesem Fall waitweise Adressierung das nächste Speicherwort wäre dann also vierbyte weiter.
So, dann ist das Ganze jetzt wieder davon abhängig,
beim Befehlssatz ist das ein sogenannter Rissbefehlsatz,
wo also quasi jetzt mit einem Speicherwort genau immer ein Befehl auch beendet ist.
Bei X-86 habe ich eben Befehle,
die jetzt also mehrere Speicherworte beinhalten,
gegebenenfalls muss ich dann also quasi nach diesem ersten Lesen feststellen,
aha,
der Befehl geht noch weiter und dann das nächste und übernächste und noch ein Wort lesen,
je nachdem wie lang der Befehl ist.
Ich demzufolge kann es sein,
dass man da dann eben auch zumindest logisch gesehen mehrere Befehlsregister
hat bzw.
zu unterscheiden hat
Gut, im nächsten Schritt befehlen steht also jetzt im Befehlsregister.
Dort wurde eigentlich dekodiert, da wird also quasi festgestellt, was soll passieren?
Mit welchen Operanten? Und für die entsprechenden Funktionseinheiten,
also sprich irgendwelche Multiplexer, irgendwelche Steuersignale, für die Alu
und so weiter, wird das Ganze dann quasi beschaltet.
Und gegebenenfalls werden dann eben auch noch die Operanten geholt,
nicht weil in den Befehlsregister steht jetzt eben schon drin,
mit welchen Operanten gerechnet wird
Die können aus dem Hauptspeicher kommen, die können aber auch aus irgendwelchen Registern kommen.
Ist dann also auch mal so ein bisschen von dem Befehlssatz jeweils abhängig.
Gut, anschließend wird da eigentlich ein Befehl ausgeführt,
also das, was nun Execute-Phase nennt. Sprich,
ich habe den Befehl im Fehlsregister, der de Cuda hat entschlüsselt.
Die Signale liegen an den Funktionseinheiten an. Und beispielsweise,
wenn das jetzt ein Alu-Befehl ist,
wo jetzt meinetwegen zwei Zahn addiert werden,
wird dann also quasi am Ausgang der Alu dann eben das entsprechende Ergebnis irgendwo Register,
Zwischengespeichert oder eben in irgendein Zielregister zurückgeschrieben oder in eine Speicheradresse zurückgeschrieben,
sodass es dann eben jetzt wieder davon abhängig,
um was für ein Befehl es sich handelt.
Genauso gilt das dann eben auch für die Ausführungszeit,
weil es gibt eben wie viele, die entsprechend aufwendig sind,
gegebenenfalls dann eben auch mehrere Takte benötigen.
Es gibt aber eben auch Befehle, beispielsweise wird das
wie ein No-Op, ein Befehl, der nichts macht.
Auch sowas braucht man gelegentlich mal,
wird was an meinem Pipelining
nochmal begegnen
Da passiert dann natürlich nichts weiter dann. Rein technisch gesehen. Gut,
ansonsten, um das Ganze dann technisch umzusetzen,
kann ich eben sagen, für die Realisierung von dem Ganzen,
entweder ich habe das fest verdrahtet, das heißt,
ich habe mir da jetzt also irgendwie so eine Hardwarestruktur aus den und den und den Funktionseinheiten,
die so und so miteinander verbunden sind,
wie das also beispielsweise beim Decore im Rechnerstrukturen Praktikum dann der Fall ist,
beziehungsweise wenn ich die Befehle habe,
die dann eben über mehrere Takte abgearbeitet werden,
hat man dann eben noch sowas wie Mikroprogrammierung.
Das heißt, die Abfolge dieser einzelnen Schritte,
die dann also vor jetzt hier für die verschiedenen Phasen der Befehlsabarbeitung gelten,
die dann aber auch in jeder einzelnen Phase dafür sorgen können,
dass das jetzt eben auch vielleicht mehrere Takte dauert,
wird dann eben entweder in einen endlichen Automaten gegossen,
der dann also quasi jetzt,
so wie wir das bislang hier immer irgendwie gelernt haben,
umgesetzt werden kann oder Mikro programmiert,
letztendlich auch nichts anderes als ein endlicher Automat realisiert.
Gut, wenn man sich jetzt anguckt, welche Befehle braucht man.
Zum einen möchte ich natürlich irgendwie rechnen. Das heißt,
ich habe irgendwie so die ganzen Arradmetischen Operationen, Additionen,
Subtraktionen, vielleicht Inkrement, Dekrement, Multiplikation, Division,
sofern ich sowas, also überhaupt jetzt das eigene Befehle habe.
Ich kann natürlich auch sagen, das sind Unterprogramme,
weil sollte eigentlich aus den Kapiteln zu Zahlen,
Darstellungen und Arradmetik klar sein.
Also Multiplikationen kann ich natürlich mit Additionen und Schieben letztendlich erschlagen.
Die Vision im Prinzip Auch mit Schiebe und Subtraktionsalgorithmen.
Also im Prinzip kann ich für sowas Spezial-Hardware vorsehen.
Ich kann das aber eben auch mit entsprechenden Unterprogrammen machen.
Gut, dann hat man eben irgendwie sowas wie logische Operation, diese Schiebeoperation.
Nicht, dann brauche ich natürlich irgendwie irgendwelche Vergleichsoperationen.
Also gleich und leicht, größer, größer, gleich,
was auch immer man sich da dann ausdenken mag.
Nicht, dann hat man natürlich Befehle für Datentransfer.
Zum einen, um jetzt also IO anzusprechen
Kann man haben, kann man auch über MemoryMap-Mechanismen machen,
wie ich das gerade eben ja schon angedeutet habe.
Das heißt, ich habe einfach eine Speicheradresse hinter der Speicheradresse,
verbirgt sich dann irgendein Device, irgendein Gerät,
beziehungsweise im Fall jetzt von Betriebssystemen dann, also erstmal eine entsprechende Karätetreiber.
Ich schreibe dann also an eine Adresse was rein und
der Geredetreiber würde dann eben letztendlich jetzt eben gucken,
was passiert und dann eben physikalisch dann,
also irgendwie die zugrunde liegenden Hardware dann also irgendwie ansprechen
und da was reinschreiben bzw. was rauslesen
Load and Store sind dann also quasi Sachen, um,
sofern ich Befehle habe, oder sofern ich also Register habe,
die ich jetzt also irgendwie anspreche, um jetzt Datentransfer zwischen Hauptspeicher und den Registern in der CPU durchzuführen.
Und da hat man natürlich noch, also jede Menge von Befehlen,
die man braucht, um Kontrollfluss im Programm zu machen,
also sprich Sprünge, bedingte Sprünge,
sowas wie Case oder Mehrfachverzweigung wird teilweise durch entsprechende Assemblerbefehle noch unterstützt und was man natürlich dann eben noch braucht, ist ein Unterprogrammaufrufe.
Also Call beziehungsweise Return, um unser Programm wieder zu beenden. Ja,
und dann gibt es eben noch so diverse Sachen,
die man also braucht, für den eigentlichen Ablauf des Programms,
also sprich, was passiert bei irgendwelchen Ausnahmeüberhandlungen, was passiert,
wenn das Programm letztendlich zu Ende ist und man dann im Betriebssystem eben signalisiert,
okay, ist fertig, schmeißt alles weg,
lasst einen nächsten Job laufen, nicht solche Sachen,
kann man da dann eben auch in irgendwelche Befehle bringen.
Gut, ansonsten, wie gesagt,
die Begriffe hatte ich also schon ein paar Mal hier eingeworfen,
bei den Befehlssätzen, die große Unterteilung ist eben immer für komplexe Instruction-Set-Computer,
beziehungsweise Risk für Reduced Instruction-Set-Computer.
Gut, wie sieht das mit den Befehlen bzw. der Befehlsdekodierung
jetzt aus? Hat er gesagt, in dem beispielsweise Instruktionsregist,
da haben wir jetzt also hier irgendwie so ein 32-Bit-Wort.
Das soll jetzt also irgendein Befehl sein. Was muss jetzt
die Hardware damit eigentlich machen? Jetzt kann ich natürlich sagen,
okay, ich kann jetzt also diesen Bitstring nehmen Als Adresse kann damit in einem entsprechenden Rom nachschauen und dann einfach sagen,
okay, damit soll jetzt beispielsweise,
wenn die Alu irgendwie 16 verschiedene Möglichkeiten zur Berechnung hat,
also Aditu und Subplaktion und so weiter,
soll dann eben irgendwie genau die Einstellung an der Alu gemacht werden,
genau die Einstellung jetzt an irgendwelchen Multiplexern gemacht werden,
dass damit dann eben diese entsprechenden Datenfahrdern irgendwie geschaltet werden.
So, wenn ich das jetzt aber eben, wie gesagt,
direkt außer Anna Tayvelle mir ausgucke, also einen Mikrocode-Raum,
dann müsste sie logischerweise, also für so ein 32-Bit-Befehlswort,
also zwar auch 32 Einträge haben.
Das möchte man natürlich nicht, weil das also schon unsinnig groß ist.
Deswegen werden die Befehle dann eigentlich noch mal logisch unterteilt,
dass man sagt, von diesen 32-Bit habe ich eben einen Teil für meinen eigentlichen Befehl.
Also sprich, dieses hier und habe dann eben noch einen Teil,
wo dann eben beispielsweise schon drin steht,
wo Operanten herkommen sollen oder wo irgendwie im Mediath-Werte,
also sprich irgendwelche Konstanten, die also hier darin benutzt werden,
dann eben direkt in dem Befehlswort kodiert sind.
Damit erreicht man das dann eben jetzt nicht ein einziges großes ROM
quasi ausgelesen werden muss, sondern dann eben entsprechend mehrere kleine Tabellen hat.
Und diese Unterteilung, das nennt sich dann eben letztendlich Befehlsformat.
Wie sieht sowas praktisch aus? Also hier nur ein theoretisches Beispiel natürlich,
weil, also wie gesagt,
das Ganze hier aussieht und wo was unterteilt ist,
ist natürlich jetzt genau vom Befehlssatz abhängig.
Also ob das jetzt ein Armprozessor ist, ob das ein X86-Rechner ist,
ob ich das jetzt von MIPS mache oder, oder, oder.
Grundidee ist aber eigentlich immer, dass man sagen kann,
also beispielsweise in diesem Fall nehme ich hier die oberen 8 Bit,
um damit beispielsweise jetzt 286 unterschiedliche Befehle zu kodieren.
Nicht, das kann ich noch relativ einfach über irgendwelche Tabelle nachschlagen,
was der Befehl ist. Und dann habe ich eben beispielsweise,
wenn ich sowas jetzt wie ein Datentransfer habe oder ein Register soll mit einem Wert geladen werden,
dann eben hier in einem bestimmten Bereich beispielsweise die Adressierung von 5 mit meinetwegen von Registern.
Damit kann ich dann demzufolge 32 Register unterscheiden und hätte dann
also hier noch beispielsweise jetzt in diesem Fall 16 Bit,
um jetzt also irgendeinen Emediate-Wert,
also sprich eine konstante in diesem Fall,
dann eben letztendlich sowas wie eine konstante 8 in das Register
14 reinzuschreiben
Wenn das jetzt also beispielsweise sowas wie so ein Load-E-Mediat wäre.
Gut, und je nachdem, welche Befehle es hier sind,
habe ich dann eben eigentlich in der Regel immer konstant meinen Ob-Code.
Und dann hier hinten diese anderen Felder werden dann eben benutzt,
um beispielsweise zu goodieren, welche Alu-Operationen gemacht werden soll, welche Register angesprochen werden.
Sprich, wenn ich jetzt so einen Befehl habe,
wo jetzt also quasi mit drei Registern gerechnet wird,
zwei für die Argumente eins, für das Ergebnis,
nicht könne ich das dann natürlich auch mit dreimal fünf Bit irgendwo rein kodieren,
wenn ich Speicheradressen zugreife, kann ich dann eben hier entweder Speicheradressen dann also auch teilweise mit reinschreiben oder, oder.
Also letztendlich, die Aufteilung ist dann aber eben genau von dem jeweiligen Befehlssatz abhängig.
Gut, das war es jetzt hier noch so kurz an Befehlssätzen vorgestellt wird,
hat er schon gesagt. Ein bisschen war es jetzt,
war das also ein sehr schöner einheitlicher Befehlssatz ist,
also dieser Risk-Architektur, da sind nämlich genau alle Befehle
32 Bild lang und es gibt auch nur genau drei Befehlsformate.
Wie gesagt, Deko ist RSB-Praktikum mit drin, 16-Bit-Befehlssatz und X86-Architekturen,
das wird uns dann also im nächsten Kapitel noch kurz begegnen.
Nicht wo es also darum geht, zu sehen,
wie da so ein bisschen die Befehle aussehen,
ist dann auch so ein klassisches Beispiel von sehr schicken,
irregulären Sisk-Befehlssatz, wo man sehr viele sehr unterschiedliche Befehlsformate hat.
Nicht wohl, da gibt es Befehle, die sind genau einbart lang.
Es gibt Befehle, die sind 36 bald lang,
je nachdem, was das letztendlich ist.
Wie gesagt, wenn ein sowas dann noch weiter interessiert,
beziehungsweise einigen von den Folien oder von den Unterlagen habe ich
dann also auch entsprechend aus diesem Intel-Ia
64. Dem hier Architecture Software Developers, Reference Manual,
da steht dann also für einen X86 Prozesse wirklich alles drin.
Alles, was man für die Assembler-Programmierung wissen muss,
ist also ein schönes kleines Dokument,
was also mein Foliensatz hier noch locker schlägt,
mit etwas über 5000 Seiten
Nicht, also, wie gesagt, wenn man x86 Assembly-Programmierung
mal genau machen möchte, dort steht alles drin. Gut,
ja, also, jetzt war ich aber hier bei den Befehlsformaten,
also wie gesagt, x86 ist dann natürlich entsprechend kompliziert,
wie man also allein schon an dem Umfang natürlich sehen kann.
Gut, hier jetzt nur ans kleines Beispiel jetzt eben für
was vergleichsweise einfaches, diese Nips. Alle Befehle sind 32
Bit lang. Der Ob-Code ist immer sechs Bit breit,
nicht demzufolge kann ich dann immer quasi 64 verschiedene Befehle gibt
es dann nur
Damit werden dann also auch unterschiedliche Adressierungsarten mit beschrieben. Mit Adressierungsart ist gemeint,
wenn ich jetzt also beispielsweise sowas habe,
wie ich mache einen Zugriff auf den Speicher, wo ich dann eben sage,
ist das ein Emediate-Wert, womit ich dann natürlich,
also im Zweifelsfall auch gar nicht alle Speicheradressen ansprechen kann,
bei 32 Bild, ist das ein Register.
Ist das also eine Art Adressierung, wo ich sagen kann,
ich habe einen Register als Basis von dem Ganzen,
wo ich also quasi sowas wie eine Startadresse angeben kann
und habe dann noch mit einem Emediate meinetwegen minus irgendeinen Wertebereich,
wo ich dann so ein Offset einstellen kann.
Nicht sowas wird also zum Beispiel ganz gerne verwendet,
wenn man jetzt in seinen Datenstrukturen im Programm sowas wie Arays hat und da irgendwie was durchläuft,
wo ich dann eben beispielsweise sagen kann, Element null,
das wäre dann die Startadresse, die wird irgendwo im Register hinterlegt.
Und wenn ich dann das nächste, übernächste,
über übernächste haben muss, dann muss ich quasi immer
nur Startadresse plus null plus 4 plus 8 plus 12
und so weiter dann eben für die entsprechenden anderen Elemente mit angehen.
Gut, ja, und es gibt eben entsprechend wenig Befehlsformate,
also quasi dieses Registerformat für Al-O-Operationen und dann eben Emediate und Jump-Format,
womit dann also quasi diese anderen Sachen sind.
Ansonsten, also die Smips auch ordentlich mehr ganz neu,
ist aber im Prinzip der Protototyp eigentlich so einer sogenannten Risk-Architektur,
wurde eben von den Herren Hennessey und Peterson,
die also hier dann auch immer irgendwie gelegentlich mal in irgendwelchen Literaturverweisen mit auftauchen,
Anfang der 80er-Jahre entwickelt.
Da ist eben wirklich die Idee, alles ist 32 Bit breit.
Und alle rächen Befehle, funktionieren eben nur mit Registern.
In der Architektur gibt es 32 Register und Speicherzugriff,
also Zugriff auf den Hauptspeicher, funktioniert nur mit Load- und Store-Befehlen.
Das heißt, ich kann jetzt nicht sagen,
ich habe einen Alu-Befehl und die beiden Operanten für die Alu,
also beispielsweise eine Addition, direkt aus dem Hauptspeicher.
Und das Ergebnis landet direkt im Hauptspeicher. Das kann ich
bei X86-Assembler problemlos machen. Bei Riska-Architekturen geht das nicht,
sondern da muss ich immer aus dem Hauptspeicher erinnern,
Register lesen. Anschließend kann ich dann eben Alu-Befehl machen.
Der arbeitet immer nur auf Registern und dann muss sie
das Ergebnis wieder in den Hauptspeicher zurückschreiben.
So wie man an dem Beispiel dann eigentlich auch schon sieht
oder sich denken kann,
brauche ich quasi jetzt für die Abarbeitung eines Befehls bei Risk
demzufolge vielleicht
mehr Befehle
Weil ich das jetzt also nicht in einem Schritt machen kann,
was ich bei X86 in einem Schritt machen kann.
Dafür ist das Ganze aber eben sehr viel regulärer.
Und diese Umsetzung in mehreren Schritten macht heutzutage natürlich typischerweise der Compiler.
Da war ich selber, wenn wir jetzt also nicht
den Spaß antun und da irgendwie ihr Sambler-Code programmieren.
Nicht, sondern ich habe mein Hochsprachprogramm, lass das entsprechend übersetzen. Und das,
was hinterher ein Assembler-Code rauskommt, muss ich dann also im Worst Case,
wenn ich also irgendwie debugge, natürlich dann nochmal irgendwie dran gucken.
Aber ansonsten, dementsprechend nicht. Gut, das ist also das,
was sie hier mit Loadstore-Architektur gemeint ist, also quasi immer nur Register,
haben Zugriff oder Speisezugriff geht eben nur Load und Store in Register.
Ja, ansonsten eben entsprechend einfacher Befehlssatz. Gut,
32 Register hatte ich ja schon gesagt,
Besonderheit bei den Mips ist ja noch halt was,
es gibt also ein Register, was also konstant null ist,
da kann ich nicht mal was reinschreiben,
physikalisch gibt es das eigentlich auch nicht.
Das kann man aber zum Beispiel benutzen,
also ich habe auch erst mal gedacht, was soll das Ganze,
um damit also zum Beispiel zu sagen, okay,
ich kann damit sowas wie Pseudobefehle machen, Um beispielsweise zu sagen,
ich möchte einen Wert oder einen Wert eines Weltzahlen in einem Register negieren.
Jetzt kann ich sagen, ich kann einen Befehlssatz dafür eigentlich
irgendeinen eigenen Befehl vorsehen. Hier könnte ich jetzt eben sagen,
Subtraktion R5 ist gleich R0 minus R5. Nicht, das ist immer null.
Und quasi das Negieren passiert dann eben in der Alu einfach
auch durch so eine Subtraktion. Und das Ergebnis landet wieder
hier und dadurch habe ich dann eben das Negieren gemacht.
Nicht, wenn ich einen Wert gleich oder einen Register mit null initialisieren möchte,
kann ich das einfach über so eine Addition machen.
Das heißt, für so ein paar Sachen können also selbst
solche Zuerst vielleicht abstrus Aussehenkonstrukte, also irgendwie sinnvoll sein.
Was Mipster auch noch hat, ist, dass das
im Prinzip jetzt nicht so was wie explizite Flex gibt.
Also Flex ist, dass sich jetzt also aus der Alu-Information bekomme über das Ergebnis von Rechenoperationen.
Typischerweise möchte man jetzt vielleicht mal wissen, ist ein Überlauf eingetreten.
Zahlendarstellung, Komplimente, was kann da alles schiefgehen?
Nicht ist ein Überlauf eingetreten. Ich möchte vielleicht wissen,
ist das Ergebnis einer Operation Gleich null oder ist es größer null oder ist es negativ?
Weil das bräuchte man zum Beispiel für bedingte Sprünge. Ich,
wenn ich sage, if a, kleiner B,
ich dann, soll irgendwohin gesprungen werden,
wird im Assembler einfach so umgesetzt, dass man eben sagt,
es wird also letztendlich gerechnet für a, kleiner B dann,
also quasi einfach a, minus B geguckt wird,
ist das Ergebnis negativ.
Und demzufolge kann ich dann also im Prinzip jetzt
meinen bedingten Sprung machen
So, und dazu haben die Allus dann eben teilweise so was wie entsprechende Ausgänge,
wo dann eben letztendlich die passenden Schaltnetze davor hängen,
die das Ganze dann eben mit entwerten Nullen oder A1
für solche Sachen mit gesetzt werden.
Beim Maps gibt es sowas nicht,
sondern der andere gibt es dann eben nur solche Sachen,
wo ich also mit Vergleichsoperationen zum Beispiel den Wert Null oder einzelnen Register schieben kann.
Also das heißt, da gibt es dann eben entsprechende spezielle Befehle,
die dann also in dem Fordern,
also wieder Registerinhalte
So, und gut, ansonsten, wie gesagt,
das Ganze wird uns dann noch in dem Abschnitt zum Pipelining wieder begegnen,
weil im Prinzip diese grundsätzlichen Stufen sind bei der Myps-Architektur nämlich wirklich eins zu eins in Hardware umgesetzt,
wo man dann eben sagen kann,
ich habe hier lesende Instruktion,
da habe ich dann also quasi Instruction Fetch und D-Code,
hier habe ich eine Registerbank,
nach dem Dekodieren laden quasi die Argumente für irgendwelche Alu-Operationen dann hier,
während der Ausführungsphase des Befehls Da habe ich hier also quasi die Argumente für eine Alu.
Und das Ergebnis landet hier in einem Register und um das
dann eben wieder entweder hier in die Registerbank zurückzuschreiben oder um,
wenn jetzt also hier sowas wie eine Speicheradresse für ein Load oder für einen Store berechnet worden ist,
um Zugriff dann auf den Datenspeicher zu machen,
wird es dann also dort als Adresse genommen.
Und das Ergebnis, wenn jetzt also beispielsweise gelesen wurde,
landet dann also hier wieder in der Registerbar.
So und dadurch kann man also quasi über so eine Hardwarestruktur
wirklich eins zu eins diese unterschiedlichen Schritte der Befehlsabarbeitung umsetzen
Gut, hier auch nochmal zum Beispiel für diese Befehlsformate.
Also ich habe hier in diesem Fall jetzt also beispielsweise jetzt für dieses Registerformat sechs Bild für einen Obcode,
dann bei 32 Registern habe ich dann jeweils fünf Bit für
zwei Quell- und ein Zielregister und hier dann eben nochmal die Funktion,
die die Alu ausführt und gut als eine der Eigenheiten,
also in dem Mips ist,
dass man dann eben sowas wie noch irgendwie eine Schiebeoperation damit einbauen kann,
um dann also
quasi nochmal so ein Beratschiff damit anzusprechen
Anderes Format, also jetzt hier mit Imediate, wäre dann also auch hier wieder sechs Bit-Op-Code. Basisregister,
Zieleregister und dann eben noch 16 Bit für irgendwie so ein Emidiate-Wert,
um jetzt also zu sagen, die Registen, die Adresse,
von der gelesen wird, berechnet sich aus dem Register,
in dem die Adresse steht,
hier landet das Ergebnis und ich kann eben noch mit einem Offset dann eben entsprechend das Ganze eben hier noch entsprechend drauf oder runterskalieren.
So und was man eben sieht, das war jetzt eben das,
was ich meinte mit diesen einheitlichen Formaten nicht. Also wenn man jetzt diese unterschiedlichen Formate sich ansieht,
die sind eben erstmal alle vergleichsweise identisch aufgebaut,
denn das ist eben eigentlich das Schöne oder das Wasser,
wirklich straightforward ist, dass man eben wirklich immer sagen kann,
okay, mit den oberen sechs Bit habe ich meinen Befehl und dann muss ich eben jetzt nur noch weiter verzweigen,
was passiert da, was passiert da,
welche Art von Befehl ist das.
Gut, also das zu dem,
zu der Grundidee jetzt also von solchen Riskbefehlen oder Riskbefehlsätzen
Gut, M-Core war jetzt eben zum Beispiel für das,
beziehungsweise es war eigentlich das,
was Norman Hendrich in diesem Fall jetzt also genommen hat,
um daraus, also quasi jetzt hier diesen Dekor,
also diesen 16-Bit-Prozess jetzt also aus dem Praktikum mit aufzubauen.
Und da sieht das dann eben so aus,
dass man da dann auch in den Befehlen letztendlich drinstehen hat,
also irgendwie sowas.
Das ist also das,
was man als Programmierer davon
jetzt wissen muss
Ich habe 16 Register zur Verfügung, ich habe meinen Program-Counter,
ich habe sowas wie ein Carry Fleck,
wo es also quasi nach der Alu ein Carry out erzeugt
werden kann und ich das eben abfragen kann für bestimmte Sachen.
Und ich habe auf der anderen Seite im Steuerwerk
dann eben das Befehlsregister und hier irgendwelche Art Register,
die ich also brauche, um auf den Speicher den Speicher anzusprechen.
Also in diesem Fall jetzt sowas wie Adresse,
Daten schreiben oder Daten lesen, um damit der Nase entsprechend die Transfers zu machen.
Und dann gibt es eben auch einen entsprechend einfachen Befehlssatz mit
eben auch so einem ganzen Satz von irgendwelchen Befehlen.
Letztendlich ist das dann eben immer genau das,
was eigentlich so ein Instruction-Set ausmacht, welche Befehle habe ich,
wie sind die kodiert, wie sehen da diese Befehlsformate aus.
Was da dann also auch mit drin ist,
was nun teilweise auch einen anderen Befehl setzen hat,
es gibt ja eben sogenannte Pseudo-Befehle,
also sowas wie so ein Software-Entererapt oder Return von Interrap
Die heißen, oder haben jetzt hier letztendlich eigenen Namen,
können also auch so im Assembler verwendet werden,
rein technisch gesehen ist das aber nichts anderes als eigentlich ein anderer Befehl,
nur um das also jetzt quasi bei der Assembler-Programmierung ein bisschen einfacher zu halten.
Gibt es dafür dann eben nochmal sprechenden Namen.
Und auch hier wieder einen vergleichsweise einheitliches Befehlsformat,
also Allogefehle sehen immer so aus, Emediate-Befehle,
nicht dann eben auch, sodass ich ja sich den Obcode habe,
dann noch irgendwie so einen Untercode,
viel wird im Mediate und dann eben Register,
Load and Store und,
und,
und nicht
Jedenfalls, dass man da immer letztendlich gleich- oder gleichartige Befehle hat. Gut,
wenn wir jetzt bei den Befehlen oder Befehl setzen,
im Prinzip guckt, das,
was man jetzt natürlich auch immer noch wissen muss, ist,
wenn ich jetzt also beispielsweise sowas wie einen Alu-Befehl habe,
hatte ich eben schon gesagt,
als Unterschied zwischen Mips und X86-Architektur, woher kommen die Operanten?
Ich kann ja sagen, okay, die können immer aus dem Hauptspeicher kommen,
die können aus Registern kommen oder die können letztendlich sowas wie Mediat-Befehle sein.
Das ist dann eben die Art und Weise, wie jetzt also die Adressierung erfolgt.
Nicht dann gibt es in den Befehlssätzen eben die Unterscheidung,
wie viele Operanten pro Befehl, wo ich dann eben sagen kann,
okay, das was Mips war, waren sogenannte Drei-Adressmaschine.
Das heißt, ich kann in einem Befehl,
in diesem Fall jetzt ein Alu-Befehl, sagen,
die beiden Argumente und das Ergebnis sind drei unterschiedliche Register.
Ich kann aber auch sowas wie ein Null-Adress-Befehlssatz mir überlegen,
wo ich dann sage, es wird nur auf dem Stack gerechnet.
Das heißt, sie habe da wirklich nur Kellerstahlspeicher,
wo ich also mit Push- und Pop-Operationen und irgendwelchen Sachen direkt darauf arbeite.
Nicht dann kann man eine Unterscheidung machen,
jetzt bei den Operanten, wie die entsprechend adressiert werden.
Gut, Emediate ist klar. Direkte Adressierung, indirekte Adressierung. Das heißt,
da gibt es dann auch noch einiges an Unterschieden,
wie viele unterschiedliche Speicherzugriffe ich dazwischen heißt eben noch Mare.
Und das sind dann eben auch letztendlich Kriterien,
womit sich also die unterschiedlichen Rechnerarchitekturen, also Riss, die und die Architektur jetzt,
also von dem Prozessor, dann eben entsprechend unterscheiden. Ja,
und was eben auch immer noch wichtig ist bei dem Ganzen,
hatte ich auch schon gesagt, Hauptspeicherzugriff wird zwar teilweise durch die Speicherhierarchie,
also den Cash spare ich ja in diesem Fall dann aufgefangen,
rein technisch muss ich aber eben auch mal noch sehen,
Hauptspeicherzugriff ist eben deutlich langsamer als Registerzugriff.
So deswegen ist es eben so, dass es eigentlich sinnvoll ist,
jetzt in den Befehlen, wenn ich jetzt also frage,
woher kommen die Operanten, zu sagen,
das ist eigentlich sinniger mit Registern in der CBU zu rechnen und die jetzt nur mit speziellen Befehlen,
Load and Store zu füllen,
als jetzt bei jedem Befehl im Prinzip ein oder sogar mehrere Hauptspeicherzugriffe zuzulassen.
Ja, nehmen wir als Beispiel sowas wie eine Addition,
da kann ich jetzt natürlich sagen, okay,
im Maximalfall habe ich da also drei Variablen,
Kann ich natürlich jetzt auch direkt zu
Ferner Befehls, das hier gibt, sagen,
ich addiere den Inhalt von zwei Registern, schreibe,
dass die auch wieder in ein Register. Bei diesen Befehlen,
also sprich, wie viele Operanten, Frohe Befehl,
gibt es aber an dieser Stelle dann eben entsprechend die Unterschiede,
wo man dann eben die Architektur entsprechend klassifizieren kann.
Gut, hier nochmal als Veranschaulichung, wie also im Prinzip
ist es zu so einer Alu theoretisch und Datenfahrt aussehen kann.
Ich habe hier
meinen Register
Irgendwelche Alu-Eingaberegister, das Ergebnisregister und das Ergebnis
soll dann eben auch gegebenenfalls wieder hier letztendlich landen.
Ja, zur Frage, woher kommen die Operanten?
Theoretisch kann ich natürlich sagen, was X686 also auch machen kann.
Alle drei Argumente meines Alu-Befehls kommen aus dem Hauptspeicher. Das heißt,
wenn ich so drei Adressbefehle habe mit zwei Operanten und einem Ergebnis,
dass ich dafür dann eben entsprechend drei Speicherzugriffe machen kann
Könnte man theoretisch auch bauen, so was,
wo ich dann also quasi mehrere Adressdekoder habe und mehrere Speicherzellen gleichzeitig auslesen kann,
beziehungsweise, also zwei muss ich lesen,
eine muss ich schreiben, ist aber extrem aufwendig und wie gesagt,
dieser Geschwindigkeitsunterschied zwischen Alu und Speicher oder CPU und Speicher,
der wird nach wie vor dort immer noch vorhanden sein.
So,
und das ist eben so ein bisschen diese Motivation,
weswegen es also immer diese Load-on-Store-Architekturen gibt,
was also quasi in dem Rissbefehl setzen quasi eins zu eins umgesetzt ist,
dass ich eben sagen kann,
die Alu-Befehle mit drei Apparanten arbeiten eben immer nur auf Registern und Zugriff auf den Speicher geht eben immer nur mit Lot,
wo ich dann also quasi hier aus dem Speicher was rauslese und in ein Register schreibe oder mit Store,
wo ich dann eben den Inhalt eines Registers in den Speicher wieder zurückschreibe.
Das sind da dann eben erstmal so die grundlegenden Unterschiede,
die sich dort letztendlich hinsichtlich dieser beiden Klassen von Befehlssätzen ergeben
Gut, ja, mit den verschiedenen Adressierungsarten,
beziehungsweise das Beispiel, werde ich jetzt also nicht mehr anfangen,
weil da folgen noch zwei, drei weitere Folien,
die da also irgendwie einigermaßen sinnvoll dazu gehören.
Außerdem habe ich also auch schon,
kratze schon wieder am Überziehen,
deswegen soll es das für heute gewesen sein,
dann bis zum letzten Termin dieses Jahr
am Freitag und dann einen schönen Abend an