Primii pași în programare de nivel scăzut

Primii pași în programare de nivel scăzut

Procedura Mighty Move

Mutare - procedura standard curios, am moștenit mai mult de la bun vechi Turbo Pascal'ya. Este probabil o greșeală a intrat în limbajul de programare de nivel înalt, dar capacitatea și viața simplificată a adăugat destul de (și ne bucurăm doar că). Se pare a fi nimic special: Procedura de mutare (Sursa Const; var dest; Count: Integer); Se mută de la sursa la dest bucată de octeți egal COUNT. Și, după cum ați observat (dacă ați observat), Sursa / dest - nu există indicii, și variabile în mod direct, și ca punct de pornire este de mutare primul octet ocupat de variabila. Uită-te la exemple: var
b. array [0..80] de octet;
c. array [4..67] de char;
w. array [8..670] cuvântului;
Procedura SomeProc;
începe
MessageBox (0, 'Bună ziua!', Nil, 0);
se încheie;
începe
mutare (b, c [4], 20); // copie 20 octeți de la începutul șirului b în matrice, începând cu locul 4.
muta (b, w, sizeof (b)); // exemplare întreaga matrice B de la începutul șirului w (notați dimensiunile de tip nepotrivire!)
muta (w [4], w [50], sizeof (cuvânt) * 100); // „împinge“ valorile 100 până la a patra de pe poziția a 50-lea într-o singură matrice (notă - sursă și dest zone de memorie se suprapun!)
mutare (SomeProc, b, sizeof (b)); // copie SomeProc cod procedură pentru matrice b
.

Teoretic, un octet este copiat bucăți de memorie, indiferent de tipul și dimensiunea datelor. De asemenea, este remarcabil faptul că procedura funcționează corect atunci când datele la noua locație „rănit“, originalul. În exemple, definim dimensiunea matrice prin utilizarea funcției sizeof. Se întoarce dimensiunea, în octeți sau structuri de date, sau tipul de date. Rețineți că nu oferă nici un control la depășirea limitelor variabilelor în punerea în aplicare a Move, care este motivul pentru care mai prudenta in utilizarea sa, precum și pentru toate tipurile de trucuri de nivel scăzut. Un al patrulea exemplu de doar unul dintre ele. El are pentru noi astăzi este cheia, așa.

al patrulea exemplu

În mod logic, încărcat în memorie și programul de lucru este format din cod - instrucțiunile pentru procesorul ( „verbe“), și datele pe care aceste instrucțiuni sunt prelucrate ( „substantive“). Sunt stocate în memoria calculatorului și a celor de alt într-un fel - ca o secvență de octeți. Și astfel codul poate fi uneori considerate ca probe. Dacă aș fi fost un profesor, aș spune că viața se desfășoară „principiul von Neumann“, într-un astfel de caz. În diverse programe specifice (compilatoare, pachetele de rutină de fișiere executabile, toate tipurile de protecție, etc.) nu se poate face fără ea. Astfel de metode sunt considerate limbi de nivel scăzut prerogative valabile (în primul rând, ansamblul), dar cu Delphi și poate efectua unele experimente interesante de acest gen.

Acum, mai aproape de exemplul nostru. Array b este plin procedurile de reprezentare SomeProc în memoria calculatorului. Mai mult decât atât, nu știm câți bytes ocupă - cel mai probabil, pe baza miniatura sale, la sfârșitul matrice va fi gunoi - o bucată de o altă procedură sau de date. Dar, în cazul în care procedura este mai mult, nu s-ar încadra în intervalul de timp alocat 80 de octeți. După cum se poate vedea: incertitudine continuă, dar vom încerca să facă lumină asupra situației. Primul lucru care vine în minte - pentru a vedea ce este în continuare înscris în gama noastră. Este destul de rezonabil! Probabil că ai deja scris ceva de genul pentru i: = Low (b) la ridicat (b) fac
Memo1.Lines.Add (IntToStr (i) + '-' + IntToStr (b [i]));. Ochii neintelegatoare si uita-te la numerele coloanei.

Cei care nu au scrie cât mai repede posibil, formați, și nu pierdeți posibilitatea unor limitări. Pascal vă permite să setați orice limite matrice indexate (care este un semn de limbaj „de nivel înalt“ - de exemplu, în C, toate matricele sunt indexate de la zero). În Delphi mers mai departe și a introdus funcții joase și înalte, care definesc indicii superioare și inferioare ale șirului respectiv. Este foarte bine, așa că vă recomand pe tot parcursul programelor dvs. de a le utiliza, a scăpa de constanta neimportante.

Astfel, o coloană de numere. Nimic, cum ar fi, interesant. Dar eu propun să se deducă nu numai cod, ci, de asemenea, o reprezentare simbolică a octetului. Ca rezultat, vom scrie următoarele: pentru i: = Low (b) la ridicat (b) fac
Memo1.Lines.Add (IntToStr (i) + '-' + IntToHex (b [i], 2) + '' chr + (b [i])); Vă rugăm să rețineți - acum utilizat în locul funcției IntToHex IntToStr. Este nevoie de un număr la reprezentarea sa șir în hexazecimal. Primul argument furnizat la numărul mare, al doilea - avem nevoie de numărul de caractere în reprezentarea dorită. programatori profesioniști sunt foarte mândru de a folosi notație hexazecimală. În primul rând, să-l descrie în valoare de un octet este suficient de numai două caractere. Și în al doilea rând, bytes sunt utilizate pentru a grupa împreună într-un cuvânt (2 octeți) și cuvinte duble (4 octeți), pentru a fi în măsură să reprezinte un număr mai mare de 255. Și acum, ne confruntăm cu o provocare: pentru a determina care numărul este cuvântul mașină, constând din 2-x bytes (ordinea este importantă!). Este necesar să se calculeze: 28 * 256 + 86 = 7254. Dar, dacă utilizați un 16-chnuyu (nu doresc să aibă să repete această „coadă la“ cuvânt) sistemului, numărul necesar pentru a obține un simplu „lipire“. Ie în acest caz, = 1C56! Chiar mai mult, evident, avantajele sale sunt afișate atunci când numărul ar trebui să fie invers, „divide“, în octeți.

