Krautkanal.com

Veröffentlicht am 2016-07-16 19:52:0 in /prog/

/prog/ 9072: Dumbernd hat Meta-Fragen

wtrsld Avatar
wtrsld:#9072

Dumbernd hat Java gelernt. Er lernte etwas über Virtuelle Maschine und So. Nicht wirklich verstanden zu dem Zeitpunkt. und vermutlich bis jetzt noch nicht richtig.
Er wusste Allerdings, dass Java in C geschrieben wurde und C in Assembler und Assembler in Maschinenkot
Dann hat er C gelernt und C hat wohl keine Virtuelle Maschine.
Dann hat Bernd auf /b/ oder /prog/ gelesen, dass man als guter Informatiker zumindest ein Bisschen in Assembler und Maschinenkot reingeschnuppert haben muss. Das hat er dann auch getan.
Bernd ist einerseits zufrieden, weil er jetzt Assembler im Lebenslauf referenzieren kann andererseits fühlte er sich nicht wirklich wie ein besserer Informatiker. Wie dem auch sei: Bernd hat sich mehrere Judenröhren-Tutorien an und schon nach dem ersten oder zweiten Tutorial war klar: Es gibt mehrere Assemblersprachen, weil viele Betriebssysteme. Irgendwann neulich hörte Bernd den Begriff Virtuelle Maschine in einem ganz anderen Zusammenhang und dann stellte sich schlussfolgern die Frage: "Moment mal. Java ist doch Systemunabhängig, weil sie eine Virtuelle Maschine hat, oder?!
C hat keine virtuelle Maschine und wenn C mit Assembler implementiert ist, dann muss C doch auch Systemabhängig sein, oder?! Aber C ist nicht Systemabhängig."

Kann ein guter Informatiker Dumbernd aufklären?

aiiaiiaii Avatar
aiiaiiaii:#9073

Nimm bitte dein Haldol.

joe_black Avatar
joe_black:#9074

C wird für Zielplattform kompiliert. Bei Java macht das der JIT.

vicivadeline Avatar
vicivadeline:#9075

> Anime-Krebs
> dumm wie Stroh

Na, wer hätte das gedacht...

tusharvikky Avatar
tusharvikky:#9076

>Er wusste Allerdings, dass Java in C geschrieben wurde und C in Assembler und Assembler in Maschinenkot

Die jeweiligen Compiler sind dies ursprünglich, Bernd. Nennt man soweit ich weiß Compiler-Bootstraping. Aber es gibt auch Python-Compiler in (R)Python und C-Compiler in C und Java-Compiler in Java. Die Java-VM wurde zum großen Teil in C(++) geschrieben. Aber der neue Compiler für dynamische Sprachen auf der Java VM names Graal wurde größtenteils in Java selbst geschrieben. Aber ich glaube dadurch verwirre ich OP nur noch meer. :3

>Es gibt mehrere Assemblersprachen, weil viele Betriebssysteme.
Es gibt verschiedene Assemblersprachen (-dialekte?), hauptsächlich weil es verschiedene Prozessorarchitekturen gibt.

>"Moment mal. Java ist doch Systemunabhängig, weil sie eine Virtuelle Maschine hat, oder?!

Man muss die Java VM nur für das jeweilige System implementieren. So wie Maniac Mansion dank SCUMM VM einfach auf verschiedenen Computern laufen konnte, weil man dort nur die VM fürs jeweilige System schreiben musste.



>C hat keine virtuelle Maschine und wenn C mit Assembler implementiert ist, dann muss C doch auch Systemabhängig sein, oder?! Aber C ist nicht Systemabhängig

Man muss für jedes System ein neues Kompilat (die .exe von mir aus) vom Quellcode übersetzen. Mit Assembler hat dies nicht zu tun. Der C-Compiler kann von mir aus auch in JavaScript oder Brainfuck geschrieben sein oder du könnte das Programm von Hand auf Papier übersetzen und dann Bit für Bit in den Computer eintippen, es wäre das gleiche.

to_soham Avatar
to_soham:#9084

>Java ist doch Systemunabhängig, weil sie eine Virtuelle Maschine hat, oder?!

Ein Java-Programm ist unabhängig, weil Java eine virtuelle Maschine hat. Solange die virtuelle Maschine auf einem System läuft, läuft auf dieser auch das Java-Programm. Stell es dir in Schichten vor, die ganzen verschiedenen Systeme werden abstrahiert, indem die JVM als Schicht dadrüber liegt.

