Lowlevel

Lowlevel => Lowlevel-Coding => Thema gestartet von: [MM] am 13. July 2005, 21:30

Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 13. July 2005, 21:30
Hallo, hat sich ja ganz schön was getan, seit ich das letzte Mal hier war, weiter so.

Zu Thema:
Ich denke ihr werded wohl für die Low Level Programmierung Compiler/Assembler wie den GCC oder TASM benutzen, oder?

Ich habe mir vor einiger Zeit einen eigenen Assembler geschrieben und dann auf dessen Basis einen C Compiler (den ich später für ein eigenes OS benutzen will).

Der Compiler hat zwar einige kleine Einschränkungen, kann aber ansonsten alles, was im ANSI Standard steht und noch mehr wie zB:


// Funktionszeiger:
void func(char* str,int anz){...}
void main(void){
  void(char*,int) fptr;
  fptr=func;
  fptr("hallo",5);
}

// Mischung von ASM und C:
int a,b;
asm{
  mov eax,0x10
  mov [a],eax
  xor ebx,ebx
}
b=ebx;


Wer Interesse hat kann ihn sich ja mal ansehen und mir seine Meinung schreiben:
http://wwwstud.fh-zwickau.de/~micmo/compiler.html

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: Legend am 13. July 2005, 22:43
Das ist aber schon mal eine grosse Leistung. Hinter Compilern steckt jede Menge Theorie, die verstanden sein will! ;)
Und die Notation des Inline Assemblers gefaellt mir so auch viel besser als beim GCC! :)
Aber lowest level waer wohl eher chip design!  :twisted:
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 13. July 2005, 22:54
Jaja, Einsen und Nullen mit nem Stock in den Sand malen...  :wink:

Aber ansonsten geht es von der PC Programmierung nur noch 'lower' wenn man das Programm mit nem Debugger schreibt, denke ich.

Was den Inlineassembler angeht, da hab ich mich ganz an das gute alte Turbo C gehalten, denn dies gewurschtel mit dem GCC mag ich auch nicht.

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: joachim_neu am 14. July 2005, 06:59
Nette Sache.
Titel: Lowest Level - Eigener Compiler
Beitrag von: Legend am 14. July 2005, 08:48
Wobei mir ein C++ Compiler noch lieber waere!  8)
Titel: Lowest Level - Eigener Compiler
Beitrag von: DarkThing am 14. July 2005, 13:19
Aaaaaahhh!! Der Compiler kann ja schon viel mehr als meiner  :?
Gefällt mir aber trotzdem  :wink:
Da ich bei meinem Compiler gerade mit Mathe beschäftigt bin, würds mich mal interessieren wie du zum Beispiel diese Zeile in Assembler compilierst:
Var=200*(Var2+x/2)-4
Ich versuche im Moment die Zeile in einzelne Teile zu zerlegen und erst mal die innersten Klammern zu bearbeiten. Also so:
"Var2+x/2" in Asm machen, dann "push Ergebnis"
Den Rest dann dazu machen: 200*pop-4
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 14. July 2005, 14:06
Naja, das Problem löst sich eigentlich von ganz alleine, wenn man das Prinzip mit dem Tokenbaum verstanden hat.
Dies ist übrigends die Ausgabe die mein Compiler mit der Option -stt anzeigt:


mtl: 'var=200*(var2+x/2)-4;'
var
200*(var2+x/2)-4
200*(var2+x/2)
(var2+x/2)
x/2

│ ├-1 <int> 4
├-1 <int> -
│ │ │ │ ├-1 <int> 2
│ │ │ ├-1 <int> /
│ │ │ │ ├-1 <int> x
│ │ ├-1 <int> +
│ │ │ ├-1 <int> var2
│ ├-1 <int> *
│ │ ├-1 <int> 200
├-1 <int> =
├-1 <int> var


