ďťż

Ładny brzuch

Witam. Od nie dawna zamierzam napisac prosty kompilator w C++ dla jezyka C. No i wlasnie. Piszac ten kompilator trzeba znac jakies linijki asemblera, aby kompilowal na maszynowke czy nie? No wogole jak to zrobic? Czy trzeba wszystkie slowa kluczowe umiescic w kodzie kompilatora, ktore ma w sobie C? Prosze powiedzcie:) Dla ulatwienia powiem ze C++ znam w dobrym stopniu :)



z tego co wiem kompilator przeksztalca frazy z c/c++ na asm i potem na obj dlatego skorzystaj z 'pomocy' w postaci kompilatora asm-a w pascalu ktory napisal Phisikus

# ASS86 - wynik wakacyjnej nudy. 7000 linii czegoś co można nazwać kompilatorem języka Assembler dla 8086. Powstał w wyniku reveng'u kodu NASM'a i GASM'a. Ma dość charakterystyczną składnię i jego użyteczność jest raczej mała, aczykolwiek działa ;-). (testowane na: Linux,OpenBSD,FreeBSD. Zalecana kompilacja przez FPC)
Kompilator ass86 ze zrodelkami
tak, nie wiele on pomoze ale naprowadzi...
Użytkownik v0lt edytował ten post 27 marzec 2008, 16:03
Naprawde fajne. Dzieki :) Ale ja bym chcial jeszcze zobaczyc przynajmniej urywek kodu kompilatora w C++. Czy jest takie cos mozliwe?

oczywiscie. moze cos zrozumiesz z tego co ci dam bo raczej gcc to za duze jest :D
Tiny C Compiler
Strona internetowa kompilatora TCC



gates22
Szczerze mówiąc wątpię abyś coś zrozumiał z kodu kompilatora języka C jeśli nie masz zielonego pojęcia o tym jak się zabrać za pisanie takiego kompilatora. Ten kod może być przydatny dla kogoś kto już ma jakieś pojęcie w tym temacie.


Piszac ten kompilator trzeba znac jakies linijki asemblera, aby kompilowal na maszynowke czy nie?
Asemblera nie musisz znać. Wystarczy że będziesz znał język maszynowy ;) Ale sugerowałbym Ci jednak poznanie asemblera gdyż jest on bardzo powiązany z językiem maszynowym i znajomość asemblera bardzo będzie pomocna w zrozumieniu jak funkcjonuje mikroprocesor, a bez wiedzy o sposobie funkcjonowania mikroprocesora nie napiszesz kompilatora.
Druga rzesz jaką musisz znać to budowa plików *.exe, *.obj i ewentualnie *.com jeśli chcesz kompilować programy do tego formatu. Proponowałbym Ci ręcznie napisać prościutki programik w edytorze heksadecymalnym (wzorując się na wcześniej napisanym programiku w Asemblerze) i sprawdzić czy on działa. Pliki *.exe mają inny format pod Windowsem i DOSem.


Czy trzeba wszystkie slowa kluczowe umiescic w kodzie kompilatora, ktore ma w sobie C?
Zapewne trzeba będzie.
Sugerowałbym Ci żebyś na razie odłożył pisanie kompilatora do języka C i żebyś najpierw napisał kompilator do Asemblera, a dopiero później spróbował pisać kompilator do języka C. Tak będzie Ci dużo łatwiej zrozumieć jak działa kompilator. I jeśli wtedy będziesz się czuł na siłach żeby napisać kompilator do C to już będziesz wiedział jak za to się zabrać.

Dzięki Geroj . Myślę że masz rację. Napisałem prościutki programik tworzący plik .exe z pliku.cpp i .c, ale jakoś mi nie działa. No cóż, może trzeba jeszcze poćwiczyć działanie kompilatora. A ten "prościutki" programik na razie odsyłam w zapomnienie. Teraz jeszcze zostanę przy pisaniu programów (normalnych, nie kompilatorów) w języku C++ :)

