Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: KtmnjjpfjsFvzG am 15. February 2013, 14:14

Titel: Was genau ist ein Sprung?
Beitrag von: KtmnjjpfjsFvzG am 15. February 2013, 14:14
Ich lese gerade, aber ich verstehe nicht wirklich, was ein Sprung ist... Und anscheinend gibt es auch noch Unterschiede zwischen verschiedenen Sprüngen, also wie weit man springt etc.

Also meine Frage: Was genau ist ein Sprung?

mfg :)
Titel: Re: Was genau ist ein Sprung?
Beitrag von: Svenska am 15. February 2013, 14:32
Ein Sprung ist eine Diskontinuität im Programmfluss.
Oder: Ein Sprungbefehl ist ein Befehl, nach dem (zeitlich) nicht zwingend der (im Speicher) folgende Befehl ausgeführt wird.
Titel: Re: Was genau ist ein Sprung?
Beitrag von: KtmnjjpfjsFvzG am 15. February 2013, 15:04
OK. Hat das etwas mit jmpzu tun?
Titel: Re: Was genau ist ein Sprung?
Beitrag von: TheThing am 15. February 2013, 15:56
Ja, hat es. jmp steht für jump, engl. to jump = springen. jmp sorgt dafür, dass der Prozessor zur angegebenen Speicheradresse springt.
Ein kleines Beispiel:
mov eax, 0xDEADC0DE
jmp testlabel
mov eax, 0xDEADBEEF
testlabel:
#irgendetwas...
Die Prozessor wird zuerst "mov eax, 0xDEADC0DE" ausführen, danach findet er jmp (das Label ist natürlich in der Maschinensprache nicht mehr vorhanden, sondern wird durch die entsprechende Adresse ersetzt) und überspringt den zweiten mov-Befehl.
Würde der Prozessor keine Sprünge kennen, hätten wir am Schluss 0xDEADBEEF in eax, da der Prozesor aber ein braver Kerl ist und unseren Befehlen gehorcht, steht da auch schön 0xDEADC0DE drin.
Sprünge sind immer dann notwendig, wenn du von einer strikt linearen Programmausführung abweichen willst, d.h. bei Verzweigungen (if) brauchst du Sprünge, ebenso bei Prozeduraufrufen.
Allerdings gibt es mehrere Sprungbefehle, je nachdem warum genau du springen willst. Für Prozeduraufrufe z.B. gibt es afaik "call", welches dir eine Rücksprungadresse auf den Stack legt (schließlich möchte deine Prozedur die Kontrolle auch zurückgeben), dann gibt es noch bedingte Sprünge, d.h. der Prozessor wird nur springen, wenn bestimmte Flags gesetzt sind o.Ä.

P.S:  Der Assembler-Code ist ohne jegliche Gewähr, ich hab in letzter Zeit mehr mit MIPS-Assembler als mit x86-Assembler zu tun.
Titel: Re: Was genau ist ein Sprung?
Beitrag von: Svenska am 15. February 2013, 16:04
Darum habe ich dir übrigens mal Bücher zum Thema empfohlen, lieber KTvuzG.
Titel: Re: Was genau ist ein Sprung?
Beitrag von: KtmnjjpfjsFvzG am 15. February 2013, 16:05
@Svenska: Ich hab mir doch Bücher ausgeliehen, allerdings verstehe ich das Zeug trotzdem nur so halb!

Eine Frage noch: Wie springe ich in einen Hardwaretask, und vor allem, wie mache ich das, wenn ich gar kein Multitasking nutze?
Titel: Re: Was genau ist ein Sprung?
Beitrag von: Martin Erhardt am 15. February 2013, 17:02
dann gibt es noch bedingte Sprünge, d.h. der Prozessor wird nur springen, wenn bestimmte Flags gesetzt sind o.Ä.
z.b JLE und JL Für mehr Infos hierzu siehe :
http://www.lowlevel.eu/wiki/Teil_2_-_Assembler_101 (http://www.lowlevel.eu/wiki/Teil_2_-_Assembler_101) Absatz "Vergleiche und Sprünge"
Titel: Re: Was genau ist ein Sprung?
Beitrag von: Svenska am 16. February 2013, 03:10
Eine Frage noch: Wie springe ich in einen Hardwaretask, und vor allem, wie mache ich das, wenn ich gar kein Multitasking nutze?
Dazu musst du den Hardwaretask finden. Ohne Multitasking ist das ziemlich unmöglich, damit kannst du da auch nicht reinspringen. :-)
Titel: Re: Was genau ist ein Sprung?
Beitrag von: KtmnjjpfjsFvzG am 16. February 2013, 13:30
Hmm, naja, wenn ich kein Multitasking habe, ist das doch quasi ein einziger Task in Ring 0, oder?
Dann brauche ich doch nur noch einen zweiten, der in Ring 3 läuft.