Deci, din nou, ne întoarcem la banane noastre. Rulați programul de și să examineze cu atenție rezultatul. Octeții de la 14 la 19 (să se exprime în 16-ary, îmi pare rău-c) este situat linia noastră de „Bună ziua!“. Încălzește. Și notă, se termină cu codul de zero octeți, așa-numitul „null-terminat.“ Deci, aranjate în rânduri programe C. Compilatorul a constatat că funcția este numită (MessageBox), al cărui argument este un șir de caractere în stilul C (în terminologia corespunde tipului de Delphi PChar). Și astfel, în loc de reprezentare internă destul de complexă a „Pascal“, format necesar „sishnuyu“.

Du-te înainte, să sape mai adânc. Cum de a determina cât de multe bytes sunt SomeProc noastre? Pentru a face acest lucru, are nevoie de o mică schimbare: Procedura SomeProc;
începe
asm
NOP
NOP
se încheie;
MessageBox (0, 'Bună ziua!', Nil, 0);
asm
NOP
NOP
se încheie;
se încheie;

În Delphi există o oportunitate convenabilă de a insera în bucăți noastre cod de program scris în întregime în limbaj de asamblare. Instrucțiunile sunt scrise între cuvinte cheie și la sfârșitul A.Ș.M., și inserat de compilator la locul potrivit codul obiect neschimbat. Am nevoie doar de o singură instrucțiune de asamblare - NOP (o abreviere a „nr OPERATION“), a cărui sarcină principală -. Pentru a face nimic, și țineți în liniște un singur octet de memorie (vă spun un secret, cu codul 90.) Unii oameni au, probabil, .., am dat seama că ceea ce am pus această instrucțiune de două ori la începutul și la sfârșitul protsedurki noastre acum putem spune sigur că totul este aranjat între cele două perechi de cod octet 90 este noastre SomeProc două aceleași instrucțiuni - pentru fiabilitate, pentru a separa nop'y lor de la alții. desigur, compilatorul nu nevoie doar de TSA vlyat în codul nu a făcut o declarație, dar chiar și mai mult nu este nevoie să introduceți-l de două ori.

Deci, rola tambur, executați programul nostru. Așa-asta. De două ori nouăzeci la bun început - aceasta înseamnă că avem, în cazul în care este necesar. Deja bine. Dă-i drumul. Numerotată, sau ca programatori spun la 1B deplasare a se vedea a doua pereche, asa ca am gasit procedura noastra are 19 bytes! Doar ce dracu '? String 'Bună ziua!' în aceste limite, nu! Dar șirul este în interiorul procedurii, de ce în cele din urmă sa dovedit a fi în afara? Aici este, cum era de așteptat, sa mutat la patru octeți în raport cu poziția anterioară (am adăugat un total de 4 nop'a), dar este în afara! Prin urmare, este necesar să se facă o concluzie importantă: în ciuda faptului că codul sursă al informațiilor program și instrucțiunile sunt lângă un program de funcționare, acestea sunt separate, fiecare la locul lui (zboara separat, cotlete, pe care le cunoașteți.).

Acum, să facem un experiment: nu lasati compilatorul aloca arbitrar un loc în linie, și fă-o pentru tine și să vedem ce se întâmplă. SomeProc devin astfel: Procedură SomeProc;
const
s: array [0..7] de char = 'alo' # 0;
începe
asm
NOP
NOP
se încheie;
MessageBox (0, s, zero, 0);
asm
NOP
NOP
se încheie;
se încheie;

Rulați programul și ceea ce vedem? Bar dispare din casele lor spre o destinație necunoscută! Faceți o mai concluzie: Datele sunt stocate în locuri diferite, iar aceste locuri depind de cine le-a pus acolo - compilator sau programator. Talk Talk, dar o linie întreagă undeva are plină zi. Acesta va avea cu siguranță să găsească!

În căutarea lui Nemo

Primii pași în programare de nivel scăzut

A existat un tabel cu trei coloane, ceva asemănător cu al nostru cu tine recent studiat. Datele sunt prezentate în mijloc și pe dreapta - ca codurile hexazecimale și simboluri, cum ar fi, respectiv. A prezentat în coloana din stânga offset.

Apăsați Alt + G, pentru a sări la deplasarea. Deci, noi intra in prima - 00450C28, și imediat - noroc! String este găsit. Apropo, sa dovedit că 450C2868 compensate nu face parte din programul nostru (cec). Excelent, un coleg, așa că am descoperi acest caz.

Aici, probabil, și să termin de divertisment noastre (sperăm) o narațiune (din nou, sperăm) să vă ajute să se uite la programare dintr-o perspectivă diferită, și a deschis dorința de a continua „cercetarea de nivel scăzut.“ Ei bine, dacă da, scrie-mi că vă interesează, și sper că în curând va fi continuată. Rămâi sănătos!