Introducere în limbajul Assembler. Caracteristici specifice ale limbajului de asamblare

Am cultivat această idee de mult timp. Probabil că am luat-o cu asalt din toate părțile timp de câțiva ani și de fiecare dată când ne-a ieșit ceva în cale. Pe de o parte, asamblatorul este la fel de cool pe cât poate fi abilitatea de a comunica cu un computer în limbajul său pentru cititorul-hacker (cracker, reverser). Pe de altă parte, există suficiente manuale actuale despre ASCM, inclusiv publicațiile acestui secol, iar zilele acestea sunt liberale, hackerii web și iubitorii de JS s-ar putea să nu ne înțeleagă sau să ne aprobe. 🙂 Succesul a pus capăt disputei dintre fizicieni, textieri, vechi credincioși, nikonieni, hackeri web și crackeri ai muncii. S-a dovedit că acum, în secolul XXI, crackerii forței de muncă încă nu au renunțat la pozițiile lor și cititorii noștri sunt interesați de acest lucru!

Dar ce este programarea în sine în esența sa, indiferent de orice limbaj? Varietatea răspunsurilor este uimitoare. Cel mai adesea puteți auzi această definiție: programarea este compilarea de instrucțiuni sau comenzi pentru execuția secvențială de către o mașină pentru a rezolva o anumită problemă. Acest răspuns este destul de corect, dar, în opinia mea, nu reflectă plenitudinea, de parcă am numi literatura o compilație de cuvinte din propoziții pentru citire secvențială de către cititor. Înclin să cred că programarea este mai aproape de creativitate, de artă. Ca orice tip de artă - expresia gândurilor creative, ideilor, programarea este o reflectare a gândirii umane. O idee poate fi atât genial, cât și complet mediocră.

Dar, indiferent de tipul de programare pe care îl facem, succesul depinde de abilitățile practice, împreună cu cunoașterea principiilor și teoriei fundamentale. Teorie și practică, studiu și muncă - acestea sunt pietrele de temelie pe care se bazează succesul.

Recent, assembler a fost nemeritat în umbra altor limbi. Acest lucru se datorează comercializării globale, care vizează obținerea unui profit cât mai mare din produs în cel mai scurt timp posibil. Cu alte cuvinte, caracterul de masă a prevalat asupra elitismului. Și assembler, după părerea mea, este mai aproape de acesta din urmă. Este mult mai profitabil să antrenezi un student în, de exemplu, limbaje precum C++, C#, PHP, Java, JavaScript, Python într-un timp relativ scurt, astfel încât să fie mai mult sau mai puțin capabil să creeze software de calitate pentru consumator. fără să-și pună întrebări de ce și de ce face asta decât să elibereze bun specialistîn asamblator. Un exemplu în acest sens este piața vastă pentru tot felul de cursuri de programare în orice limbă, cu excepția asamblarii. Aceeași tendință poate fi observată atât în ​​predarea la universități, cât și în literatura educațională. În ambele cazuri, până la astăzi cea mai mare parte a materialului se bazează pe procesoarele din seria 8086 timpurie, pe așa-numitul mod de funcționare „real” pe 16 biți, Mediul de operare MS-DOS! Este posibil ca unul dintre motive să fie că, pe de o parte, odată cu apariția calculatoare IBM Profesorii de PC au trebuit să treacă la această platformă specială din cauza indisponibilității altora. Pe de altă parte, pe măsură ce s-a dezvoltat linia 80x86, a rămas capacitatea de a rula programe în modul DOS, ceea ce a făcut posibilă economisirea banilor la achiziționarea unora noi calculatoare educaționaleși compilarea manualelor pentru studiul arhitecturii noilor procesoare. Cu toate acestea, acum o astfel de alegere a platformei de studiu este complet inacceptabilă. MS-DOS ca mediu de execuție a programelor a fost depășit fără speranță la mijlocul anilor 90, iar odată cu trecerea la procesoare pe 32 de biți, începând cu procesorul 80386, sistemul de comandă în sine a devenit mult mai logic. Deci, nu are rost să pierdem timpul studiind și explicând ciudateniile arhitecturii modul real, care cu siguranță nu va apărea niciodată pe niciun procesor.

În ceea ce privește alegerea unui mediu de operare pentru învățarea asamblatorului, dacă vorbim despre sistemul de instrucțiuni pe 32 de biți, alegerea este relativ mică. Acestea sunt fie sisteme de operare Windows, fie reprezentanți ai familiei UNIX.

De asemenea, ar trebui să spuneți câteva cuvinte despre ce asamblator să alegeți pentru un anumit mediu de operare. După cum știți, două tipuri de sintaxă de asamblare sunt utilizate pentru a funcționa cu procesoarele x86 - sintaxa AT&T și sintaxa Intel. Aceste sintaxe reprezintă aceleași comenzi în moduri complet diferite. De exemplu, comanda din sintaxa Intel arată astfel:

Mutare eax, ebx

Sintaxa AT&T va avea o formă diferită:

Movl %eax,%ebx

Sintaxa de tip AT&T este însă mai populară în mediul UNIX OS mijloace didactice nu există informații despre acesta, este descris exclusiv în literatura de referință și tehnică. Prin urmare, este logic să alegeți un asamblator bazat pe sintaxa Intel. Pentru sistemele UNIX există doi asamblatori principali - NASM (Netwide Assembler) și FASM (Flat Assembler). Pentru linia Windows, FASM și MASM (Macro Assembler) de la Microsoft, și a existat și TASM (Turbo Assembler) de la Borland, care cu destul de mult timp în urmă a refuzat să-și susțină propria creație.

În această serie de articole vom studia în Mediul Windows bazat pe limbajul de asamblare MASM (pur și simplu pentru că îmi place mai mult). Mulți autori, în stadiul inițial al învățării asamblatorului, îl introduc în shell-ul limbajului C, pe baza considerațiilor că se presupune că este destul de dificil să treci la exemple practice în mediul de operare: trebuie să cunoști atât elementele de bază ale programării în it și comenzile procesorului. Cu toate acestea, această abordare necesită și cel puțin cele mai mici rudimente de cunoaștere în limbajul C. Încă de la început, această serie de articole se va concentra doar asupra asamblatorului în sine, fără a confunda cititorul cu orice altceva care este de neînțeles pentru el, deși în viitor va fi urmărită o legătură cu alte limbi.

Trebuie remarcat faptul că atunci când învățați elementele de bază ale programării, iar acest lucru se aplică nu numai programării de asamblare, este extrem de util să aveți o înțelegere a culturii aplicațiilor console. Și este complet nedorit să începeți imediat să învățați prin crearea de ferestre, butoane, adică cu aplicații cu ferestre. Există o părere că consola este o relicvă arhaică a trecutului. Cu toate acestea, nu este. Aplicația de consolă este aproape lipsită de orice dependență externă de învelișul ferestrei și se concentrează în principal pe îndeplinirea unei sarcini specifice, ceea ce oferă o oportunitate excelentă, fără a fi distras de nimic altceva, de a se concentra asupra studiului principii de baza atât programarea, cât și asamblatorul în sine, inclusiv familiaritatea cu algoritmii și dezvoltarea acestora pentru a rezolva probleme practice. Și până când vine momentul să treceți la familiarizarea cu aplicațiile ferestre, veți avea deja o cantitate impresionantă de cunoștințe în spate, o înțelegere clară a funcționării procesorului și, cel mai important, conștientizarea acțiunilor dvs.: cum și ce funcționează, de ce și de ce.

Ce este asamblatorul?

Cuvântul în sine asamblator(assembler) este tradus din engleză ca „assembler”. De fapt, acesta este numele unui program de traducere care ia ca text de intrare care conține simboluri ale comenzilor mașinii care sunt convenabile pentru oameni și traduce aceste simboluri într-o secvență de coduri de comandă a mașinii corespunzătoare care sunt înțelese de procesor. Spre deosebire de instrucțiunile mașinii, convențiile lor, numite și mnemonice, sunt relativ ușor de reținut deoarece sunt abrevieri ale cuvintelor englezești. În cele ce urmează, pentru simplitate, ne vom referi la mnemonici ca instrucțiuni de asamblare. Se numește limbajul convențiilor limbaj de asamblare.

În zorii erei computerelor, primele computere ocupau încăperi întregi și cântăreau mai mult de o tonă, cu o capacitate de memorie de mărimea creierului unei vrăbii, sau chiar mai mică. Singura modalitate de a programa în acele vremuri era să introduci programul în memoria computerului direct în formă digitală, comutând întrerupătoarele, firele și butoanele. Numărul acestor comutatoare putea ajunge la câteva sute și creștea pe măsură ce programele deveneau mai complexe. A apărut întrebarea despre economisirea timpului și a banilor. De aceea urmatorul pas dezvoltarea a fost apariția la sfârșitul anilor patruzeci ai secolului trecut a primului traducător-asamblator, care face posibilă scrierea comodă și simplă a comenzilor mașinii în limbajul uman și, ca urmare, automatizarea întregului proces de programare, simplificarea, accelerarea dezvoltarea de programe și depanarea acestora. Apoi au venit limbile nivel inaltȘi compilatoare(generatoare de cod mai inteligente dintr-un limbaj mai citit de om) și interpreți(executorii unui program scris de om din mers). S-au îmbunătățit și s-au îmbunătățit - și în cele din urmă s-a ajuns la punctul în care puteți programa pur și simplu cu mouse-ul.