Wie zu erkennen ist sind die Operatoren nach ihrer Wertigkeit angeordent, wobei die Klammern diese überschreiben. In der Abarbeitung des Baumes werden nun also nur noch die einzelnen Operationen durchgeführt, wie man aus dem Listing unten erkennen kann.
Es wird also erst der linke (?) Ast durchgegangen, bis eine 2 im eax zurück kommt, dann wird sie gepuscht, der rechte Ast am Knoten bearbeitet, was den Inhalt von x liefert, dann wird gepopt und dann dividiert, das Ergebnis wird wieder in eax zurück geliefert, klar soweit?


0001: main()
main_begin:
6689E5           mov ebp,esp
{
 < create  int x (4) >
 < create  int var2 (4) >
 < create  int var (4) >
6681EC0C000000   sub esp,0c
 < local stack: 4 >
0003: var=200*(var2+x/2)-4;
66B804000000     mov eax,04
6650             push eax
66B8C8000000     mov eax,0c8
6650             push eax
66B802000000     mov eax,02
6650             push eax
66678B45F4       mov eax,[ebp-0c]
665B             pop ebx
6631D2           xor edx,edx
66F7F3           div ebx
6650             push eax
66678B45F8       mov eax,[ebp-08]
665B             pop ebx
6603C3           add eax,ebx
665B             pop ebx
66F7E3           mul ebx
665B             pop ebx
662BC3           sub eax,ebx
66678945FC       mov [ebp-04],eax
6681C40C000000   add esp,0c
66C3             ret
}
0004: end of main()


Ich hoffe das Prinzip ist klar geworden. Wie genau machst du das? Aus deiner Beschreibung heraus denke ich ohne Baum, oder?
Kann man deinen Compiler irgendwo sehen?

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: DarkThing am 14. July 2005, 14:16
Okay danke. Also bisher macht der Compiler nichts mit Mathe, außer ein paar Überprüfungen usw. Das Tokenbaum-Prinzip sieht interessant aus, ich denke ich werde es auf jeden Fall aufnehmen.

Vom Compiler gibt es bisher leider nicht viel zu sehen. Ich habe einen einfachen Präprozessor inkl. Tutorial praktisch fertig und der Compiler befindet sich in der Entwicklung. Das ganze ist für eine eigene Sprache, die L3 heißt (die Sprache ist für den Compilerbau recht einfach). Bisher kann ich:
- Variablen erstellen
- Variablen Werte zuweisen (das geht schon mit dem Mathe-Anfang)
- Inline Assembler

z.b. kann ich schon diesen Code compilieren:

DimInt x
DimInt y
x=5
y=4
asm{
mov eax, [_x]
mov ebx, [_y]
add eax, ebx
mov [_x], eax
}
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 14. July 2005, 14:56
Das sieht mir irgendwie sehr nach Basic aus, kann das sein?

Und was das mit 'Mathe' betrifft, muss man den Begriff denke ich etwas weiter fassen. Ich nenne es einfach 'Ausdruck' bzw 'Expression', denn eine Anweisung wie diese "x=(a==0?0x10:0x20);" hat meiner Meinung nach nicht viel mit 'Mathe' zu tun.

Und erzeugt dein Compiler auch schon ausführbaren Code, und wenn ja, wie machst du das?

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: Buster am 14. July 2005, 18:31
Respekt! Da hast du echt viel Arbeit reingesteckt, find ich super. Wo hast du die ganze Theorie her um so ein Teil überhaupt schreiben zu können? Von deiner Uni (s. Link), Bücher, Internetdokus oder sogar nur Trial and Error? ;D
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 14. July 2005, 19:24
Bei meiner FH gibt es ein sehr cooles PMode Tutorial:
http://www.fh-zwickau.de/doc/prmo/pmtutor/text/
Aber nichts in Richtung Compiler.