>C hat keine virtuelle Maschine und wenn C mit Assembler implementiert ist, dann muss C doch auch Systemabhängig sein, oder?! Aber C ist nicht Systemabhängig."

Hier das gleiche, nur umgekehrt: Ein C-Programm ist systemabhängig, weil es keine virtuelle Maschine hat. Weil das Kompilat des C-Programms direkt von der CPU ausgeführt wird und die muss das verstehen.

Nochmal genauer: Die zwei verbreitesten Beispiele für "Systeme"(=Architekturen) sind x86 und ARM. eine x86 CPU (von Intel oder AMD) ist in deinem Computer oder Laptop, ARMs sind häufig in Schlaufons und Kaffeemaschinen. Da diese zwei vershiedene, unabhängig von einander entwickelte Architekturen sind, haben sie auch verschiedene Assembler"sprachen" (genauer: einen eigenen definierten Befehlssatz, wie die Assembler-Befehle heißen und was sie wie machen). Wenn du ein C-Programm kompilierst, gibst du in der Regel an, in welcher Architektur, also Assembler-Befehlssatz, die Executable übersetzt wird. Default natürlich die gleiche Architektur, auf der du kompilierst, aber man kann z.B. auf einem Intel-Rechner auch für ARM kompilieren, siehe Cross-Compiling.
Bei Java kompilierst du für die JVM. Die JVM hat sozusagen wieder einen eigenen Assembler-Befehlssatz, der über der Architektur liegt. Man kann also sagen, dass du Java für die Architektur "JVM" kompilierst. Da die JVM aber sowohl auf einem ARM als auch einem Intel rennen kann, ist dadurch die physische Endarchitektur wegabstrahiert.

Das sollte helfen.

soyeljuaco Avatar
soyeljuaco:#9087

Standard-C gehorcht dem C-Standard.

Regel Nummer 0 des C-Standards: Das ist nicht garantiert.

Zum Beispiel ist nicht garantiert, daß C compiliert wird, daß es einen Stack gibt oder daß ein Byte 8 Bits hat. Es ist eine virtuelle Maschine für Juristen.

iamglimy Avatar
iamglimy:#9088

>dann muss C doch auch Systemabhängig sein, oder?! Aber C ist nicht Systemabhängig
Nein! Doch! Oh!

iamglimy Avatar
iamglimy:#9090

>>9087
Stack ist Pflicht. CHAR_BITS==8 ist seit C99 Pflicht.

polarity Avatar
polarity:#9091

>>9072
>Kann ein guter Informatiker Dumbernd aufklären?
Keine Sorge. Ich bin schon da.

>Er wusste Allerdings, dass Java in C geschrieben wurde und C in Assembler und Assembler in Maschinenkot
Das stimmt nicht so generell. Erstmal ist Java, C, usw. eine Sprache. Das ist also eher so etwas wie Grammatikregeln, die dir bestimmte Sachen garantieren. Die sind in keiner (Programmier-)Sprache geschrieben. Das ist nur ein Standard. Wie das ganze umgesetzt ist, hängt vom Compilerhersteller ab. Ein Compiler macht nichts anderes als den Code zwischen den Sprachen zu übersetzen. Im Prinzip wäre jede Richtung denkbar C in Assembler, C in Maschinencode, Assembler in C (auch C in Java, obwohl das einige Probleme bereiten würde). Der gcc übersetzt beispielsweise C-Kot in Assembler-Kot. Der gas (im gcc-Paket enthalten) übersetzt Assembler-Kot in Maschinensprache. Letzterer ist übrigens in C geschrieben.
Besser wäre es also wenn du dich fragen würdest: Ist ein C-Compiler in Assembler geschrieben?
Die meisten C-Compiler sind in C geschrieben (z.B. gcc). Aber alles ist möglich. Man könnte beispielsweise einen C-Compiler in Maschinencode schreiben, oder einen C-Compiler in Java.

>systemabhängig, systemunabhängig
Zunächst sollte man sich fragen was damit gemeint ist. Es gibt nämliche unterschiedliche Auffassungen davon.
Systemunabhängig heißt: Wenn ich ein Programm schreibe, dann funktioniert das auch auf einer anderen Architektur und der geschriebene Code muss nicht abgeändert werden. Wenn ich beispielsweise ein C-Programm für einen Intel x86 schreibe, dann kann ich meinen Quellcode auch auf einem ARM oder MIPS-Rechner übersetzen und benutzen (natürlich nur wenn ich nicht irgendwelche dreckigen C-Schweinereien mache, die sich nicht nach dem Standard richten). C ist also systemunabhängig.
Für Assembler funktioniert das nicht. Wenn ich ein Assemblerprogramm für einen x86 schreibe, dann kann ich nicht einfach den Quellcode auf einem MIPS-Rechner übersetzen und ausführen.
Wichtig ist: Der Quellcode ist unabhängig vom Rechner, der übersetzte Code muss es nicht sein (der ist ja schließlich nicht mehr in C geschrieben).
Also
Ich schreibe programm.c
Ich übersetze programm.c auf einem x86 und erhalte programm_x86.s
Ich übersetze programm.c auf einem MIPS und erhalte programm_mips.s
programm.c bleibt beide Male gleich (C ist systemunabhängig). programm_x86.s und programm_mips.s unterscheiden sich (Assembler ist systemabhängig).