Ciekawi mnie jak napisałeś ten prościutki kompilator skoro z Twojego pierwszego posta w tym temacie można wywnioskować, że nie wiesz jak się za to zabrać...
Wbrew powszechnej opinii Asembler jest bardzo prostym językiem do nauczenia się. Można o wiele szybciej nauczyć się programować w Asemblerze niż w Javie czy C++. Problem z Asemblerem polega na tym że jak już go poznasz to trudno jest za jego pomocą napisać jakiś rozbudowany program. Załóżmy, że w Javie jakąś skomplikowaną aplikację napisałbyś w 2 godziny to w C++ napisanie jej zajęłoby może ze 3-4 godziny, a pisząc tą samą aplikację w Asemblerze straciłbyś kilka tygodni, a jakbyś gdzieś się pomylił albo zrobił jakiś głupi błąd to straciłbyś jeszcze więcej czasu. To jest powód dla którego ludzie nie piszą w Asemblerze tylko wolą języki wysokiego poziomu. Ale nauka podstaw Asemblera trwa znacznie krócej niż nauka podstaw Javy czy C++.

Czym tak na prawdę jest Asembler i czym jest język maszynowy?
Język maszynowy składa się z samych liczb. To są liczby binarne. Każda taka liczba odpowiada jakiejś operacji wykonywanej przez mikroprocesor. Na przykład w języku maszynowym liczba 1000 1110 1101 1000 powoduje, że mikroprocesor wartość znajdującą się w rejestrze AX kopiuje do rejestru DS. Kod binarny jest ciężki dla człowieka bo po pierwsze jest bardzo długi, a po drugie są w nim same zera i jedynki, a patrzenie na nie powoduje, że obraz się rozmywa i tak na prawdę nic się nie widzi ;) Dlatego łatwiej jest stosować zapis szesnastkowy czyli heksadecymalny. Bardzo łatwo jest zamienić liczbę z systemu binarnego na system heksadecymalny i na odwrót. A z systemu binarnego lub heksadecymalnego na system dziesiętny, którego używają ludzie jest już o wiele trudniej zamienić liczby dlatego stosuje się albo system binarny albo heksadecymalny. Powyższa instrukcja w systemie heksadecymalnym wyglądałaby tak: 8ED8h. Jest o wiele krótsza od tej binarnej, łatwiejsza do zapamiętania i łatwiej ją odróżnić od innych heksadecymalnych instrukcji.
W mikroprocesorach Intela i AMD rozkazy mają różny rozmiar. Mogą być 8 bitowe, 16 bitowe, a nawet 32 bitowe. Jeśli dobrze pamiętam to w mikroprocesorach Motorola rozmiar rozkazów był stały. Instrukcja 8ED8h jest 16 bitowa. Jeśli policzysz te powyższe jedynki to wyjdzie Ci, że jest ich 16. System heksadecymalny jest takim jakby skrótem systemu binarnego. Powoduję on, że w zapisie jest zawsze 4 razy mniej cyfr.

Teraz skoro już wiadomo czym jest język maszynowy to odpowiedzmy sobie na pytanie czym jest Asembler?
Człowiekowi trudno jest zapamiętać liczby. Znacznie łatwiej byłoby zapamiętać jakieś napisy opisujące w skrócie co dany rozkaz w języku maszynowym robi. I to spowodowało, że ktoś wymyślił Asemblera. Zamiast pisać 8ED8h w Asemblerze napisałbyś "mov ds, ax" co oznacza "przenieś wartość z rejestru ax do rejestru ds". Z tym że ta wartość nadal pozostaje w rejestrze ax. Każdemu rozkazowi z języka maszynowego odpowiada jakiś rozkaz w języku Asembler. Jak widać Asembler jest znacznie prostszy od języka maszynowego i dużo łatwiej się w nim programuje.
Napisanie kompilatora do Asemblera sprowadza się do zamiany instrukcji w Asemblerze na odpowiednią wartość liczbową, która jest instrukcją w języku maszynowym. Jest to dość proste zadanie w porównaniu do napisania kompilatora do języka C. Język C jest bardziej zbliżony do ludzkiego języka i dzięki temu łatwiej sie w nim programuje niż w Asemblerze, ale trudniej jest napisać kompilator do tego języka.
Weźmy taki prosty przykładowy kod w języku C:
short int zmienna1 = 12; short int zmienna2 = 15; short int zmienna3; zmienna3 = zmienna1 + zmienna2;