Deci, asamblatorul este mecanic orientat spre limbaj programare, care vă permite să lucrați direct cu computerul, unul la unul. De aici formularea sa completă - un limbaj de programare nivel scăzut a doua generație (după Codul mașinii). Comenzile din limbajul de asamblare corespund una la una comenzilor de procesor, dar deoarece există diferite modele de procesor cu propriul set de instrucțiuni, atunci, în consecință, există varietăți, sau dialecte, de limbaj de asamblare. Prin urmare, utilizarea termenului „limbaj de asamblare” poate duce la concepția greșită că există un singur limbaj de nivel scăzut sau cel puțin un standard pentru astfel de limbi. Nu exista. Prin urmare, atunci când denumim limba în care este scris un anumit program, este necesar să se clarifice ce arhitectură este destinat și ce dialect al limbii este scris. Deoarece asamblatorul este legat de dispozitivul procesor, iar tipul de procesor determină strict setul de instrucțiuni disponibile limbajul mașinii, atunci programele de asamblare nu sunt portabile pe alte arhitecturi de computer.

Deoarece assemblerul este doar un program scris de o persoană, nimic nu împiedică un alt programator să-și scrie propriul asambler, ceea ce se întâmplă adesea. De fapt, nu este atât de important ce limbaj de asamblare să studiezi. Principalul lucru este să înțelegeți însuși principiul de funcționare la nivelul comenzilor procesorului și atunci nu va fi dificil să stăpâniți nu numai un alt asamblator, ci și orice alt procesor cu propriul set de comenzi.

Sintaxă

Nu există un standard general acceptat pentru sintaxa limbajelor de asamblare. Cu toate acestea, majoritatea dezvoltatorilor de limbaje de asamblare urmează abordări tradiționale generale. Principalele astfel de standarde sunt Sintaxa IntelȘi Sintaxa AT&T.

Formatul general pentru instrucțiunile de înregistrare este același pentru ambele standarde:

[etichetă:] opcode [operanzi] [;comentar]

Un opcode este de fapt o comandă de asamblare, un mnemonic al instrucțiunilor către procesor. Pot fi adăugate prefixe (de exemplu, repetări, modificări ale tipului de adresare). Operanzii pot fi constante, nume de registre, adrese din RAM și așa mai departe. Diferențele dintre standardele Intel și AT&T se referă în principal la ordinea în care operanzii sunt listați și la sintaxa lor pentru diferite metode de adresare.

Comenzile folosite sunt de obicei aceleași pentru toate procesoarele din aceeași arhitectură sau familie de arhitecturi (printre cele cunoscute sunt comenzi pentru procesoare și controlere Motorola, ARM, x86). Acestea sunt descrise în specificațiile procesorului.

Original: începeți în limbajul de asamblare. Partea 1
Autor: Mike Saunders
Data publicării: 30 octombrie 2015
Traducere: A. Panin
Data traducerii: 10 noiembrie 2015

Partea 1: Depășirea limitărilor limbajelor de programare de nivel înalt și înțelegerea modului în care funcționează de fapt unitatea centrală de procesare.

Pentru ce este?

  • Pentru a înțelege cum funcționează compilatoarele.
  • Pentru a înțelege instrucțiunile CPU.
  • Pentru a vă optimiza codul pentru performanță.

Majoritatea oamenilor cred că limbajul de asamblare nu este mult diferit de magia neagră și face parte dintr-o lume întunecată și înfricoșătoare în care doar 0,01% îndrăznesc să intre. cei mai buni dezvoltatori software. Dar de fapt este un limbaj de programare frumos și foarte accesibil. Ar trebui să le studiați elementele de bază cel puțin pentru a înțelege mai bine mecanismul de generare a codului de către compilatoare, principiul de funcționare al procesoarelor centrale și, de asemenea, pentru a înțelege mai bine principiul de funcționare a computerelor. Limbajul de asamblare este în esență o reprezentare textuală a instrucțiunilor pe care le execută unitatea centrală de procesare, cu câteva caracteristici suplimentare care simplifică procesul de programare.

Astăzi, nimeni în mintea sa nu ar dezvolta o aplicație desktop puternică în limbaj de asamblare. La urma urmei, codul unei astfel de aplicații va fi prea confuz, procesul de depanare a aplicației va fi mult mai complicat și, în plus, vor trebui depuse eforturi enorme pentru a porta această aplicație pentru a funcționa cu alte arhitecturi de procesor central. Cu toate acestea, limbajul de asamblare este încă folosit pentru o varietate de scopuri: multe drivere din nucleul Linux conțin bucăți de cod în limbaj de asamblare, care este folosit atât pentru că este cel mai bun limbaj de programare pentru interacțiunea directă cu hardware-ul, cât și din motive de eficiență a șoferilor. De asemenea, în anumite cazuri, codul scris manual în limbaj de asamblare poate fi mai rapid decât codul generat de compilator.

În articolele din această serie, vom explora lumea limbajului de asamblare în detaliu. În acest articol ne vom uita doar la tehnicile de programare de bază, în articolul din numărul următor al revistei ne vom ocupa de probleme mai complexe, după care vom termina considerația limbajului de asamblare scriind o încărcare simplă. sistem de operare- nu va putea executa niciuna muncă utilă, dar se va baza pe codul dvs. și va funcționa direct cu hardware-ul fără a fi nevoie să descărcați niciun sistem de operare terță parte. Sună bine, nu-i așa? să începem

Primul program în limbaj de asamblare

Multe tutoriale de programare în limbaj de asamblare încep cu secțiuni lungi, confuze și plictisitoare, care continuă la nesfârșit despre aritmetica binară și teoria proiectării CPU fără a conține de fapt niciun cod real. Consider că astfel de materiale anulează interesul cititorului, așa că vom începe direct cu o revizuire a codului program real. După aceea, ne vom uita la fiecare dintre liniile de cod ale acestui program, astfel încât să înțelegeți principiul limbajului de asamblare pe baza unui exemplu practic.

Unele editoare de text, cum ar fi Vim, oferă evidențierea sintaxei în limbajul de asamblare (încercați să utilizați comanda set syn=nasm)

Copiați următorul cod în câmpul de text al oricărui editor de text și salvați-l într-un fișier numit myfirst.asm în directorul dvs. de acasă:

Secțiunea .text global _start _start: mov ecx, mesaj mov edx, lungime mov ebx, 1 mov eax, 4 int 0x80 mov eax, 1 int 0x80 secțiune .data mesaj db „Reguli de asamblare!”, 10 lungime equ $ - mesaj

(Notă: puteți folosi fie spații, fie tabulaturi pentru a indenta codul - nu contează.) Acest program pur și simplu imprimă linia „Reguli de asamblare!” la ecran și iese.

Instrumentul pe care îl vom folosi pentru a converti acest cod de limbaj de asamblare într-un fișier binar executabil are numele destul de amuzant de „assembler”. Există mulți asamblatori diferiți, dar asamblatorul meu preferat este NASM; se află în depozitul de pachete software din aproape fiecare distribuție, așa că îl puteți instala folosind managerul de pachete software GUI, yum install nasm , apt-get install nasm sau orice comandă este relevantă pentru distribuția dvs.

Acum deschideți o fereastră de emulator de terminal și introduceți următoarele comenzi:

Nasm -f elf -o myfirst.o myfirst.asm ld -m elf_i386 -o myfirst myfirst.o

Prima comandă este de a genera un fișier de cod obiect numit myfirst.o folosind NASM (format de fișier executabil utilizat în Linux). Vă puteți întreba: „De ce este generat un fișier de cod obiect, deoarece ar fi mai logic să generați un fișier cu instrucțiunile pentru procesorul central pe care ar trebui să le execute?” Ei bine, ai putea folosi un executabil cu instrucțiuni CPU în sistemele de operare din anii 80, dar sistemele de operare moderne au mai multe cerințe pentru executabile. Binarele ELF includ informații de depanare și permit codul și datele să fie separate prin existența unor secțiuni separate pentru a preveni suprascrierea datelor din acele secțiuni.

Mai târziu, în procesul de luare în considerare a metodologiei de scriere a codului să funcționeze direct cu hardware (pentru sistemul nostru de operare minimalist), ca parte a acestei serii de articole, vom acorda atenție unor astfel de fișiere binare cu instrucțiuni de la procesorul central.

O privire în trecut

