byte reinterpretierung



  • hi,

    wie kann man eigentlich bytes wieder so reinterpretieren wie sie eigentlich geschrieben sind? angenommen ich habe eine EXE anwendung. diese anwendung wurde ja im prinzip so erzeugt:

    C++ sourcecode -> assembler -> binärcode.

    und wir wissen doch, binärcode beideutet nichts anderes wie z.B.:

    00110110 pro byte.

    und der computer versteht im endeffekt ja nur maschinen-code. soll also heissen, der prozessor muss also die binärzahlen so interpretieren, dass er gültige assemblerbefehle interpretieren kann. ist doch richtig soweit oder nicht?

    und jetzt dachte ich mir folgendes: in einem char, was genau 8bit (1 byte) ist, kann man 256 unterschiedliche zeichen darstellen. so..

    wenn ich nun also eine exe-anwendung byte für byte auslese, warum sehe ich dann nicht das, was auch der prozessor im endeffekt zu sehen bekommt, den maschinen-code? wenn mir hier jemand licht ins dunkle bringen könnte, wäre ich sehr froh drum.

    mir fehlt es glaube ich nur noch um diese kleine ergänzung, was die bit darstellung, speicherung etc. angeht. da muss es scheinbar noch gewisse richtlinien geben, wie ein byte interpretiert wird.



  • steffen09 schrieb:

    wenn ich nun also eine exe-anwendung byte für byte auslese, warum sehe ich dann nicht das, was auch der prozessor im endeffekt zu sehen bekommt, den maschinen-code? wenn mir hier jemand licht ins dunkle bringen könnte, wäre ich sehr froh drum.

    Doch, genau das siehst Du.

    mir fehlt es glaube ich nur noch um diese kleine ergänzung, was die bit darstellung, speicherung etc. angeht. da muss es scheinbar noch gewisse richtlinien geben, wie ein byte interpretiert wird.

    Das steht im Handbuch zu Deinem Prozessor.



  • Hört sich alles soweit richtig an 🙂

    steffen09 schrieb:

    wenn ich nun also eine exe-anwendung byte für byte auslese, warum sehe ich dann nicht das, was auch der prozessor im endeffekt zu sehen bekommt, den maschinen-code?

    Du siehst ihn doch. Öffne z.B. die Exe-Datei in einem Hex-Editor und schau dir die ganzen Bytes an. Irgendwo nach den Headern und sonstigen Meta-Daten kommt auch der Quelltext in Maschinensprache. Das ist natürlich kein ASCII-Text, denn das wäre Platzverschwendung.
    Wenn der Prozessor einen 1-Byte-Befehl mit dem Wert z.B. 0x28 reinbekommt, reagiert er entsprechend darauf, z.B. schreibt den Inhalt eines Registers in den Arbeitsspeicher oder setzt ein Register auf 0 oder sonstwas. Viele Befehle bestehen aber aus mehr als einem Byte, im FAQ des Assembler-Forums müsste irgendwo stehen, welche Bytes für welche Befehle stehen (denn das ist natürlich standartisiert).



  • also könnte man das so verstehen:

    der prozessor ansich kennt garkeine buchstaben in dem sinne. soll heissen, selbst ein:

    char c = 'A';
    ist eigentlich nur ein zahlenwert, hier 65.

    das wiederum sieht für den prozessor vielmehr so aus:

    0011011000110101

    kommt das hin? und ich glaube für die opcodes gibt es eigentlich zahlenwerte. diese werden dann also einfach binär assembliert, damit der prozessor weiss, wie er es interpretieren soll. kommt das auch hin?

    und angenommen der prozessor muss den buchstaben A in ein register verschieben, dann würde das heissen: er bekommt zunächst den binären assembler befehl, sagen wir mal move eax, 65 wäre der code dafür und sagen wir mal das move den zahlenwert 50 hat, eax 60. dann wäre das ingefähr für dieses pseudobeispiel folgendes:

    50
    0011010100110000
    60
    0011011000110000
    65 (der wert)
    0011011000110101

    der prozessor interpretiert demnach:

    001101010011000000110110001100000011011000110101

    einfach als:

    move eax, 65

    ja?



  • Eigentlich richtig 😉 Nur deine Bytes sind etwas lang, 50(dez) wäre 00110010(bin), also 8 Bits/Byte. Mit dem Visual C++-Compiler kann man sich auch den Assembler-Code ausgeben lassen, hier ein Beispiel:

    void foo( char x )
    {
    }
    
    int main()
    {
    	char a = 'A';
    	foo( a );
    }
    

    =>

    ; char a = 'A';
      c6 45 fb 41	 mov	 BYTE PTR _a$[ebp], 65	; 00000041H
    
    ; foo( a );
      8a 45 fb	 mov	 al, BYTE PTR _a$[ebp]
      50		 push	 eax
      e8 00 00 00 00	 call foo
      83 c4 04	 add	 esp, 4
    


  • genial. vielen dank. dann habe ich nun endlich die bit welt komplett verstanden. nur eine kleine sache noch dazu, da du dezimalwert erwähnst.

    gehe ich richtig der annahme das es zwei arten von zahlendarstellungen gibt? zum einzen den deziamlen wert einer zahl 50, welches aus einem byte besteht und zum anderen den ASCII wert einer zahl 50 was dann 2 bytes sind.

    sogesehen ist jeder assembler befehl eigentlich genau ein byte wenn ich mich jetzt nicht täusche?

    und zuguter letzt, um auf das C++ norme thema zurück zu kommen:
    wie kann man denn nun aber die bytes die man aus einer datei ausliesst in den korrekten assembler syntax darstellen? müsste man simpel gesagt dazu erst einmal wissen, das der dezimale wert 250 z.B. ein xor ist?



  • Das geht schon irgendwie, ist aber sicher nicht trivial.

    Stichwort: Disassembler



  • steffen09 schrieb:

    gehe ich richtig der annahme das es zwei arten von zahlendarstellungen gibt? zum einzen den deziamlen wert einer zahl 50, welches aus einem byte besteht und zum anderen den ASCII wert einer zahl 50 was dann 2 bytes sind.

    Oh, es gibt noch ehrheblich mehr! Ich würde aber anders herangehen: Du hast eine Menge von Bits/Bytes und willst sie interpretieren. Dazu musst du natürlich wissen, zu welchem Zweck sie angelegt worden sind. Wenn du weißt, dass die Bytes Zeichen im ASCII-Textformat darstellen sollen, schnappst du dir eine ASCII-Tabelle und interpretierst sie als solche. Du kannst die Bits/Bytes aber ebenso als Zahlenwert, als Zeichen anderer Darstellung (z.B. Unicode) oder als sonstwas interpretieren.
    Und wenn du die Bits/Bytes interpretiert hast, kannst du dich an die Darstellung machen. Die Bytemenge {0x41,0x61} würdest du, als ASCII-Text interpretiert, so ausgeben: Aa . Als Integer interpretiert kannst du sie je nach gewünschtem Zahlensystem ausgeben, z.B. 16737 im 10er-System, 4161 im 16er-System oder 0100000101100001 im 2er-System.
    Wobei meist noch ein Zwischenschritt zwischen Interpretation und Ausgabe steht: Wenn du z.B. den Integer-Wert 0x4161 (also die Bytemenge {0x41,0x61}) in C++ auf der Konsole ausgeben willst, musst du den Wert erst in eine Zeichenkette verwandeln, also in die Bytes {0x34,0x31,0x36,0x31} und diese dann der Konsole übergeben; diese zeichnet dann die entsprechenden Symbole unseres Alphabet auf eine Zeichenfläche, die dann am Monitor angezeigt wird.



  • thank you! :xmas1:


Anmelden zum Antworten