Pierwsze co trzeba wiedzieć to to że mikroprocesor nie potrafi dodać dwóch wartości znajdujących się w pamięci. Aby dodać dwie wartości do siebie, jedna z tych wartości musi znaleźć się w rejestrze ogólnego przeznaczenia (ax, bx, cx, dx). Można dodawać dwie wartości znajdujące się w dwóch rejestrach ogólnego przeznaczenia, ale dwóch wartości znajdujących się w pamięci mikroprocesor nie potrafi dodać, ani przeprowadzić na nich żadnych innych arytmetycznych czy logicznych operacji.
Powyższy program w języku maszynowym mógłby zostać zrealizowany w ten sposób:
1. W nagłówku pliku *.exe podajesz gdzie znajdują się dane, kod programu, itp.
2. zmienna1 jest umieszczana pod offsetem 0000 segmentu danych
3. zmienna2 jest umieszczana pod offsetem 0002 segmentu danych
4. zmienna3 rezerwuje 16 bitowe miejsce pod offsetem 0004 segmentu danych
5. do rejestru ds ładujesz adres segmentu danych w którym znajdują się te zmienne
6. do rejestru ax przenieś wartość znajdującą się pod offsetem 0000 (zmienna1)
7. dodaj wartość z rejestru ax do wartości znajdującej się pod offsetem 0002 (zmienna2) i wynik umieść w rejestrze ax
8. skopiuj do zmiennej znajdującej się pod offsetem 0004 (zmienna3) wartość znajdującą się w rejestrze ax

Powyższe kroki musi wykonać mikroprocesor aby wykonać tą krótką instrukcję z języka C ;)
Zakładając że zmienne już gdzieś wpisałeś w pliku *.exe to kod dodający te zmienne w języku maszynowym będzie tak wyglądał:
A10000 - do rejestru ax przenieś wartość znajdującą się pod offsetem 0000 (zmienna1)
03060200 - dodaj wartość z rejestru ax do wartości znajdującej się pod offsetem 0002 (zmienna2) i wynik umieść w rejestrze ax
A30400 - skopiuj do zmiennej znajdującej się pod offsetem 0004 (zmienna3) wartość znajdującą się w rejestrze ax
Oczywiście w pliku *.exe te zmienne są zapisane w jednym ciągu i ten kod wygląda tak:
A1000003060200A30400
a dokładniej tak:
10100001000000000000000000000011000001100000001000000000101000110000010000000000
A w Asemblerze to by wyglądało tak:
mov AX, zmienna1 add AX, zmienna2 mov zmienna3, AX
mov AX, zmienna1 = A10000
add AX, zmienna2 = 03060200
mov zmienna3, AX = A30400

Jak widzisz napisanie kompilatora do języka Asembler jest bardzo prostym zadaniem, natomiast napisanie kompilatora do języka C już nie jest takie proste, a napisanie kompilatora do języka obiektowego jak np. C++ jest jeszcze trudniejszym zadaniem. Dlatego bardzo mnie ciekawi jak napisałeś ten prościutki kompilator do języka C?

P.S.
Stary kompilator Borlanda BC3.1 ma taką fajną opcję, która pozwala na zamianę napisanego programu w języku C/C++ na język Asembler.
Użytkownik Geroj edytował ten post 28 marzec 2008, 22:49
Ja napisalem ze zrobilem programik ktory zamienia tylko rozszerzenie z .cpp na .exe, ale i tak jakos mi sie nie chcial skompilowac. To wcale nie byl zaden "kompilator". No i widze ze znasz sie na rzeczy. Czapki z glow normalnie. Ale dz za pomoc :)

No jasne, że nie chciał ci się "skompilować", bo dla głupiego komputera to dalej będzie kod w języku C++, którego za Chiny nie zrozumie, bo zna tylko zerojedynkowy :) Swoją drogą nigdy nie mogłem sobie wyobrazić, jak ktoś pisząc same zera i jedynki mógł napisać program :)

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • zsf.htw.pl
  •