În acest moment, avem la dispoziție fișierul myfirst.o cu codul executabil al programului nostru. Cu toate acestea, procesul de construire a programului nu a fost încă finalizat; Folosind linker-ul ld, trebuie să conectăm codul din acest fișier cu codul special de pornire a sistemului (adică, codul standard care este executat la lansarea fiecărui program) pentru a genera fisier executabil numit primul meu. (Parametrul elf_i386 descrie tipul de format binar - în acest caz, aceasta înseamnă că puteți utiliza cod de asamblare pe 32 de biți chiar dacă utilizați o distribuție pe 64 de biți.)

Dacă procesul de construire programul va avea loc cu succes, veți putea executa programul folosind următoarea comandă:

Ca rezultat, ar trebui să vedeți rezultatul: „Reguli de asamblare!”. Aceasta înseamnă că v-ați atins obiectivul - ați creat un program independent cu drepturi depline pentru Linux, al cărui cod este scris în întregime în limbaj de asamblare. Desigur, acest program nu efectuează acțiuni utile, dar este un exemplu excelent care demonstrează structura unui program în limbaj de asamblare și vă permite să urmăriți procesul de conversie cod sursaîntr-un fișier binar.

Înainte de a ne scufunda în cod, ar fi o idee bună să cunoaștem dimensiunea fișierului binar al programului nostru. După rularea comenzii ls -l myfirst, veți vedea că dimensiunea fișierului binar este de aproximativ 670 de octeți. Acum să estimăm dimensiunea unui program echivalent în C:

#include int main() (puts("Reguli de asamblare!"); )

Dacă salvați acest cod într-un fișier numit test.c, îl compilați (gcc -o test test.c) și vă uitați la parametrii fișierului binar rezultat numit test, veți descoperi că acest fișier este mult mai mare ca dimensiune - 8.4 k. Puteți elimina informațiile de depanare din acest fișier (testul strip -s), dar chiar și atunci dimensiunea acestuia va fi redusă ușor, doar la 6 k. Acest lucru se datorează faptului că compilatorul GCC adaugă o mulțime din codul menționat mai sus pentru a porni și opri aplicația și, de asemenea, leagă aplicația cu biblioteca limbajului de programare C. marime mare. Mulțumită acest exemplu Este ușor de concluzionat că limbajul de asamblare este cel mai bun limbaj de programare pentru dezvoltarea aplicațiilor destinate utilizării în conditii grele limitări ale capacității suportului de stocare.

Merită menționat faptul că mulți dezvoltatori de limbaje de asamblare câștigă salarii excelente pentru dezvoltarea codului pentru dispozitive încorporate cu resurse limitate, motiv pentru care limbajul de asamblare este singura opțiune reală pentru dezvoltarea de jocuri pentru console mai vechi pe 8 biți și computere de acasă.

Cod de demontare

Dezvoltarea unui cod nou este distractiv, dar cercetarea muncii altora poate fi și mai distractiv. Datorită unui instrument numit objdump (din pachetul Binutils), puteți „dezasambla” un fișier executabil, adică să convertiți instrucțiunile CPU în echivalentele lor text. Încercați să utilizați acest instrumentîn legătură cu myfirst binar la care am lucrat în acest tutorial, după cum urmează:

Objdump -d -M intel myfirst

Veți vedea o listă de instrucțiuni din secțiunea de cod a fișierului binar. De exemplu, prima instrucțiune, cu care am plasat informații despre locația șirului nostru în registrul ecx, arată astfel:

Mutare ecx,0x80490a0

În timpul procesului de asamblare, NASM a înlocuit eticheta liniei „mesaj” cu o valoare numerică corespunzătoare locației acestei linii în secțiunea de date a fișierului binar. Astfel, rezultatele dezasamblarii fișierelor binare sunt mai puțin utile decât acestea codul original, pentru că le lipsesc lucruri precum comentariile și șirurile de caractere, dar pot fi totuși utile pentru a vă familiariza cu implementările de funcții critice de timp sau pentru a distruge sistemele de securitate ale aplicațiilor. De exemplu, în anii 80 și 90, mulți dezvoltatori au folosit instrumente de dezasamblare a software-ului pentru a identifica și neutraliza sistemele de protecție împotriva copierii jocurilor.

De asemenea, puteți dezasambla programele dezvoltate folosind alte limbaje de programare, dar rezultatele dezasamblarii rezultate pot fi semnificativ mai complexe. De exemplu, puteți rula comanda objdump de mai sus împotriva fișierului binar /bin/ls și puteți evalua în mod independent miile de linii de secțiuni de cod generate de compilator pe baza codului sursă C original al utilitarului.

Analiza codului

Acum să discutăm despre scopul fiecărei linii de cod din programul nostru. Să începem cu aceste două rânduri:

Secțiunea .text global _start

Acestea nu sunt instrucțiuni CPU, ci directive de asamblare. NASM; Prima directivă prevede că codul de mai jos ar trebui să fie localizat în secțiunea de cod „text” a executabilului final. Puțin neevident este faptul că secțiunea numită „text” nu conține date text obișnuite (cum ar fi linia noastră „Reguli de asamblare!”), ci cod executabil, adică instrucțiuni de la procesorul central. Urmează directiva globală _start, care spune linkerului ld în ce moment ar trebui să înceapă execuția codului din fișierul nostru. Această directivă poate fi utilă în special dacă dorim să începem executarea codului nu chiar de la începutul secțiunii de cod, ci de la unele punct dat. Parametrul global permite ca această directivă să fie citită nu numai de către asamblator, ci și de către alte instrumente, deci este procesată de linker-ul ld.

După cum sa menționat mai sus, execuția codului trebuie să înceapă la poziția _start. Din acest motiv, indicăm în mod explicit poziția corespunzătoare în codul nostru:

Cuvintele individuale cu două puncte la sfârșit se numesc etichete și sunt menite să indice pozițiile din cod la care putem sări (mai multe despre asta în următorul articol din serie). Astfel, execuția programului începe din această linie! Mai mult, am ajuns în sfârșit la primul instrucțiuni reale CPU:

Mov ecx, mesaj

Limbajul de asamblare este în esență un set de mnemonice pentru instrucțiunile CPU (sau codul mașinii). În acest caz, mov este o astfel de instrucțiune - poate fi scrisă și într-un format binar care poate fi citit de CPU, cum ar fi 10001011. Dar lucrul cu date binare poate fi un coșmar pentru noi, oamenii obișnuiți, așa că vom folosi aceste opțiuni mai lizibile. Asamblatorul pur și simplu convertește instrucțiunile textuale în echivalentele lor binare - deși se poate executa muncă în plus, despre care vom vorbi în următoarele articole din serie.

Oricum ar fi, pentru a înțelege scopul acestei linii de cod, trebuie să înțelegem și conceptul de registre. Unitățile centrale de procesare nu efectuează operații deosebit de complexe - pur și simplu mută datele în memorie, le folosesc pentru a efectua calcule și efectuează alte operații în funcție de rezultate. Procesorul central habar n-are ce este un monitor, mouse sau imprimantă. Pur și simplu mută datele și efectuează mai multe tipuri de calcule.

În acest moment, principala stocare pentru datele utilizate de procesorul central sunt băncile dumneavoastră de RAM. Dar datorită faptului că memoria RAM este situată în afara procesorului central, accesarea acestuia durează mult timp. Pentru a accelera și simplifica procesul descris, unitatea centrală de procesare conține propriul său grup mic de celule de memorie numite registre. Instrucțiunile CPU pot folosi aceste registre direct, iar în această linie de cod folosim un registru numit ecx.

Este un registru pe 32 de biți (prin urmare, poate stoca numere de la 0 la 4.294.967.295). Pe măsură ce vă uitați la următoarele linii de cod, veți vedea că lucrăm și cu registrele edx, ebx și eax - acestea sunt registre de uz general care pot fi folosite pentru a îndeplini orice sarcină, spre deosebire de registrele specializate pe care le avem. ma voi uita luna viitoare. Și aceasta este o mică explicație pentru cei care sunt dornici să cunoască originea numelor de registre: registrul ecx a fost numit c în timpul lansării procesoarelor pe 8 biți, după care a fost redenumit cx pentru stocarea valorilor pe 16 biți și ecx pentru stocarea valorilor pe 32 de biți. Deci, deși numele de registre arată puțin ciudat în zilele noastre, pe vremea procesoarelor mai vechi, dezvoltatorii foloseau registre de uz general cu nume distincte a, b, c și d.

Odată ce ai început, nu te vei mai putea opri.

Unul dintre subiectele pe care le vom acoperi luna viitoare este utilizarea stivei, așa că vă vom pregăti să acoperiți asta acum. Stiva este o zonă de memorie în care valorile temporare pot fi stocate atunci când registrele trebuie eliberate în alte scopuri. Dar cea mai importantă caracteristică a stivei este modul în care stochează datele: veți „împinge” valorile pe stivă și le veți „pop” din acesta. Stiva folosește principiul LIFO (last in, first out), ceea ce înseamnă că ultima valoare adăugată la stivă va fi prima care va fi scoasă din ea.