Aber angefangen hatte ich auch erst vor Jahren mit einem Assembler, den ich dann immer weiter entwickelt hatte und der nun den Gundstein für meinen Compiler gebildet hatte.
Die Idee mit dem Zerlegen in die Token und das Aufbauen eines Baumes hatte ich irgendwo mal im Internet aufgeschnappt. Den Rest habe ich mir selber ausgedacht (natürlich nicht das Konzept mit Objektdateien Linker usw, sondern wie es intern funktioniert).

Ich habe zwar auch Automatentheorie usw gelernt, wo man uns immer sagte, "Das braucht man für den Compilerbau" aber ich muss sagen, man braucht es nicht ...  :wink:

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: DarkThing am 14. July 2005, 19:42
Zitat von: [MM]
Das sieht mir irgendwie sehr nach Basic aus, kann das sein?

Und was das mit 'Mathe' betrifft, muss man den Begriff denke ich etwas weiter fassen. Ich nenne es einfach 'Ausdruck' bzw 'Expression', denn eine Anweisung wie diese "x=(a==0?0x10:0x20);" hat meiner Meinung nach nicht viel mit 'Mathe' zu tun.

Und erzeugt dein Compiler auch schon ausführbaren Code, und wenn ja, wie machst du das?

MM

Jup, die Sprache ist an Basic angelehnt aber in Basic gibts kein Inline-Asm ^^

Der Compiler erzeugt nicht direkt ausführbaren Code sondern Assembler-Files, die man dann mit Nasm & co assemblieren kann.
Im Prinzip lese ich die Input-Datei (Includes gibt es, werden aber vom Präprozessor vorher aufgelöst also hat man nur einen File) Zeile für Zeile ein und versuche einen Befehl zu erkennen:

while(!FileIn->eof())
{
// Zeile lesen
FileIn->getline(&line[0], MAX_LINE_LENGTH, '\n');

// ----- INLINE ASSEMBLER -----
if(strcmp(line, strInlineAsm) == 0)
{
DoInlineAsm();
continue;
}

// ...

// Nichts erkannt -> Fehler
// ...
}

Wenn z.B. Inline-Assembler erkannt wurde, wird eine Funktion aufgerufen, die den Befehl in Assembler umsetzt.
Titel: Lowest Level - Eigener Compiler
Beitrag von: Buster am 14. July 2005, 21:09
Geile Sache! Im wievielten Jahr oder Semester studierst du schon und was studierst du auf dieser FH? Interessiert mich unverschämt! ;D Btw das Tutorial kenn ich, ist wirklich eins der besten die ich im Internet kenne. Da bist du ja an einer fähigen FH gelandet, die sehr viel Potential hat. =D
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 14. July 2005, 21:26
Ich studiere erst seit einem Jahr an der FH-Zwickau (sind grad Prüfungen am Ende des 2. Semesters). Ich habe aber davor in Ulm als Assembler/C Programmierer von Microcontrollern gearbeitet (also auch sehr LowLevel  :wink: ). Bin nämlich von Beruf "Technischer Assistenten für Informatik".

Und als Studiengang habe ich "Systeminformatik" gewählt (im Hauptstudium). Das ist so weit ich weiß sehr selten in Deutschland, ich kenne keine andere FH die das anbietet. Da werden dann solche Sachen gemacht wie:

- Systemprogrammierung
- Objektorientierte Systeme
- Verteilte Systeme
- Neuronale Netze
- Treiberentwicklung

Und das PMode Tutorial ist Teil der Unterlagen von Systemprogrammierung.
Wie das aber in Zukunft aussieht weiß ich nicht, denn ich bin im letzten Diplomjahrgang und ich weiß nicht, was im Zuge mit Bachelor/Master da umgestellt wird.

Unter http://www.fh-zwickau.de/doc/prmo/start.htm gibt es auch noch ein MMX Tutorial, aber das kennst du dann ja bestimmt auch. Ansonsten sind die Sachen nur im Intranet zugänglich.

MM