Obwohl C systemunabhängig ist, können die ausführbaren Dateien (.exe oder ähnliches) nicht wiederverwendet werden. Sie sind schließlich keine C-Programme mehr, sondern Maschinenkot. Es muss also auf jedem Rechner neu übersetzt werden.
Java wählt deswegen einen anderen Ansatz: Die Javaprogramme werden nicht in Maschinenkot übersetzt, sondern in den Java-Bytekot. Dieser ist wiederum systemunabhängig. Aber er kann nicht direkt in den Prozessor gefüttert werden, weil es eben kein Maschinenkot ist. Der Prozessor kann damit nichts anfangen, schließlich spricht er eben nur x86-Maschinencode oder MIPS-Maschinencode, aber keinen Java-Bytekot. Deshalb übersetzt der JIT das Programm während es läuft in Echtzeit in den Maschinencode.
Java selbsts ist also systemunabhängig und der Java-Bytekot ist es auch. Aber es ist kein echter Maschinenkot.

>Es gibt mehrere Assemblersprachen, weil viele Betriebssysteme
Das stimmt nicht. Es gibt verschiedene Assemblersprachen, weil es verschiedene Architekturen gibt. Der Assemblerkot unterscheidet sich nicht vom Betriebssystem.
Nimm zum Beispiel x86: Jeder Assemblerbefehl (push, add, lea, ...) funktioniert sowohl unter Windows als auch unter Linux oder sonstigem. Ein korrektes Assemblerprogramm unter Linux wird auch unter Windows korrekt bleiben. Die Betriebssysteme unterscheiden sich nur in den Systemaufrufen. Aber das hat nichts mit der Sprache zu tun. Es sind eher Funktionen, die vom Betriebssystem angeboten werden. Und jedes Betriebssystem bietet andere Funktionen an und sie werden auch verschieden aufgerufen.

RussellBishop Avatar
RussellBishop:#9092

So, weil's so schön ist, versuche ich das jetzt auch mal zu erklären. Nur in kurz und verständlich:

Assembler IST Maschinenkot. Eine CPU hat Register, als ich anfing unter DOS am 8088 gab's nur 4 (ax, bx, cx, dx). Diese hatten je 16 Bit, also ein Word, also 0-65536. Du konntest sie aber auch nur als ah (a-high) und al (a-low) ansprechen, dann hattest du 2x 8 Bit. Du konntest das gemischt verwenden, z.B. auf ax schreiben, und dann ah und al getrennt auslesen. Der CPU ist das egal. Brauchst du mehr Variablen als die CPU hat, musstest du ein paar auf den Stack zwischenspeichern, um sie später wieder zu holen. Händisch.

Das ist das niedrigeste Level, das möglich ist. Alles, was du hier rein schreibst, wird direkt so 1:1 auf der CPU ausgeführt. Wenn man da Mist gebaut hat, hängt das ganze System (weil single-Tasked), und man mussten einen Reset machen, also den Computer neu starten.

Dann kamen "bessere" Assembler-Compiler, die konnten schon mit Variablen umgehen, und nahmen dir diesen Variablen-Fuckup ab. Damit habe ich nie gearbeitet.

Dann kam (für mich) Turbo Pascal. Das war im Endeffekt ein schöner Wrapper für Assembler; eine komplexere Sprache die selbst die Variablen managt, schöne Funktionsaufrufe erlaubt, und so weiter. Wenn du das komplilert hast, kam trotzdem wieder Masischencode raus - eine .com-Datei. Die konnte man "dekompilieren" zu Assemblercode, und ansehen, was der Compiler so gemacht hat. Wobei dekompilieren hier eigentlich falsch ist, weil jedes Byte Maschinencode genau einem "Wort" Assembler entspricht.

Beispiel - Grafik-Modus 13 initialisieren in ASM
mov ax, 13
int 10