Imaginați-vă că aveți, de exemplu, o geantă Pringles goală și puneți lucruri în ea... următoarea secvență: un cracker cu două straturi, un cip cu caracterul „Alf” și un disc de pe consola GameCube. Dacă începeți să eliminați aceste lucruri, veți elimina mai întâi discul GameCube, apoi cipul de caractere Alpha și așa mai departe. Când lucrați cu limbajul de asamblare, stiva este utilizată după cum urmează:

Push 2 push 5 push 10 pop eax pop ebx pop ecx

După ce aceste șase instrucțiuni sunt executate, registrul eax va conține o valoare de 10, registrul ebx va conține o valoare de 5, iar registrul ecx va conține o valoare de 2. Astfel, utilizarea stivei este o modalitate excelentă de a elibera temporar. registre; Dacă, de exemplu, există valori importante în registrele eax și ebx, dar trebuie să faceți lucrul curent înainte de a le procesa, puteți împinge acele valori în stivă, puteți face munca curentă și le puteți scoate din stivă, revenind la starea anterioară registre

În plus, stiva este folosită la apelarea subrutinelor pentru a stoca adresa de retur la codul principal. Din acest motiv, trebuie să aveți grijă deosebită atunci când lucrați cu stiva - dacă suprascrieți datele stocate în acesta, nu veți putea reveni la o poziție anterioară în codul principal al aplicației, configurandu-vă pentru un singur sens. accident!

Sa trecem peste

Înapoi la cod: instrucțiunea mov mută (de fapt copiază) un număr dintr-un loc în altul, de la dreapta la stânga. Deci, în acest caz, spunem „mesajul ar trebui să fie plasat în registrul ecx”. Dar ce este „mesajul”? Acesta nu este un alt registru, este un pointer către locația datelor. Aproape de sfârșitul codului, în secțiunea „date”, puteți găsi o etichetă de mesaj urmată de un parametru db, care indică faptul că ar trebui plasați câțiva octeți în cod în locul etichetei mesajului. Acest lucru este foarte convenabil, deoarece nu trebuie să aflăm locația exactă a „Regulilor de asamblare”. în secțiunea de date - ne putem referi pur și simplu la ea folosind eticheta mesajului. (Numărul 10 după linia noastră este doar un caracter newline, similar cu caracterul \n adăugat la linii atunci când lucrați cu limbajul de programare C.)

Așa că punem datele despre locația șirului în registrul ecx. Dar ceea ce facem în continuare este deosebit de interesant. După cum am menționat mai devreme, procesorul nu are niciun concept real de dispozitive hardware - pentru a scoate ceva pe ecran, va trebui să trimiteți date pe placa video sau să mutați datele în memoria RAM a plăcii video. Dar nu avem nicio informație despre locația RAM-ului acestei plăci video, în plus, toată lumea folosește plăci video diferite, setări de server X window system, manageri de ferestre etc. Pe baza acestui fapt, afișarea directă a ceva pe ecran folosind un program mic este practic imposibilă în cazul nostru.

Așa că vom cere nucleului sistemului de operare să facă acest lucru pentru noi. Nucleul Linux oferă aplicațiilor de nivel scăzut un număr mare de apeluri de sistem pe care aplicațiile le pot folosi pentru a iniția execuția. diverse operatii la nivelul nucleului. Unul dintre aceste apeluri de sistem este pentru ieșire șir de text. Odată ce acest apel de sistem este utilizat, nucleul sistemului de operare face toate lucrările necesare - și, desigur, oferă un nivel și mai profund de abstractizare în care linia poate fi scoasă de către un terminal text obișnuit, un emulator de terminal de sistem de ferestre X sau chiar scris într-un fișier deschis anterior.

Cu toate acestea, înainte de a spune nucleului OS să imprime un șir de text, va trebui să îi spunem Informații suplimentare, pe lângă informații despre locația șirului deja în registrul ecx. De asemenea, va trebui să îi spunem câte caractere trebuie să fie scoase, astfel încât ieșirea liniei să nu continue după sfârșitul acesteia. Pentru asta este folosită linia din secțiunea de date de la sfârșitul codului aplicației:

Lungime equ $ - mesaj