PS @ DarkThing:
Wenn du noch vor hast Maschinencode zu generieren kann ich dir die folgende Referenz von Intel empfehlen:
http://www.intel.com/design/pentiumii/manuals/243191.htm
Am Ende gibt es eine Befehlsreferenz der x86 (>386) Serie mit allen Befehlen und Adressierungsarten in Maschinencode. Hat mir bei der Entwicklung meines Assemblers sehr geholfen.
Titel: Lowest Level - Eigener Compiler
Beitrag von: DarkThing am 15. July 2005, 13:42
Zitat von: [MM]

Wenn du noch vor hast Maschinencode zu generieren kann ich dir die folgende Referenz von Intel empfehlen:
http://www.intel.com/design/pentiumii/manuals/243191.htm
Am Ende gibt es eine Befehlsreferenz der x86 (>386) Serie mit allen Befehlen und Adressierungsarten in Maschinencode. Hat mir bei der Entwicklung meines Assemblers sehr geholfen.

thx, Ich hab zwar erstmal nicht vor einen Assembler zu schreiben, aber ich finde den File trotzdem recht interessant und vielleicht werde ich ihn ja später brauchen :wink:
Titel: Lowest Level - Eigener Compiler
Beitrag von: SSJ7Gohan am 16. July 2005, 20:05
Hm, ich muss bald auch einen Compiler schreiben, jedoch nicht um Executeables zu erzeugen, sondern um die Scriptsprache für ein Online Spiel, das ich programmiere zu compilieren. Ich hatte früher schon funktionierende Ansätze, jedoch fand ich das Parsen der Tokens und die Codegenerierung ziehmlich schwierig. Ich werde mir deinen Compiler mal ansehen. =)
Titel: Lowest Level - Eigener Compiler
Beitrag von: DarkThing am 16. July 2005, 20:12
Ich glaube du brauchst eher einen Interpreter für eine Scriptsprache. Und Interpreter haben nicht sehr viel mit Compilern gemeinsam, da Compiler den Code in Maschinensprache/Assembler übersetzen und Interpreter nur Funktionen z.B. einer API aufrufen.
Titel: Lowest Level - Eigener Compiler
Beitrag von: SSJ7Gohan am 16. July 2005, 20:14
Nein, ich will keinen Interperter XD
Ich compiliere den Code in eine Art Bytecode, der dann von einer VM ausgefürt wird.
Titel: Lowest Level - Eigener Compiler
Beitrag von: DarkThing am 17. July 2005, 14:57
Okay ^^
Dann brauchst du wirklich einen Compiler  :wink: Das ganze dürfte dann dem Compiler von [MM]  entsprechen nur dass du deinen Bytecode statt dem Intel Opcode erzeugst.

@MM:
Gibt es irgendwelche Tuts über Tokentrees oder so?
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 17. July 2005, 21:02
Nicht das ich wüßte. Musst dir halt nur mal überlegen wie die Wertigkeiten sind, und das ganze auf Papier mal durchspielen. Einen Tipp kann ich aber noch geben:
Bei +,- bzw *,/ sollte man auf jeden Fall die gleiche Wertigkeit verwenden, sonst kommt es zu seltsamen Effekten, wie ich feststellen musste...  :wink:

Ansonsten kann ich dir nur raten, dass du dir mal ansiehst, wie mein Compiler die Debugausgabe mit dem Parameter "-stt" macht. Damit sollte man schon die meisten kniffeligen Stellen erkennen können.

Ich werde den Compiler übrigends in den kommenden Semesterferien nochmal komplett überarbeiten, denn ich hab letztens doch noch einige gravierende Mängel in der Zeigerarithmetik gefunden.

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: MagicTom am 17. July 2005, 21:08
[MM]: kann es sein dass deine Webseite nicht erreichbar ist? Bei mir funktioniert sie seit Tagen nicht und hat seit dem ich das erste mal dieses Thema gelesen habe, auch noch nie funktioniert  :?:
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 17. July 2005, 21:34
Ich schätze du hast das Thema dann am Freitag entdeckt?
Das Problem ist mir bekannt, mit Beschwerden wendet euch bitte an das HRZ Kompetenzteam unserer Lehranstalt...  :wink:

Ich schätze da ist am Freitag nachdem alle schon weg waren der Apache kaputt gegangen. Wird aber bestimmt behoben sein, wenn am Montag Mittag die ersten RZ Murkel aus dem Wochenende zurück kommen.

Also einfach morgen nochmal probieren,

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: matthieuriolo am 18. July 2005, 13:20
Hey
Also erst mal ein grosses Lob. Sehr intressante projekte, nur blicke ich nicht durch ;) Denn beim compiler müssste man doch es irgendwie in 0 und 1 umschreiben. Das finde ich nicht! Und genau das würde mich eben intressieren...


Und was ist eine com datei? Dies ist wahrscheinlich eine sehr blöde frage aber es is only windows und darum für mich unbekannt (mac user). Hab schon danach gesucht aber nix gefunden  :oops:


Danke
Titel: Lowest Level - Eigener Compiler
Beitrag von: DarkThing am 18. July 2005, 13:23
Zitat von: [MM]
Nicht das ich wüßte. Musst dir halt nur mal überlegen wie die Wertigkeiten sind, und das ganze auf Papier mal durchspielen. Einen Tipp kann ich aber noch geben:
Bei +,- bzw *,/ sollte man auf jeden Fall die gleiche Wertigkeit verwenden, sonst kommt es zu seltsamen Effekten, wie ich feststellen musste...  :wink:

Ansonsten kann ich dir nur raten, dass du dir mal ansiehst, wie mein Compiler die Debugausgabe mit dem Parameter "-stt" macht. Damit sollte man schon die meisten kniffeligen Stellen erkennen können.
MM

Werd ich machen ^^ Im Moment hab ich eh ne "Kreativitäts"-Pause  :wink: Und danach werd ich das dann einbauen. Der Rest (if, schleifen, ...) erscheint mir dann wieder einfacher.
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 18. July 2005, 14:02
@matthieuriolo:
Erst zum einfachen Teil:
com Dateien sind ausführbare Dateien ohne Header oder feste Formatierung. Das heißt sie werden vom System an die Adresse 0x100 eines Segmentes geladen und dann wird einfach der IP auf 0x100 gesetzt. Also die primitiveste Art ausführbaren Code zu verpacken (siehe command.com bei ms dos).  Oft befinden sich auch Code, Stack und Daten im gleichen Segment, wenn das Programm größer wird als 64K muss der Programmiere das im Program selber regeln.

So, nun zu 0 und 1:
In der Datei code.c ist ein Makro definiert MAKE_ASM:
#define MAKE_ASM(s) c=atocommand((s));if(Optionen.dbc){fprintf(dbc,commandtoalong(c));}add_opcode(c.opcode.hex);
Wenn du dir die Datei ansiehst wirst du feststellen, dass dort zB Zeilen auftauchen, die das heißen:
MAKE_ASM("mov eax,ebx")
Es wird die Funktion atocommand() aufgerufen, die in asm.c steht (glaub ich). Diese Funktion liefert eine Struktur mit dem Bytecode zurück, der dann von dem Makro in den Codebuffer eingetragen wird, welcher später in die obj Datei geschrieben wird.
So, die Datei asm.c ist 1:1 aus meinem Assembler übernommen und es mag etwas umständlich erscheinen, den Umweg über den String zugehen, der dann wieder vom Assembler analysiert wird, aber so hat man gleich den Stribng für Debugausgaben.
Ich gehe mal davon aus, dass du dich dafür interessierst, wie nun aus den ASM-Befehlen der Opcode erzeugt wird, denn wie man auf die ASM-Befehle kommt sollte klar sein.
Was macht also die Funktion atocommand: Es wird analysiert, welcher Befehl mit welchen Parametern benutzt wird und dann wird der Opcode generiert. Als Beispiel hier mal den str Befehl, der mit einer Speicherstelle oder einem Register benutzt werden kann:

    case _STR_:
      if(com->p1.typ==_REG_){ // str reg
        add("000011110000000011001");
        addreg(p1);
        break;
      }
      if(com->p1.typ==_MEM_){ // str mem
        add("0000111100000000");
        addmod(p1);
        add("001");
        addrm(p1);
        addstuff(p1);
        break;
      }
      break;