Währenddessen muss ja der in Ring 0 nicht weiterlaufen, ich brauch das ja nur ganz kurz am Anfang...

Oder?
Titel: Re: Was genau ist ein Sprung?
Beitrag von: Svenska am 16. February 2013, 15:23
Hallo,

wenn du kein Multitasking hast, hast du nur einen Ring0-Task, das stimmt soweit. Allerdings kannst du diesen Task nicht anspringen, da ihm die notwendigen Datenstrukturen (TSS) fehlen. Für die CPU ist es also kein Task, sondern nur ein Haufen Programmcode. Wenn dein Kernel im Ring 0 weiterlaufen soll, musst du ihn erst zu einem Task machen; das macht man aber üblicherweise nicht.

Der Kernel erzeugt normalerweise einen (Monolith) oder mehrere (Microkernel) Ring3-Tasks und endet in dem Augenblick, wo er den Scheduler aktiviert. Jeder Task, der dann etwas vom Kernel möchte, tut das über einen Syscall, der zwar den CPU-Modus wechselt (in den Ring 0), aber kein Taskwechsel ist.

Gruß,
Svenska
Titel: Re: Was genau ist ein Sprung?
Beitrag von: KtmnjjpfjsFvzG am 16. February 2013, 16:02
Der kann doch eigentlich problemlos in Ring 0 bleiben, wüsste nicht, wo da das Problem ist...?

Meine Recherche zu TSS ergibt: http://www.lowlevel.eu/wiki/Task_State_Segment.

Aha. OK. Muss ich dann wohl machen.  :|
Titel: Re: Was genau ist ein Sprung?
Beitrag von: Svenska am 16. February 2013, 16:22
Der kann doch eigentlich problemlos in Ring 0 bleiben, wüsste nicht, wo da das Problem ist...?
Kannst du. Das ist aber unabhängig vom grundsätzlichen Multitasking.

Verschiedene Tasks sind unabhängig voneinander, das heißt sie haben verschiedene Register, verschiedene Stacks, verschiedene Program Counter, (verschiedene Dateideskriptoren, verschiedene Speicherblöcke, verschiedene ... - je nachdem, was dein OS unterstützt). Der Ring ist da eher nebensächlich. Normalerweise hat man alle Tasks in Ring 3 und führt Kernel-Code im Ring 0, aber im Kontext des zuletzt laufenden Tasks aus. Wenn du nun alle Tasks in Ring 0 verlegst, kann jeder Task dein System zum Absturz bringen, einfacher wird es dadurch aber nicht (wenn du es vernünftig implementieren möchtest).