Această linie folosește o etichetă de lungime diferită, dar în loc să folosim parametrul db pentru a asocia acea etichetă cu unele date, folosim parametrul equ pentru a indica faptul că această etichetă este echivalentă cu ceva (aceasta este un pic ca directiva #define preprocesor din C limbaj de programare). Semnul dolar corespunde poziției curente în cod, așa că în acest caz spunem „eticheta de lungime trebuie să fie echivalentă cu poziția curentă din cod minus locația liniei etichetate „mesaj””.

Să revenim la secțiunea din codul aplicației în care plasăm valoare datăîn registrul edx:

Mov edx, lungime

Totul merge bine: două registre sunt umplute cu informații despre locația liniei și numărul de caractere ale liniei care urmează să fie scoase. Dar înainte de a spune nucleului sistemului de operare să-și facă partea sa din treabă, trebuie să-i oferim puțin mai multe informații. În primul rând, trebuie să spunem nucleului sistemului de operare care „mâner de fișier” ar trebui folosit - cu alte cuvinte, unde ar trebui să fie direcționată ieșirea. Acest subiect depășește domeniul de aplicare al tutorialului limbajului de asamblare, așa că să spunem doar că trebuie să folosim fluxul de ieșire standard stdout , ceea ce înseamnă: imprimați o linie pe ecran. Fluxul de ieșire standard folosește un mâner fix de 1, pe care îl punem în registrul ebx.

Suntem acum extrem de aproape de a efectua apelul de sistem, dar mai există încă un registru care trebuie completat. Nucleul sistemului de operare poate efectua un număr mare de operațiuni diferite, cum ar fi montarea sistemelor de fișiere, citirea datelor din fișiere, ștergerea fișierelor și altele. Mecanismele corespunzătoare sunt activate folosind apelurile de sistem menționate și înainte de a transfera controlul către kernel-ul sistemului de operare, va trebui să îi spunem ce apel de sistem trebuie utilizat. Pe pagină puteți găsi informații despre unele dintre apelurile de sistem disponibile pentru programe - în cazul nostru, este necesar apelul de sistem sys_write („scrierea datelor într-un descriptor de fișier”) cu numărul 4. Prin urmare, vom plasa numărul acestuia în registru eax:

Și e tot! Am făcut toate pregătirile necesare pentru a efectua apelul de sistem, așa că acum vom transfera pur și simplu controlul către nucleul sistemului de operare, după cum urmează:

Instrucțiunea int înseamnă „interrrupt” și întrerupe literalmente fluxul de execuție al unui anumit program, trecând în spațiul kernel-ului OS. (În acest caz este folosit valoare hexazecimală 0x80 - nu trebuie să vă faceți griji pentru moment.) Nucleul sistemului de operare va imprima șirul indicat de valoarea din registrul ecx și apoi va returna controlul programului nostru.

Pentru a termina execuția programului, trebuie efectuat apelul de sistem sys_exit, care este numerotat 1. Prin urmare, plasăm acest numărîn registrul eax, întrerupem din nou execuția programului nostru, după care nucleul sistemului de operare oprește cu atenție execuția programului nostru și revenim la salutul shell-ului de comandă. Putem spune că ați finalizat sarcina: ați implementat un program complet (deși foarte simplu) în limbaj de asamblare, al cărui cod a fost dezvoltat manual, fără a utiliza biblioteci extinse.

Am acoperit destul de multe aspecte ale utilizării limbajului de asamblare în acest tutorial și, așa cum am menționat mai devreme, ne-am putea concentra doar pe informațiile teoretice. Cu toate acestea, încă sper că ați găsit util programul de exemplu real, iar în numărul următor al revistei vom petrece mai mult timp acoperind unele dintre conceptele care au fost abordate în acest tutorial. În plus, ne vom îmbunătăți programul adăugând logica și subrutine - versiuni în limbaj de asamblare ale instrucțiunilor if și goto.

În timp ce vă familiarizați cu codul acestui program, puteți încerca să îl modificați singur pentru a efectua următoarele operații:

  • Ieșiți un șir diferit, mai lung.
  • Ieșiți două linii, una după alta.
  • Returnează codul de ieșire al aplicației modificat shell de comandă(pentru aceasta va trebui să utilizați motor de căutare Google!).

Dacă întâmpinați dificultăți și aveți nevoie de ajutor, vizitați forumul nostru la http://forums.linuxvoice.com - autorul ghidului va fi în apropiere și va fi bucuros să vă ghideze pe calea cea bună. Programare fericită!

Limbaj de programare

Assembler este un limbaj de programare de nivel scăzut, care este un format pentru înregistrarea comenzilor mașinii care este convenabil pentru percepția umană.

Comenzile din limbajul de asamblare corespund una la una comenzilor procesorului și, de fapt, reprezintă o formă simbolică convenabilă de înregistrare (cod mnemonic) a comenzilor și a argumentelor acestora. Limbajul de asamblare oferă, de asemenea, abstracții de programare de bază: legarea părților programului și a datelor prin etichete și directive denumite simbolic.

Directivele de asamblare vă permit să includeți blocuri de date (descrise explicit sau citite dintr-un fișier) într-un program; repetați un anumit fragment de un anumit număr de ori; compilați fragmentul în funcție de condiție; setați adresa de execuție a unui fragment, modificați valorile etichetelor în timpul procesului de compilare; utilizați definiții macro cu parametri etc.

Fiecare model de procesor, în principiu, are propriul set de instrucțiuni și un limbaj de asamblare (sau dialect) corespunzător.

Avantaje și dezavantaje

  • cantitate minimă de cod redundant (folosirea mai puține instrucțiuni și accesări la memorie). Ca urmare, viteza mare și dimensiune mai mică programe
  • cantități mari de cod, număr mare sarcini suplimentare mici
  • lizibilitate slabă a codului, greu de suportat (depanare, adăugare de caracteristici)
  • dificultatea implementării paradigmelor de programare și orice alte convenții oarecum complexe, dificultatea dezvoltării în comun
  • mai puține biblioteci disponibile, compatibilitatea lor scăzută
  • acces direct la hardware: porturi I/O, registre speciale de procesor
  • capacitatea de a scrie cod cu auto-modificare (adică metaprogramare, fără a fi nevoie de un interpret software)
  • „potrivire” maximă pentru platforma dorită(utilizarea instrucțiunilor speciale, caracteristicile tehnice ale hardware-ului)
  • neportabilitatea către alte platforme (cu excepția celor compatibile cu binar).

Sintaxă

Nu există un standard general acceptat pentru sintaxa limbajelor de asamblare. Cu toate acestea, există standarde de facto - abordări tradiționale la care aderă majoritatea dezvoltatorilor de limbaje de asamblare. Principalele astfel de standarde sunt sintaxa Intel și sintaxa AT&T.

Formatul general pentru instrucțiunile de înregistrare este același pentru ambele standarde:

`[eticheta:] opcode [operanzi] [;comentar]`

Un opcode este un mnemonic direct al instrucțiunilor către procesor. Pot fi adăugate prefixe (repetări, modificări ale tipului de adresare etc.). Operanzii pot fi constante, nume de registre, adrese din RAM etc. Diferențele dintre standardele Intel și AT&T se referă în principal la ordinea în care operanzii sunt listați și la sintaxa lor atunci când diverse metode adresarea.

Mnemoteciile utilizate sunt de obicei aceleași pentru toate procesoarele din aceeași arhitectură sau familie de arhitecturi (printre cele mai cunoscute sunt mnemonice pentru procesoare și controlere Motorola, ARM, x86). Acestea sunt descrise în specificațiile procesorului.

De exemplu, procesorul Zilog Z80 a moștenit sistemul de instrucțiuni Intel i8080, l-a extins și a schimbat mnemonicii (și desemnările registrului) în felul său. De exemplu, am schimbat mov-ul Intel în ld. Procesoarele Motorola Fireball au moștenit sistemul de instrucțiuni Z80, reducându-l oarecum. În același timp, Motorola a revenit oficial la mnemonicii Intel. iar în momentul de față, jumătate dintre asamblatorii pentru Fireball lucrează cu mnemonice Intel și jumătate cu mnemonice Zilog.

Directive

Pe lângă instrucțiuni, un program poate conține directive: comenzi care nu sunt traduse direct în instrucțiuni de mașină, dar controlează funcționarea compilatorului. Setul și sintaxa lor variază semnificativ și depind nu de platforma hardware, ci de compilatorul utilizat (generând dialecte ale limbilor în cadrul aceleiași familii de arhitecturi). Setul de directive include:

  • definirea datelor (constante și variabile)
  • controlul organizării programului în memorie și parametrii fișierului de ieșire
  • setarea modului de operare al compilatorului
  • tot felul de abstracții (adică elemente de limbaje de nivel înalt) - de la proiectarea procedurilor și funcțiilor (pentru a simplifica implementarea paradigmei programare procedurală) la condiționale și bucle (pentru paradigma de programare structurată)
  • macro-uri

Originile și critica termenului „limbaj de asamblare”

Acest tip de limbaj își trage numele de la numele traducătorului (compilatorului) din aceste limbi - assembler (asamblator englez). Numele acestuia din urmă se datorează faptului că pe primele computere nu existau limbaje de nivel superior, iar singura alternativă la crearea de programe folosind assembler era programarea direct în coduri.

Limba de asamblare în rusă este adesea numită „asamblator” (și ceva legat de acesta - „asamblator”), care, potrivit traducere in engleza cuvintele sunt incorecte, dar se încadrează în regulile limbii ruse. Cu toate acestea, asamblatorul însuși (programul) este numit și simplu „asamblator” și nu „compilator limbaj de asamblare”, etc.

Utilizarea termenului „limbaj de asamblare” poate duce, de asemenea, la concepția greșită că există un singur limbaj de nivel scăzut, sau cel puțin un standard pentru astfel de limbi. Când denumim limba în care este scris un anumit program, este recomandabil să specificați pentru ce arhitectură este destinat și ce dialect al limbii este scris.

Elemente de sintaxă:

Exemple:

Salut Lume!:

Exemplu pentru versiunile Intel x86 (IA32).

mov ax , cs mov ds , axe mov ah , 9 mov dx , offset Hello int 21h xor ax , ax int 21h Hello : db "Hello World!", 13, 10, "$"

Salut Lume!:

Exemplu pentru versiunile Amiga

mișcare. l #DOS muta . l 4. w , a6 jsr - $0198(a6) ; Mutare OldOpenLibrary . l d0 , a6 beq . s. Mișcă afară. l #HelloWorld , d1 A ) moveq #13, d2 jsr - $03AE (a6 ) ; WriteChars B ) jsr - $03B4 ; PutStr muta . l a6, a1 mutare. l 4. w , a6 jsr - $019E (a6 ) ; Închideți Biblioteca. Out rts DOS dc. b "dos.library" , 0 HelloWorld dc . b „Bună lume!” , $A , 0

Salut Lume!:

Exemplu pentru versiunile AtariST

mișcare. l #helloworld , - (A7 ) mutare #9, - (A7 ) capcană #1 addq . l #6, A7 mutare #0, - (A7) capcană #1 helloworld : dc . b „Bună lume!”, $0d, $0a, 0

Salut Lume!:

Exemplu pentru versiunile Intel x86 (IA32).

NASM Linux, folosește sintaxa Intel. Compilarea și legarea:

  • nasm –f elf –o hello.o hello.asm
  • ld -o buna buna ziua.o

SECȚIUNE. data msg db „Bună ziua, lume!”, 0xa len equ $ - msg SECTION . text global _start _start : ; Punct de intrare program mov eax, 4; apel de sistem „scriere” mov ebx, 1 mov ecx, msg; Pointer la date mov edx, len; Număr de date int 0x80 ; Kernel call mov eax, 1; Apel de sistem „_exit” mov ebx , 0 ; Returnează 0 (totul este bine) int 0x80 ; Apelarea nucleului

Salut Lume!:

Exemplu pentru versiunile PDP-8

/ - comentarii.

/Hello World în assembler pentru DEC PDP - 8 * 200 hello , cla cll tls /tls setează steagul de imprimare. tad charac / creează un registru de index dca ir1 / pentru a primi caractere tad m6 / setează contor pentru dca count / introducere de caractere. în continuare, tad i ir1 / get symbol. jms tip / tipul său. isz count / face altceva? jmp următor / nu, introduceți un alt tip de caracter hlt , 0 / tip de subrutină tsf jmp . - 1 tls cla jmp i tip charac , . / folosite ca valoarea initiala ir1. 310 / H 305 / E 314 / L 314 / L 317 / O 254 / , 240 / 327 / L 317 / O 322 / R 314 / L 304 / D 241 / ! m6 , - 15 count , 0 ir1 = 10 $

Salut Lume!:

Exemplu pentru versiunile PDP-11

Programul este scris în macro-asamblatorul MACRO-11 Pentru a compila și rula acest program în sistemul de operare RT-11, comandăm:

MACRO SALUT

ERORI DETECTE: 0

LINK SALUT -- Link. RUN HELLO -- Lansați

TITLUL HELLO WORLD ; Nume . MCALL. TTYOUT,. EXIT HELLO :: MOV #MSG , R1 ; Adresa de pornire a liniei 1$: MOVB (R1) + , R0 ; Obținem următorul simbol BEQ DONE; Dacă este zero, ieșim din buclă. TTYOUT; Altfel tipărim simbolul BR 1$ ; Repetați ciclul TERMINAT: . EXIT MSG: . ASCIZ /Bună, lume!/; Linia Bună, lume! . FINALĂ SALUT ; Sfârșitul programului HELLO

Salut Lume!:

Exemplu pentru versiunile System/360, System/370

IBM System/360/370/390 Basic Assembler Language.

// EXEC ASSEMBLY START MAIN BALR 2, 0 FOLOSIND *, 2 OPEN PRINT MVC BUF, HW PUT PRINT CLOSE PRINT EOJ HW DC CL132 "HELLO WORLD" BUF DS CL132 PRINT DTFPR IOAREA1 = BUF, DEVADDR = BLKSISLST *, =132 DEVICE = 3203 , CONTROL = YES , PRINTOV = YES END MAIN /* // EXEC LNKEDT // EXEC /* /&

Salut Lume!:

Exemplu pentru versiunile Apple II

* HELLO WORLD PENTRU 6502 APPLE ][ * ******************************** STROUT EQU $DB3A LDY #> HELLO LDA #< HELLO JMP STROUT HELLO ASC "HELLO WORLD !", 00

Salut Lume!:

Exemplu pentru versiunile PDP-10

CHTTYO - Toate I/O se fac folosind canale I/O. Cel mai bine este să creați nume simbolice pentru canalele pe care le utilizați și să le începeți cu CH. Definiți aceste nume folosind operatorul MIDAS == .

CALL este o notație simbolică pentru apelarea unui apel de sistem. Formatul său este .CALL.

OPEN deschide un canal I/O pentru utilizare. Necesită doi parametri - numărul canalului și numele dispozitivului în SIXBIT.

LOSE %LSFIL este un apel de sistem care tipărește un mesaj de eroare I/O dacă apare brusc.

IOT este un apel de sistem care se ocupă de fapt de I/O. Ca parametru, trebuie să specificați canalul și adresa care conțin codul simbol pentru ieșire. De exemplu, „H reprezintă H.

TITLUL PRINTHELLO A = 1 CHTTYO == 1 ; Canal de ieșire. START: ; Deschiderea unui canal TTY. . Apelați [ SETZ ? SIXBIT/OPEN/[. UAO, CHTTYO]? [SIXBIT/TTY/] ((SETZ))] . PIERDE %LSFIL . IOT CHTTYO ,[ "H ] ; Tipăriți HELLO WORLD caracter cu caracter. . IOT CHTTYO ,[ "E ] . IOT CHTTYO ,[ "L ] . IOT CHTTYO ,[ "L ] . IOT CHTTYO ,[ "O ]. IOT CHTTYO ,[ ^M ] ; Simbol linie nouă. IOT CHTTYO ,[ "W ]. IOT CHTTYO ,[ "O ] . IOT CHTTYO ,[ "R ]. IOT CHTTYO ,[ "L ] . IOT CHTTYO ,[ "D ] . VALUE ; Program, stop :) END START