Die Funktion add fügt ganz konkret die 1/0 an den Opcode an, addreg entsprechend den Code für das beschriebene Register und addrm/addmod analog für die Speicheradressierung.

So, das war nun zwar etwas viel Text, aber ich hoffe ich konnte deine Frage beantworten, oder dir zumindest aufzeigen, wo du die 'Aha'-Stellen finden kannst.

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: matthieuriolo am 18. July 2005, 14:38
Danke vielmal für diese ausführliche erklärung. Ich habe im moment Ferien und werde öfters zum prgrammieren kommen. Darum intressiere ich mich so sehr für deinen Compiler. Aber ich habe noch 2 fragen. So wie ich das verstanden habe machst du aus dem C ein asm Code. Der tust du dann compilieren. Wo bleibt die Optimation? Oder is die irgendwo weiter versteckt? Und wenn man zum beispiel short int = 2; macht. Wie macht man das man nen short int hat, vorallem das es überhaupt als ein int deklariert wird. Und wo wird das asm Compiliert?


Ok, das waren jetzt mehr als 2 Fragen  :D
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 18. July 2005, 18:59
Nett,ich habe Donnerstag meine letzte Prüfung und dann 2 Monate Vorlesungsfrei, dann werde ich mich mal an einen neuen, besseren Compiler setzen  :D
Also, wenn Jemand schon immer einen C-Compiler haben wollte, der was ganz bestimmtes können sollte....  :wink:

Nun zu deinen Fragen matthieuriolo:
Optimierung findet nur auf Ebene des Token Trees statt bzw in der Umsetzung der Assembleroperationen. Eine Zuweisung von 1 wird zb so dargestellt:
xor eax,eax
inc eax

Und auf der Ebene des Token Trees werden überflüssige Operationen gekürzt, wie zb Addition von Konstanten werden vorberechnet.
Wenn u Optimierungen in der Größenordnung haben willst, wie zB das Weglassen einer Zuweisung, wenn die Variable nie benutzt wird, dann müßte man sehr viel mehr Aufwand treiben, was ich aber nicht gemacht habe.

Und die Sache mit den Variablen ist dann etwas trickreich. Man unterscheidet sinnvoller Weise zwischen globalen, lokalen und Parametervariablen.
Bei einem globalen int werden einfach irgendwo im Datenbereich 4 bytes reserviert, und immer auf diese feste Adresse verwiesen (die Adresse ist erst dem Linker bekannt).
Die anderen beiden Typen sind etwas komplizierter, da sie auf dem Stack liegen.
Beim Eintritt in eine Funktion wird der esp in den ebp kopiert. Alle Aufrufparameter liegen also über ebp. Wenn eine lokale Variable deklariert wird, so wird einfach esp um die erforderliche anzahl an Bytes verringert und der Zugriff erfolgt dann durch ebp-x, wobei x sich nach der Anzahl der schon auf dem Stack befindlichen Variablen richtet.
Um das etwas zu verdeutlichen hier ein Beispiel:

void func(int para){
  var=0x10;
  para=0x20;
}