wird zu (Werte in Hex, also 0xd statt 13)
0: 66 b8 0d 00 mov ax,0xd
4: cd 0a int 0xa

Dieser Byte-Code iat natürlich total CPU-Spezifisch, und konnte nur auf 8088 (oder abwärtskompatiblen, z.B. 286, 386, ...) ausgeführt werden. Auf einer anderen CPU frohr das Programm mit ziemlich hoher Wahrscheinlichkeit die CPU ein. Also sehr maschinenspezifisch.

Der Käse bei .com-Programmen war, dass sie höchstens 64 KByte groß sein durften. Weil ein Speichersegment war eben 64KB groß, und die .com-Datei wurde direkt in den Speicher gekloppt, wenn sie gestartet wurde.

Um das zu umgehen, gab es .exe-Dateien. Die konnten mehr, und vor allem größer als 64KB sein, weil sie nicht sofort 1:1 in den RAM kopiert wurden.

Daher wurde das .exe-Format eingeführt. Das konnte schon mehr, war aber auch im Endeffekt Maschinencode, nur mit mehr Features.

Das gute Turbo Pascal wusste genau, wieviel Register deine CPU hatte, und was die sonst noch drauf hatte, und wandelte also deinen leserlichen Quellcode in Maschinenkot um. Wenn es Turbo Pascal für andere Plattformen gegeben hätte (so wie C), dann könnte man den Pascal-Code nehmen, und auf der anderen CPU in Pascal wieder in passenden Maschinenkot kompilieren. Selber Sourcecode, unterschiedlich kompilierter Maschinenkot.

Und dann kam irgendwann Java. Hier war die Idee, dass man einen Layer zwischenschaltet, nämlich die JVM. Der Java-Compiler tut im Grunde nichts anderes als deinen Code ein bisschen zu optimieren, und zu komprimieren. Ausserdem kommt Java mit einem Sack voll Libraries daher, wie etwa umfangreiche String-Manipulation. Das alles musste man sich in Assembler selbst schreiben. String in Großbuchstaben umwandeln? Schreib' dir eine Umwandlungs-Funktion, die CPU hat ja keinen Dunst von Buchstaben!

Die JVM interpretiert also den komprimierten Code, und wandelt ihn in Echtzeit (oder kurz vorher) in Maschinenkot um. Der Vorteil dabei ist, dass die JVM gewisse Sachen verbieten kann, z.B. auf Sektor 0 der Festplatte zu schreiben, oder einfach irgendwelche Speicherbereiche auszulesen. Ein weiterer Vorteil ist, dass die JVM gewisse CPU-Features ausnutzen kann, an die der Assembler-Programmierer vielleicht noch nicht mal denken konnte, z.B. abgefahrene Spezialfunktionen für Verschlüsselung zu benutzen, falls diese auf der CPU existieren.

Java ist nun deshalb Plattformunabhängig, weil es für jede Plattform eine eigene JVM gibt, die den komprimierten Code unter Ausnutzung der aktuellen CPU-Features live zu optimierten Maschinenkot macht.

damenleeturks Avatar
damenleeturks:#9093

>>9092
>Assembler IST Maschinenkot.

Nö. https://de.wikipedia.org/wiki/Maschinensprache#Unterschiede_zur_Assemblersprache

souperphly Avatar
souperphly:#9094

>>9092
>Der Vorteil dabei ist, dass die JVM gewisse Sachen verbieten kann, z.B. auf Sektor 0 der Festplatte zu schreiben, oder einfach irgendwelche Speicherbereiche auszulesen
Das ist bei modernen Betriebssystemen auch bei jeder anderen Sprache (z.B. C) verboten.

dpg Avatar
dpg:#9095

>>9094
>einfach irgendwelche Speicherbereiche auszulesen
>Das ist bei modernen Betriebssystemen auch bei jeder anderen Sprache (z.B. C) verboten.
Ja, aber Java verbietet dir immerhin, aus Versehen einen Speicherbereich zu überschreiben, der zu deinem Prozess gehört bzw. Daten in ungewolltem Kontext zu lesen, indem es verhindert, dass du über die Grenzen deines Arrays hinaus liest und schreibst. C tut das nicht (und das Betriebssystem auch nur, wenn du in Speicherbereichen rumpfuschst, die nicht zu deinem Prozess gehören).
Mit Java hätte es kein Heartbleed gegeben :3

wahidanggara Avatar
wahidanggara:#9106

>>9094
Wer sagt denn dass ein Betriebssystem vorhanden ist? Vielleicht läuft das Programm auch auf dem nackten Metall?