Gruß,
Svenska
Titel: Re: Was genau ist ein Sprung?
Beitrag von: KtmnjjpfjsFvzG am 16. February 2013, 16:34
Macht ja nichts, ich hab dann ja nur einen Task (den in Ring 0), den zweiten (in Ring 3) brauch ich ja nur für VM86... (ich beende den dann einfach sofort wieder)
Titel: Re: Was genau ist ein Sprung?
Beitrag von: w_ciossek am 24. June 2013, 15:47
So wie ich es sehe, sind viele Antworten bezüglich zu einem Prozessor (80x86) geschrieben worden.
Allgemein und unabhängig vom Prozessortyp kann man sagen, daß ein Sprung nichts weiteres ist, daß ein Register welcher der Befehlszähler ist, mit einem Adresswert geladen wird. Im Prinzip kann ein Prozessor ohne Sprungbefehle auskommen, wenn beispielsweise ein Move-Befehl wie move <Programmzähler>,<Adresswert> existieren würde. Ein Jump-Befehl tut genau dieses, wo der Programmzähler nicht explizit angegeben werden muß.
Einige Jump-Befehle werden nur in Abhängigkeit von Flags ausgeführt, so daß nach einer Bedingung gesprungen wird, sofern sie erfüllt ist, oder der Jump-Befehl wird ignoriert und der Programmzähler erhöht sich um den Betrag, um den nächsten folgenden Befehl auszuführen.
Titel: Re: Was genau ist ein Sprung?
Beitrag von: Martin Erhardt am 24. June 2013, 17:49
So wie ich es sehe, sind viele Antworten bezüglich zu einem Prozessor (80x86) geschrieben worden.
Allgemein und unabhängig vom Prozessortyp kann man sagen, daß ein Sprung nichts weiteres ist, daß ein Register welcher der Befehlszähler ist, mit einem Adresswert geladen wird. Im Prinzip kann ein Prozessor ohne Sprungbefehle auskommen, wenn beispielsweise ein Move-Befehl wie move <Programmzähler>,<Adresswert> existieren würde. Ein Jump-Befehl tut genau dieses, wo der Programmzähler nicht explizit angegeben werden muß.
Einige Jump-Befehle werden nur in Abhängigkeit von Flags ausgeführt, so daß nach einer Bedingung gesprungen wird, sofern sie erfüllt ist, oder der Jump-Befehl wird ignoriert und der Programmzähler erhöht sich um den Betrag, um den nächsten folgenden Befehl auszuführen.
Ja ein unbedingter Sprung ist nichts anderes als ein mov $Addresswert, %eip in X86. Allerdings deutest du auch schon an das es bedingte Sprünge gibt etwa jnz jz jl jg etc.. Da sich auf X86 nur diese Sprünge bedingt ausführenlassen, sind Sprung Anweisungen als Implementierung von if else in den Hochsprachen unumgänglich. Interessant ist hier allerdings ARM; Dort lässt sich jede Instruktion durch einen Suffix bedingt ausführen. jz entspräche dann:

cmp r0. r1
moveq r15, #addr
Titel: Re: Was genau ist ein Sprung?
Beitrag von: kevin am 24. June 2013, 21:55
Im Prinzip kann ein Prozessor ohne Sprungbefehle auskommen, wenn beispielsweise ein Move-Befehl wie move <Programmzähler>,<Adresswert> existieren würde.
Ein Prozessor kann ohne Sprungbefehle auskommen, wenn er zum Beispiel einen Sprungbefehl hätte?
Titel: Re: Was genau ist ein Sprung?
Beitrag von: OsDevNewbie am 25. June 2013, 12:33
Im Prinzip kann ein Prozessor ohne Sprungbefehle auskommen, wenn beispielsweise ein Move-Befehl wie move <Programmzähler>,<Adresswert> existieren würde.
Ein Prozessor kann ohne Sprungbefehle auskommen, wenn er zum Beispiel einen Sprungbefehl hätte?
Nein, bei x86 ist es so, dass in den Programmzähler nicht direkt geschrieben werden kann, also dass "mov $Adresse,%eip" ein Fehler erzeugt. Ob man daraus lesen kann, weiss ich gerade nicht.
Aber wenn das möglich wäre (also das Schreiben in den IP), dann bräuchte es keine JMP-Befehle mehr.
Titel: Re: Was genau ist ein Sprung?
Beitrag von: kevin am 25. June 2013, 13:50
Nein, %eip kann man nicht in Operanden reinkodieren. Lesen oder schreiben macht dafür keinen Unterschied.

Mein Punkt war, dass du selbst wenn du den jmp-Opcode loswirst und dafür mov ..., %eip einführst, du immer noch einen Sprungbefehl hast. Der wäre dann eben als mov statt als jmp kodiert, aber das macht ihn ja nicht weniger sprungbefehlig.
Titel: Re: Was genau ist ein Sprung?
Beitrag von: Jonathan am 25. June 2013, 17:31
Ein mov ..., %eip ist nicht möglich - weil bei einem jmp noch zusätzliche Logik dabei ist, die ein Leeren der Pipeline und eine Synchronisation macht. Ansonsten würde es seeeehr tolle Effekte bei einem Sprung geben, wie z.B. sowas, dass einige der Befehle hinter dem Sprung noch ausgeführt werden (oder sogar nur Teile davon) und dann erst die neuen Befehle vom neuen eip kommen - verursacht durch Out of Order Execution und Pipelining.

