Beiträge anzeigen

Diese Sektion erlaubt es dir alle Beiträge dieses Mitglieds zu sehen. Beachte, dass du nur solche Beiträge sehen kannst, zu denen du auch Zugriffsrechte hast.


Nachrichten - [MM]

Seiten: 1 ... 5 6 [7]
121
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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
122
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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
123
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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
124
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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
125
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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.
126
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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
127
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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
128
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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
129
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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
130
Lowlevel-Coding / Lowest Level - Eigener Compiler
« 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
Seiten: 1 ... 5 6 [7]

Einloggen