0004: func()
func_begin:
6689E5           mov ebp,esp
{
 < create  short var (2) >
6681EC02000000   sub esp,02
 < local stack: 2 >
0007: var=0x10;
B81000           mov ax,010
678945FE         mov [ebp-02],ax      <-- var liegt bei ebp-2
0008: para=0x20;
66B820000000     mov eax,020
6667898504000000 mov [ebp+04],eax   <-- para bei ebp+4
6681C402000000   add esp,02
66C3             ret
}
0010: end of func()


Man muss halt nur genau aufpassen, wo was liegt, denn auf dem Stack liegt dazwischen ja noch die Rücksprungadresse, und wenn man die überschreibt kommt man Sonstwo raus.
Klar soweit?

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: matthieuriolo am 20. July 2005, 20:22
Hey
Ich habe nochmal ein frage an dich. Wenn man mit deinem Compiler den Befehl mov compiliert wird aus dem das 000011110010001011. So wie ich das gesehen habe. Sind diese befehle und länge irgendwie eingeschrenkt? Gibt es irgendwo trennungen? Bin mir am überlegen dein Compiler noch eine Disassemblierung einzubauen ;)
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 20. July 2005, 21:31
Ich fürchte ich verstehe die Frage nicht.
Die Befehle sind natürlich an 8 Bit ausgerichtet und können daher sehr bequem als Hecadezimalzahlen dargestellt werden:
B81000           mov ax,010
678945FE         mov [ebp-02],ax

Wie man sieht ist B81000 "mov ax,0x10" wenn man aber ein Byte weiter hinten anfäng zu disassemblieren, so wird murks draus.
Ein sehr guter 32Bit Debugger ist meiner Meinung nach der DDEB der kann den von meinem Compiler produzierten Code wunderbar lesen (bis auf Jumps).
Und was möchtest du genau machen? Der Compiler produziert ja schon bei Bedarf Ausgabedateien mit dem Opcode und ASM-Befehlen in Textform.

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: matthieuriolo am 20. July 2005, 22:12
Naja es ist ja so. Mov entspricht 000011110010001011. Was ist aber wenn man ein program hat das so aussieht 10100011100101111010001010101000010101111000110101011101000101010101001010100001010100 (KA was das is ... is ja auch wurst). Wie kann ich nun aus dem, ein assambler zurück machen? Da muss es also irgendwie trennungen geben. Wie du gesagt hast sind befehle immer (?) 8 bit lang, wie finde ich nun der Rest heraus?
Titel: Lowest Level - Eigener Compiler
Beitrag von: elfish_rider am 20. July 2005, 22:28
Stelle den Code besser hexadezimal anstatt binär dar, sodass du wenigstens einen gewissen Überblick hast.

x86-CPUs haben bestimmte Opcodes für alle Befehle, die sehr unterschiedlich lang und auch sonst ziemlich verschieden sind. Am besten schaust du in der Dokumentation von NASM, dort stehen zu jeder Befehlsvariante die Opcodes.
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 20. July 2005, 23:06
Genau, mov al,1 ist zb sehr viel kürzer als zb mov eax [ebp+esi*8]
Es kommt also auf den Einsprungpunkt an, wo du anfängst den Code zu disassemblieren. Und wenn dein Disassembler einen Opcode nicht kennt bzw eine Kombination nicht, dann wird ab der Stelle nur noch Müll produziert. Kannst ja mal versuchen mit dem MS-Debugger ein Programm in den Speicher zu schreiben, und dann läßt du es dir wieder disassemblieren nur mit der Startadresse +1:
C:\>debug
-a100
0CD8:0100 mov al,1
0CD8:0102 xor bx,bx
0CD8:0104
-u100 l4
0CD8:0100 B001          MOV     AL,01
0CD8:0102 31DB          XOR     BX,BX
-u101 l4
0CD8:0101 0131          ADD     [BX+DI],SI
0CD8:0103 DB20          ESC     1C,[BX+SI]TBYTE PTR [BX+SI]
-

Und bzgl der Länge:
0CD8:0100 B001          MOV     AL,01
0CD8:0102 B80100        MOV     AX,0001