Ein Sprung ist deshalb das Neuladen des IP gekoppelt mit einer Initialisierung der CPU auf die neue Adresse.


Gruß
Jonathan
Titel: Re: Was genau ist ein Sprung?
Beitrag von: kevin am 25. June 2013, 20:35
Naja, dass der Befehl als mov kodiert ist, müsste ja nicht zwingend heißen, dass es keine Nebeneffekte gibt, wenn der Zieloperand %eip ist. Aber du hast schon recht, daran hatte ich nicht gedacht und es ist ein guter Hinweis.

Beim MIPS ist das mit den Delay Slots ja noch vorhersehbar und macht auf eine gewisse Weise sogar Spaß, aber bei der Komplexität heutiger x86-Prozessoren würde ich das eher nicht wollen...
Titel: Re: Was genau ist ein Sprung?
Beitrag von: streetrunner am 25. June 2013, 21:24
Zitat
aber bei der Komplexität heutiger x86-Prozessoren würde ich das eher nicht wollen
Ich glaube x86 ist bei der Komplexität nicht alleine, letzten endlich dürfte jede CPU die mit Pipelines arbeitet davon betroffen sein wenn sie nicht wie z.B. MIPS oder Itanium auf SEHR VIEL Vorarbeit vom Compiler angewiesen ist.
Titel: Re: Was genau ist ein Sprung?
Beitrag von: kevin am 26. June 2013, 09:29
Hm, inwiefern ist MIPS auf viel Vorarbeit angewiesen? Das ist halt einfach eine ziemlich einfache CPU, die zwar eine Pipeline hat, aber die ist kurz genug und Out of Order gibt es nicht, so dass es übersichtlich bleibt.

Und ja, ich bezweifle nicht, dass es jede Menge anderer CPUs gibt, bei denen man das auch nicht selber machen will. ;)
Titel: Re: Was genau ist ein Sprung?
Beitrag von: streetrunner am 26. June 2013, 10:47
MIPS ist deshalb sehr einfach, da der Compiler die komplizierte Arbeit macht. Das soll jetzt nicht heißen das andere Compiler nicht auch optimieren (der andauernde Gebrauch von "volatile" spricht da glaube ich Bände :-D), aber bei MIPS ist es so das man gefühlt versucht hat alles was kompliziert ist und Platz auf dem Die verbraucht in den Compiler zu verlagern. Das MIPS kein Out of Order hat stimmt dann nicht mehr so ganz, da sich dort der Compiler im vorhinein darum kümmert. Des weiteren meine ich gelesen zu haben dass bei bedingten Sprüngen der Compiler dafür Sorge zu tragen hat dass nach dem Sprung die Pipeline erst mal leer ist (NOP-Befehle).
Titel: Re: Was genau ist ein Sprung?
Beitrag von: kevin am 26. June 2013, 15:30
Der Sprung wirkt erst mit einer Instruktion Verzögerung (und zwar immer), aber das war's. In diesen Delay Slot kann man entweder ein nop reinstecken oder auch eine Instruktion, die noch ausgeführt wird.

Meines Wissens werden keine Befehle umgeordnet oder ähnliches, wo man den Überblick wirklich verlieren würde.
Titel: Re: Was genau ist ein Sprung?
Beitrag von: Svenska am 26. June 2013, 15:47
Der Compiler darf (und wird, wenn er vernünftig optimiert) die Befehle umsortieren, und zwar unabhängig von der Architektur. Das macht die CPU aber noch lange nicht zu einer Out-Of-Order-Architektur.

Die-Space ist teuer und inzwischen nichtmal mehr vollständig nutzbar (Heat Envelope oder Dark Silicon, realisiert als z.B. Turbo Mode bei Intel), daher ist es schon sinnvoll, möglichst viel überflüssige Intelligenz aus der CPU zu entfernen. Außerdem muss so ein µOp-Scheduler in Echtzeit arbeiten, während ein "echter" Compiler vergleichsweise unendlich viel Zeit zum Optimieren und gleichzeitig deutlich mehr Kontext zur Verfügung hat.

Beide Ansätze existieren (vgl. Mali und PowerVR bei embedded-GPUs), was zeigt, dass es eigentlich keine Rolle spielt. Andere Metriken sind wichtiger (geworden) als Performance.