numerele Fibonacci:

Exemplu pentru versiunile MIPS32

Emulator MARS. Ieșirea consolei MARS:

Numerele Fibonacci sunt: ​​1 1 2 3 5 8 13 21 34 55 89 144 -- programul s-a terminat --

Programul afișează 15 numere Fibonacci. Numărul de numere poate fi modificat în secțiunea .data.

Spațiu de date: .asciiz " " head: .asciiz „Numerele Fibonacci sunt:\n” fib: .word 0 : 15 size : .word 15 .text main: la $t0 , fib la $t5 , size lw $t5 , 0 ($t5 ) li $t2 , 1 add.d $f0 , $f2 , $ f4 sw $t2 , 0 ($t0 ) sw $t2 , 4 ($t0 ) adi $t1 , $t5 , - 2 buclă : lw $t3 , 0 ($t0 ) lw $t4 , 4 ($t0 ) adăuga $ t2 , $t3 , $t4 sw $t2 , 8 ($t0 ) addi $t0 , $t0 , 4 addi $t1 , $t1 , - 1 bgtz $t1 , bucla la $a0 , fib muta $a1 , $t5 jal print li $v0 , 10 syscall print : add $t0 , $zero , $a0 add $t1 , $zero , $a1 la $a0 , head li $v0 , 4 syscall out : lw $a0 , 0 ($t0 ) li $v0 , 1 syscall la $a0 , space li $v0 , 4 syscall addi li $v0 , 1 la $a0 , ($t2 ) syscall la $a0 , string1 li $v0 , 4 syscall mult $t1 , $t2 mflo $ t1 li $v0 , 1 la $a0 , ($t1 ) syscall la $a0 , string2 li $v0 , 4 syscall addiu $t2 , $t2 , 1 beq $t2 , 16 , endloop j loop endloop: li $v0 , 10 syscall



Instituția bugetară de stat și de învățământ

Articol: Informatica

Eseu

Subiect: Istoria limbajelor de programare.

Asamblator.

Efectuat: elev în clasa a VIII-a,

gimnaziu nr 1467

Sorokin Nikolay

Supraveghetor: Tsvetkova Oksana Mihailovna

Introducere

Odată cu creșterea volumului de calcule, a apărut primul instrument de calcul portabil - „Abacus”.

La începutul secolului al XVII-lea era nevoie de calcule complexe. erau necesare dispozitive de calcul care să poată efectua un volum mare de calcule cu precizie ridicată. În 1642, matematicianul francez Pascal a proiectat prima mașină de calcul mecanică, Pascalina.

În 1830, omul de știință englez Babage a propus ideea primului programabil calculator(„Motor analitic”). Trebuia să fie alimentat cu abur, iar programele erau codificate pe carduri perforate. Nu a fost posibilă implementarea acestei idei, deoarece nu a fost posibilă realizarea unor părți ale mașinii.

Primul a implementat ideea cărților perforate Hollerith. El a inventat o mașină pentru procesarea rezultatelor recensământului. În mașina sa, el a fost primul care a folosit electricitatea pentru calcule. În 1930, omul de știință american Bush a inventat analizorul diferențial - primul computer din lume.

Al Doilea Război Mondial a dat un mare impuls dezvoltării tehnologiei informatice. Armata avea nevoie de un computer, care a devenit Mark-1 - primul din lume calculator digital, inventat în 1944 de profesorul Aiknam. A folosit o combinație de semnale electrice și acționări mecanice. Dimensiuni: 15 X 2,5 m, 750.000 piese. Ea ar putea înmulți două numere de 23 de biți în 4 secunde.

În 1946, un grup de ingineri comandați de departamentul militar american a creat primul calculator electronic- „Eniak”. Performanță: 5000 de operații de adunare și 300 de operații de înmulțire pe secundă. Dimensiuni: 30 m lungime, volum – 85 m3, greutate – 30 tone. s-au folosit 18.000 el. lămpile

Prima mașină cu un program cronic - "Edsak" - a fost creată în 1949, iar în 1951 au creat mașina "

Univac” este primul computer serial cu un program cronic. Acest aparat a fost primul care a folosit bandă magnetică pentru înregistrarea și stocarea informațiilor.

Pentru ce este un limbaj de programare?

Calculatoarele au apărut în lumea noastră cu mult timp în urmă, dar abia recent au început să fie folosite atât de intens în multe domenii ale vieții umane. În urmă cu zece ani, era rar să vezi orice computer personal - ele existau, dar erau foarte scumpe și nici măcar fiecare companie nu putea avea un computer în biroul lor. Si acum? Acum, fiecare a treia casă are un computer, care a intrat deja adânc în viața locuitorilor casei înșiși.

Însăși ideea de a crea inteligență artificială a apărut cu mult timp în urmă, dar abia în secolul al XX-lea a început să fie pusă în practică. A apărut primul calculatoare uriașe, care erau adesea de mărimea unei case uriașe. Utilizarea unor astfel de mașini, după cum înțelegeți voi înșivă, nu a fost foarte convenabilă. Dar ce poți face? Dar lumea nu a stat la un loc de dezvoltare evolutivă - oamenii s-au schimbat, habitatul lor s-a schimbat și, odată cu aceasta, tehnologiile în sine s-au schimbat, devenind din ce în ce mai îmbunătățite. Iar computerele au devenit din ce în ce mai mici până când au ajuns la dimensiunea pe care o au astăzi.

Dar o persoană trebuie să comunice cumva cu mașina - la urma urmei, cine are nevoie de o mașină incontrolabilă? La început, oamenii comunicau cu computerele folosind carduri perforate. Cărțile perforate sunt cărți mici cu rânduri de numere imprimate pe ele. Computerul avea o „unitate de disc” în care erau introduse cardurile în sine și cu ajutorul unor ace mici făcea găuri pe numere. Puțini oameni s-au bucurat de o astfel de comunicare - la urma urmei, nu este foarte convenabil să transportați grămezi de cărți perforate, care trebuiau aruncate după o singură utilizare.

Dar, ca și alte tehnologii, procesul de comunicare umană cu inteligenţă artificială a suferit unele modificări. Acum o persoană își conduce conversația cu un computer folosind o tastatură și un mouse. Acest lucru este destul de convenabil și uneori chiar aduce plăcere persoanei.