Und ich würde dir als Doku die von Intel empfhelen, den Link findest du weiter Oben auf Seite 1 in einem meiner Posts.
Und was willst du denn genau machen für den Compiler, oder interessiert es dich nur so?

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: matthieuriolo am 20. July 2005, 23:19
Das is ja einiges komplizierter als ich gedacht habe! Dann lass ich es lieber sein und mache lieber mal das gleiche wie du ^^ "klein" anfangen is hier die Devise. Ich hab zwar gesagt für den Compiler aber das is eigentlich mist. Weil jeder Compiler bringt ungerfähr den gleichen bit hervor (sonst würde es nicht das gleiche machen) also wäre es ja egal mit welchem man es kompiliert hat.
Titel: Lowest Level - Eigener Compiler
Beitrag von: DarkThing am 21. July 2005, 16:59
Es ist wirklich egal - solange man alle Opcodes abfragt. Aber nicht jeder Compiler erzeugt den gleichen Code. Die wirklich großen Compiler haben z.B. noch viele Optimierungen drin und die Compiler setzen ifs, usw. manchmal unterschiedlich um.
Auch ein cooles Projekt wäre ein Decompiler sozusagen. Das heißt man macht aus den Opcodes/Assembler wieder C-Code. Das ist sicher höllisch schwer aber sollte bis zu einem gewissen Grad machbar sein.
Titel: Lowest Level - Eigener Compiler
Beitrag von: SSJ7Gohan am 22. July 2005, 12:51
Falls du dich an einen neuen Compiler setzt, könnstest du evt. die Möglichkeit einbauen, die Zielsprache leicht zu verändern? Also nicht nur in x86 Assembler Code zu erzeugen, sondern auch in anderen Sprachen? Es würde ja genügen, die Codeerzeugung von dem eigentlichen Compiler (also Lexer und Parser) zu trennen. Das würde mir sehr helfen.
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 22. July 2005, 14:26
Es wäre möglich asm-Code zu generieren, wobei der Code natürlich aus x86 Befehlen besteht. Würde das reichen, oder brauchst du Code für einen ganz anderen Befehlssatz (ATMEL 8051 oder sowas verrücktes)?

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: SSJ7Gohan am 22. July 2005, 14:32
Ich brauche den Code für eine VM, und der Code sieht ziehmlich anders aus, als der x86, es wäre also gut, wenn du die Codegenerierung von den anderen Teilen des Compiler trennen könntest. =D
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 22. July 2005, 15:53
Das wird nicht so einfach sein. Aber du könntest die Funktionen überschreiben, die das übernehmen (in der aktuellen Version ist das in code.c token_operant()). Ich hätte jetzt spontan keine Idee, wie man das abnders machen könnte.

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: [MM] am 24. July 2005, 23:31
Bin grad dabei einen neuen Compiler zu basteln und überlege, ob ich wie bei dem Alten einfach die mehrdimensionalen Felder weglassen sollte.
Damit meine ich nicht die Möglichkeit auf zB einen char ** mit [..][..] zuzugreifen, sondern die Möglichkeit ein Feld zu erstellen, welches mehr als eine Dimension hat, denn [10][20] ist ja das selbe wie [200].
Was meint ihr dazu?
Benutzt eigentlich jemand von euch mehrdimensionale Felder?

MM
Titel: Lowest Level - Eigener Compiler
Beitrag von: DarkThing am 28. July 2005, 13:48
Ich benutz mehrdiemensionale Felder nur sehr selten, aber sie sind manchmal seht praktisch und koennen nie schaden.  :wink:
Titel: Lowest Level - Eigener Compiler
Beitrag von: SSJ7Gohan am 28. July 2005, 14:39
Auf char ** mit [..][..] zugreifen sollte man son können und mehrdimensionale Felder sind auch nützlich, aber nicht notwendig.