Notă Din ieșirea de mai sus a fișierului preprocesat că, deoarece programul nostru a solicitat stdio.h antet fi incluse în sursa noastră, care, la rândul său, a solicitat o grămadă de alte fișiere antet.
compilare
următorul pas este să luați fișierul Preprocesat ca intrare, să îl compilați și să produceți o ieșire compilată intermediară. Fișierul de ieșire pentru această etapă produce codul de asamblare care depinde de mașină.
folosind steagul”- s ” cu gcc putem converti codul sursă C preprocesat în limbajul de asamblare fără a crea un fișier obiect:
$ gcc -S HelloWorld.i -o HelloWorld.s
deși eu nu sunt de mult în programarea nivel de asamblare, dar o privire rapidă concluzionează că această ieșire nivel de asamblare este într-o formă de instrucțiuni pe care asamblorul poate înțelege și converti în limbaj de nivel mașină.
Adunarea
după cum știm cu toții ,mașinile pot înțelege numai limbaj binar, asa ca acum avem nevoie de un asamblor care convertește codul de asamblare în „HelloWorld.c ” fișier în cod binar.
ASSEMBLER a fost unul dintre primele instrumente software dezvoltate după inventarea computerului digital.
dacă există apeluri către funcții externe în codul de asamblare, Asamblorul lasă adresele funcțiilor externe nedefinite, pentru a fi completate ulterior de Linker.
Asamblorul poate fi invocat așa cum se arată mai jos. Prin utilizarea” – c ” pavilion în gcc putem converti codul de asamblare în codul de nivel mașină:
$ gcc -c HelloWorld.c -o HelloWorld.o
singurul lucru pe care îl putem explica uitându-ne la HelloWorld.o fișier este despre ELF șir în prima linie. ELF standuri pentru format executabil și linkable.
un fișier obiect și un fișier executabil vin în mai multe formate, cum ar fi ELF (Executable and Linking Format) și COFF (Common Object-File Format). De exemplu, ELF este utilizat pe sistemele Linux, în timp ce COFF este utilizat pe sistemele Windows.
acesta este un format relativ nou pentru fișierele obiect la nivel de mașină și executabil care sunt produse de gcc. Înainte de aceasta, a fost utilizat un format cunoscut sub numele de.out. Se spune că ELF este un format mai sofisticat decât a.out (s-ar putea să săpăm mai adânc în formatul ELF într-un alt articol viitor).
dacă compilați codul fără a specifica numele fișierului de ieșire, fișierul de ieșire produs are numele ‘a.out’, dar formatul s-a schimbat acum în ELF. Doar că numele fișierului executabil implicit rămâne același.
legarea
aceasta este faza finală în care se realizează toate legăturile apelurilor de funcții cu definițiile lor. Linker știe unde sunt implementate toate aceste funcții (Assembler a lăsat adresa tuturor funcțiilor externe care urmează să fie apelate). Până în această etapă GCC nu știe despre funcția ca printf ().Asamblorul ar fi lăsat adresa funcțiilor care urmează să fie apelate și Linker face procesul final de completare a acestor adrese cu definițiile reale. Linker-ul face, de asemenea, câteva sarcini suplimentare pentru noi. Acesta combină programul nostru cu unele rutine standard, care sunt necesare pentru a face rula programul nostru. Deci, dimensiunea executabil final este mult mai mult decât fișierul de intrare!
întregul proces de legătură este gestionat de gcc și invocat după cum urmează:
$ gcc -o Output HelloWorld.c
comanda de mai sus rulează fișierul „HelloWorld.c „și produce fișierul executabil final”ieșire”.
după cum puteți vedea , ‘ieșire’ fișier este implicit un fișier executabil cu permisiuni-rwxrwxr-x ,Acest lucru înseamnă doar că are permisiunea executabil pentru toți utilizatorii(proprietar,grup și altele). Dacă executați acest fișier executabil prin simpla tastare’./ Output ‘ veți obține rezultatul final al programului nostru !
Deci, acum știm cum un program C devine convertit într-un executabil . Ne vom scufunda puțin mai adânc în programarea C în articolele următoare. Până atunci, învățare fericită! 🙂