Calculatoarele moderne reprezintă una dintre cele mai semnificative realizări ale gândirii umane, a cărei influență asupra dezvoltării progresului științific și tehnologic poate fi cu greu supraestimată. Domeniile de aplicare ale computerelor sunt în continuă expansiune. Aceasta în într-o mare măsură promovează răspândirea computerelor personale, și în special a microcalculatoarelor.

De-a lungul anilor 50, computerul digital a evoluat dintr-o grămadă „magică”, dar în același timp scumpă, unică și supraîncălzită. tuburi vid, fire și miezuri magnetice într-o mașină mică - un computer personal - constând din milioane de dispozitive semiconductoare minuscule care sunt ambalate în cutii mici de plastic.

Ca urmare a acestei transformări, calculatoarele au început să fie folosite peste tot. Ei gestionează munca case de marcat, monitorizează funcționarea sistemelor de aprindere a mașinilor, ține evidența bugetului familiei sau pur și simplu sunt folosite ca complex de divertisment... Dar aceasta este doar o mică parte din capacitățile computerelor moderne. Mai mult, progresul rapid al microelectronicii semiconductoare, care reprezintă baza tehnologiei computerelor, indică faptul că nivelul actual atât al computerelor în sine, cât și al zonelor de aplicare a acestora este doar o aparență slabă a ceea ce va urma în viitor.

Calculatoarele încep să atingă viețile fiecărei persoane. Dacă te îmbolnăvești și dacă ești trimis la un spital, atunci odată ce ajungi acolo, te vei afla într-o lume în care viața oamenilor depinde de computere (în unele spitale moderne vei întâlni chiar mai multe computere decât pacienții înșiși și acest raport va crește în timp, depășind numărul de pacienți). Studiind treptat echipamente informatice Ei încearcă să o introducă în programa școlară ca materie obligatorie, astfel încât copiii să cunoască structura și capacitățile computerelor de la o vârstă destul de fragedă. Și în școlile în sine (în special în Occident și în America), computerele au fost folosite de mulți ani pentru a menține documentația educațională, iar acum sunt folosite în studiul multor discipline academice care nu au legătură directă cu tehnologia informatică. Chiar și în școală primară computerele sunt introduse pentru a preda cursuri de matematică și fizică elementară. Microprocesoarele în sine nu sunt mai puțin răspândite decât computerele - sunt încorporate în sobe de bucătărie, mașini de spălat vase și chiar ceasuri.

Jocurile construite pe microprocesoare au devenit foarte răspândite. Astăzi, industria jocurilor de noroc ocupă o parte foarte mare a pieței, înlocuind treptat alte tipuri de divertisment pentru copii. Dar este foarte dăunător pentru corpul unui copil să stea ore în șir la un monitor și să apese cu disperare taste, deoarece copilul poate dezvolta un fel de boală - atunci când are un singur lucru în minte - computerul și nimic altceva. Copiii cu această boală devin de obicei agresivi dacă accesul lor la jocuri este limitat. Astfel de copii își pierd imediat orice dorință de a face ceva care nu are legătură cu computerul și care nu este interesant pentru ei - așa că încep să-și abandoneze studiile, ceea ce duce la consecințe nu foarte bune.

Deja acum computerele pot pronunța clar diverse fraze, fraze, pot reda muzică etc. O persoană poate scrie acum câteva cuvinte, propoziții și chiar compoziții muzicale pe computerul său, astfel încât computerul să le poată reda apoi la orice moment stabilit.

De asemenea, computerele pot interpreta limbajul vorbit ca semnale, dar trebuie să performeze buna treaba prin descifrarea a ceea ce s-a auzit, dacă forma de comunicare nu este strict stabilită. La urma urmei, aceeași persoană poate pronunța aceeași comandă în mai multe moduri și tot timpul această comandă va suna diferit; și în întreaga lume sunt miliarde de oameni și toată lumea pronunță aceeași poruncă de mai multe ori căi diferite. Prin urmare, în timp dat Este destul de dificil să creezi un computer care să fie controlat folosind o voce umană. Multe companii încearcă să rezolve aceste probleme. Unele companii fac pași mici către acest obiectiv, dar totuși acești pași sunt încă aproape imperceptibili.

Dar problema recunoașterii vorbirii face parte dintr-o problemă mai mare numită recunoaștere a modelelor. Dacă computerele pot recunoaște bine modelele, vor putea analiza razele X și amprentele digitale, precum și multe alte sarcini. caracteristici utile(Deja sortează scrisorile acum). Trebuie remarcat faptul că creierul uman se descurcă bine cu recunoașterea modelelor chiar și în prezența diferitelor zgomote și distorsiuni, iar cercetările în acest domeniu, menite să apropie capacitățile computerului corespunzătoare de abilitățile umane, pare foarte promițătoare. Dacă computerele pot recunoaște suficient de bine vorbirea și pot răspunde la aceasta forma verbala, atunci se pare că va fi posibil să introduceți programe și date în ele în acest formular. Acest lucru vă va permite să spuneți literalmente computerului ce ar trebui să facă și să ascultați părerea acestuia cu privire la această chestiune, cu condiția, desigur, ca instrucțiunile care îi sunt date să fie clare, să nu conțină contradicții etc.

Comunicarea orală cu computerele va facilita programarea acestuia, dar problema nerezolvată rămâne în ce limbă să comunici cu el. Mulți oferă limba engleză în aceste scopuri, dar nu are acuratețea și neambiguitatea necesare din punctul de vedere al unui computer și al programelor executate în acesta. S-au făcut deja multe în acest domeniu, dar mai rămân multe de făcut.

Ne plângem adesea că alți oameni nu ne înțeleg; dar până acum, computerele personale în sine nu sunt capabile să ne înțeleagă pe deplin sau să înțeleagă ceea ce vrem să spunem dintr-o privire. Și pentru o perioadă de timp va trebui să ne mulțumim cu mașini care pur și simplu urmează instrucțiunile noastre, executându-le „cu precizie milimetrică”.

Pentru a comunica cu computerele, pe vremea cărților perforate, programatorii din acea vreme foloseau un limbaj de programare foarte asemănător cu Asamblarea modernă. Acesta este un limbaj în care toate comenzile primite de computer sunt scrise în detaliu folosind cuvinte și pictograme speciale (?).

În zilele noastre, sunt din ce în ce mai folosite limbaje de programare de nivel superior, cu care este mult mai ușor de lucrat decât cu Assembly, deoarece în ele un cuvânt poate înlocui mai multe comenzi deodată. Și, în plus, majoritatea limbajelor de programare de nivel înalt în numele comenzilor utilizate atunci când comunicați cu un computer folosesc echivalentele numite în Limba engleză, ceea ce în mod natural ușurează programarea. Dar au un dezavantaj în comparație cu limbaje precum Assembly - în Assembly, toate comenzile care provin din program sunt distribuite clar în memoria computerului, ocupând locuri libere, câștigând astfel semnificativ în viteză; și limbajele de nivel înalt nu știu cum să facă acest lucru și, în consecință, pierd viteza de execuție a programului. Și în lumea noastră de astăzi, toată lumea știe că: „Timpul este bani”.

Deși, deocamdată, un computer este inferior unei persoane în ceea ce privește activitatea creativă, deoarece mașina nu este încă înzestrată cu astfel de calități care l-ar putea ajuta să creeze ceva nou care nu a fost introdus în memoria sa de către persoana însăși.

Majoritatea oamenilor par să considere termenii „calculator” și „hardware de computer” ca fiind sinonimi și îi asociază cu hardware-ul fizic, cum ar fi un microprocesor, afișaj, discuri, imprimante și alte dispozitive care atrag atenția oamenilor atunci când o persoană vede computerul. Deși aceste dispozitive sunt importante, ele sunt doar vârful aisbergului. În stadiul inițial de utilizare calculator modern nu avem de-a face cu computerul in sine, ci cu un set de reguli, numite limbaje de programare, in care sunt specificate actiunile pe care trebuie sa le realizeze calculatorul. Importanța unui limbaj de programare este subliniată de faptul că computerul însuși poate fi considerat ca un interpret hardware al unui anumit limbaj, care se numește limbaj mașină. A furniza munca eficienta Mașinile au dezvoltat limbaje de mașină, a căror utilizare prezintă anumite dificultăți pentru oameni. Majoritatea utilizatorilor nu se confruntă cu aceste inconveniente din cauza prezenței uneia sau mai multor limbi concepute pentru a îmbunătăți comunicarea om-mașină. Flexibilitatea unui computer se manifestă prin faptul că poate executa programe de traducere (numite în general compilatoare sau interpreți) pentru a converti programe din limbaje orientate către utilizator în programe în limbaj mașină. (La rândul lor, chiar și programele, jocurile, shell-urile de sistem în sine nu sunt altceva decât un program de traducere destul de simplu, care, pe măsură ce funcționează sau joacă, își folosește comenzile pentru a accesa „în interiorul și în exteriorul computerului”, traducând comenzile sale în limbaje de mașină. Și toate acestea se întâmplă în timp real.)

Limbaje mașină, limbaje de asamblare și

limbi de nivel înalt

Programatorii scriu programe într-o varietate de limbaje de programare, dintre care unele sunt direct înțelese de computer, în timp ce altele necesită un pas intermediar de traducere. Sutele de limbi disponibile pot fi clasificate în trei tipuri generale:

1. Limbaje mașini

2. Limbaje de asamblare

3. Limbi de nivel înalt.

Fiecare computer poate înțelege doar propriul limbaj de mașină, care este limbajul natural al unui anumit computer. Este strâns legat de hardware-ul său. Limbajele mașinii constau în general din secvențe de numere (de obicei zerouri și unu) care sunt instrucțiuni pentru a efectua operații elementare individuale. Limbajele mașinii sunt dependente de mașină, de exemplu. un anumit limbaj de mașină poate fi utilizat numai cu un anumit tip de computer. Limbajul mașină este incomod pentru înțelegerea umană.

Pe măsură ce computerele au devenit mai răspândite, a devenit evident că programarea în limbaje mașini împiedică dezvoltarea tehnologiei computerelor, este foarte lentă și este prea mult pentru majoritatea programatorilor. În loc de o secvență de numere direct înțeles de computer, programatorii au început să folosească abrevieri în engleză pentru a reprezenta operațiuni elementare, care au stat la baza limbajelor de asamblare. Pentru a converti programele scrise în astfel de limbi în limbaj mașină, programele de traducere au numit asamblatori. Conversia a avut loc la o viteză egală cu viteza computerului. Odată cu apariția limbajelor de asamblare, utilizarea computerelor a crescut semnificativ, dar scrierea era încă necesară cantitate mare instructiuni chiar si pentru implementarea solutiilor la cele mai simple probleme. Pentru a accelera procesul de programare, au fost dezvoltate limbaje de nivel înalt în care să performeze actiuni complexe este suficient să scrii o singură afirmație. Programele pentru conversia unei secvențe de instrucțiuni într-un limbaj de nivel înalt în limbaj mașină sunt numite compilatoare. În limbile de nivel înalt, instrucțiunile scrise de programatori arată adesea ca un text simplu în limba engleză, folosind simboluri matematice comune.

Unul dintre limbajele de nivel înalt este limbajul de programare C.

Istoria limbajului C

Limbajul c își are originile în două limbi, BCPL și B. În 1967, Martin Richards a dezvoltat BCPL ca limbaj pentru scrierea de software și compilatoare de sisteme. În 1970, Ken Thompson a folosit B pentru a crea versiuni timpurii ale sistemului de operare UNIX pe computerul DEC PDP-7. atât în ​​BCPL, cât și în B, variabilele nu au fost împărțite în tipuri - fiecare valoare de date ocupa un cuvânt în memorie și responsabilitatea de a distinge, de exemplu, între numere întregi și numere reale a căzut în întregime pe umerii programatorului.

Limbajul C a fost dezvoltat (pe baza B) de Dennis Ritchie de la Bell Laboratories și a fost implementat pentru prima dată în 1972 pe computerul DEC PDP-11. C a câștigat faima ca limbaj al sistemului de operare UNIX. Astăzi, aproape toate sistemele de operare majore au fost scrise în C și/sau C++. Două decenii mai târziu, C este disponibil pe majoritatea computerelor. Este independent de hardware.

La sfârșitul anilor 70, C a evoluat în ceea ce numim „C tradițional”. În 1983, Comitetul național american pentru standarde de procesare a computerelor și a informațiilor a stabilit un standard unificat pentru această limbă.

Concluzie

Bazat a acestui rezumat putem concluziona că viața noastră este complet pătrunsă tehnologii informatice. Nu va trece mult până când computerele vor fi instalate peste tot unde este nevoie de prezența umană. Dar fără cunoștințe certe, comunicarea cu un computer va fi imposibilă. Și pentru a-l face să funcționeze pentru tine, trebuie să-i cunoști limbajul - un limbaj de programare.

Lista literaturii folosite

1. Tom Swan „Mastering Turbo Assembler”, Dialectika, Kiev, 1996

2. Berezin B.I., Berezin S.B. „Curs de programare pentru începători”, Dialogue MEPhI, Moscova, 1996

3. Prelegeri de Nina Viktorovna Komleva pe tema „Limbaje de programare și metode de traducere”

4. H.M. Deitel, How to program in C, Editura Binom, Moscova, 2000.

Asamblator (asm, asamblator); din engleza asamblare - asamblare, montare) - un limbaj de programare de nivel scăzut, un program auxiliar ca parte a sistemului de operare pentru traducere automată programul sursă să fie executat pe un computer în limbaj mașină; tip de traducător. Conceptele limbajului de asamblare reflectă arhitectura unui computer electronic. Asamblarea este o formă simbolică de înregistrare a limbajului mașină, a cărei utilizare simplifică scrierea programelor de mașină. Pentru același computer pot fi dezvoltate diferite limbaje de asamblare. Spre deosebire de limbajele de nivel înalt, în care problemele de implementare a algoritmilor sunt ascunse dezvoltatorilor, limbajul de asamblare este strâns legat de sistemul de instrucțiuni al computerului. Asamblatorul oferă acces la registre, specificarea metodelor de adresare și descrierea operațiunilor în termeni de instrucțiuni ale procesorului. Poate conține instrumente de nivel superior: macrocomenzi încorporate și definite corespunzătoare mai multor instrucțiuni ale mașinii, selectare automată a comenzilor în funcție de tipurile de operanzi și instrumente pentru descrierea structurilor de date.

Caracteristici ale asamblatorului

Un asamblator este, de asemenea, un compilator care convertește limbajul de asamblare în instrucțiuni de limbaj mașină. Un alt nume pentru un astfel de compilator este codul mnemonic. Acesta este conceput pentru a reprezenta codurile de comandă a mașinii într-o formă convenabilă (mnemonică), prevede utilizare eficientă resurse de sistem (procesor, memorie, periferice). Codul mnemonic este folosit în locurile în care este necesară performanța și dimensiunea RAM este limitată. Limbajul de asamblare este uneori numit și sistemul de instrucțiuni al procesorului central.

Fiecare arhitectură de procesor și fiecare sistem de operare are propriul său asamblator. Asamblerile încrucișate vă permit să asamblați programe pentru altă arhitectură sau alt sistem de operare pe mașini cu o singură arhitectură. Asamblatorul oferă acces la registre, specificarea metodelor de adresare și descrierea operațiunilor în termeni de instrucțiuni ale procesorului. Un asamblator poate conține instrumente de nivel înalt: macro instrucțiuni încorporate și definite corespunzătoare mai multor instrucțiuni de mașină, selectare automată a comenzilor în funcție de tipurile de operanzi și instrumente pentru descrierea structurilor de date.

Comenzile din limbajul de asamblare corespund comenzilor procesorului și reprezintă o formă simbolică de scriere a comenzilor și argumentelor. Limbajul de asamblare asigură legarea părților de program și a datelor prin etichete, care se realizează în timpul asamblarii (se calculează o adresă pentru fiecare etichetă, după care fiecare apariție a etichetei este înlocuită cu această adresă). Deoarece sistemele de instrucțiuni ale microprocesoarelor diferă, fiecare procesor are propriul set de instrucțiuni în limbaj de asamblare și propriile compilatoare de asamblare.

De obicei, programele sau secțiunile de cod sunt scrise în limbaj de asamblare în cazurile în care dezvoltatorul trebuie să optimizeze performanța (la crearea driverelor) și dimensiunea codului. Majoritatea compilatoarelor vă permit să combinați codul scris în diferite limbaje de programare într-un singur program. Acest lucru vă permite să scrieți programe complexe folosind un limbaj de nivel înalt, fără a pierde performanța în sarcinile critice de timp, folosind piese scrise în limbaj de asamblare pentru acestea. Combinarea se realizează prin inserarea de fragmente în limbaj de asamblare în textul programului (directive speciale de limbă) sau scrierea procedurilor în limbaj de asamblare. Această metodă este utilizată pentru transformări simple de date, dar nu este aplicabilă în codul de asamblare complet cu date și rutine cu multe intrări și ieșiri care nu sunt acceptate de limbaje de nivel înalt.

În acest caz, se utilizează compilarea modulară, atunci când fiecare fișier de program este compilat într-un modul obiect, care sunt apoi legate în program gata făcut. Fișierele obiect sunt blocuri de cod de mașină și date, cu adrese de referință nedefinite la date și proceduri din alte module obiect, precum și o listă a procedurilor și datelor acestora. Linker-ul colectează codul și datele fiecărui modul obiect în program, calculează și completează adresele de referință încrucișată între module. În timpul procesului de conectare, programul este legat de biblioteci statice și dinamice (care sunt arhive de fișiere obiect Cu compilare modulară, fiecare modul obiect al programului poate fi scris în propriul limbaj de programare și compilat cu propriul compilator (asamblator). .