Nu aveti permisiuni pentru a descarca fisierul grader_test7.ok
Diferente pentru introducere-in-asamblare intre reviziile #25 si #24
Nu exista diferente intre titluri.
Diferente intre continut:
h1. Introducere in asamblare
(Categoria _Limbaje_, autor(i) _Botau Cristian_)
Acest articol prezinta un limbaj mai putin folosit : limbajul de asamblare. Este folosit de cele mai multe ori pentru marirea vitezei de rulare a programelor. In prima sectiune sunt prezentate cateva avantaje / dezavantaje in folosirea acestui limbaj, iar ulterior sunt definite notiunile elementare ce trebuie stiute inainte de a trece la tratarea limbajului propriu-zis. De asemenea, sunt prezentate cateva intructiuni si transcrieri ale unor structuri din C/Pascal in limbaj de asamblare. In final sunt comparati timpii de executie intre varianta pascal si varianta assembler ale unei proceduri de {$Bubble Sort$}. h2. Limbajul de asamblare : avantaje si dezavantaje in folosirea lui
mov ax, 2 int 0x33; }
==
== h2. Transcrierea unor instructiuni C/PASCAL in asamblare h3. IF cond THEN instr Exemplu : == code(cpp) |if (a==5) b=a; // a, b : integer == == code(cpp) |mov ax, a cmp ax, 5 // ne intrebam daca !cond jnz @skip_if mov b, ax @skip_if : == h3. IF cond THEN instr1 ELSE instr2 Exemplu: == code(cpp) |if (a==b) a-=b; else b-=a; == Transcrierea in asamblare : == code(cpp) |mov ax, a mov bx, b // compara ax cu bx si seteaza flag-urile cmp ax, bx je @if_then // if (ax == bx) sari la @if_then sub b, ax jmp @end_if : @if_then : sub a, bx @end_if : == h3. DO { inst } WHILE Exemplu : == code(cpp) |int i, a, n; i = 0; a = 0; do { i++; a+=i; } while (i<=n); == Codul in asamblare : == code(cpp) |// cx = 0, instructiunea xor cx, cx este // mai rapida decat mov cx, 0 xor cx, cx xor ax, ax mov bx, n @while : inc cx add ax, cx cmp cx, bx jne @while mov a, ax mov I, cx == Sau folosind instructiunea loop (pornim invers) : == code(cpp) |mov cx, n @while: add ax, cx loop @while == In codul de mai sus (prima varianta) puteti observa cateva mici optimizari : retinerea variabilelor in registri (accesul la registri este mult mai rapid decat la memorie), inlocuirea instructiunii {$mov reg, 0$ cu {$xor reg, reg$}. Varianta "xor" este mai rapida (desi $mov$ si $xor$ "teoretic" au tot atatea ceasuri de procesor) deoarece instructiunea $mov reg, 0$ transcrisa in cod masina este mai "lunga" (are cu $2-4$ bytes mai mult decat {$xor reg, reg$}). Aceeasi regula se aplica si in cazul "{$or reg, reg$}" in testarea daca valoarea unui registru este egala cu {$0$}, intrucat instructiunea "{$or$}" modifica flagurile procesorului ({$ZeroFlag$}). O alta optimizare este folosirea registrului $ax$ pentru calcule (in majoritatea cazurilor instructiunile care folosesc registrul $(e)ax$ sunt mai rapide). h2. Program demonstrativ Exemplu de functie in realizata in C/Asamblare (compilator folosit BC++ 3.1): == code(cpp) |// BSort.CPP #include <stdio.h> #include <conio.h> int a[20], n; void bsort() { asm { mov di,seg a mov es,di mov di,offset a // es:[di] inceputul vectorului // es - adresa segment // di - adresa offset }; do_while_not_ok : asm { // ok = 1; mov dx, 1 // cx = n; mov cx, n // cx = n-1 dec cx // ax = a[0] mov ax, es:[di] // punem di pe stiva push di } inner_for : asm { // bx = a[i-1] mov bx, ax // ne mutam pe noua pozitie in vector add di, 2 // ax = a[i] mov ax, es:[di] // comparam ax cu bx (a[i-1] cu a[i]) cmp bx, ax // if (a[i-1] <= a[i]) don't swap jbe if_not // interschimbam a[i-1] cu a[i] xchg bx, ax // le scriem in memorie mov es:[di], ax mov es:[di-2], bx // ok = 0 xor dx, dx } if_not : asm { // cx--; dec cx jnz inner_for // daca cx != 0 atunci continuam for-ul pop di // compara dx cu 0 // (mai rapid decat cmp dx, 0) or dx, dx // if (ok) executam inca odata while-ul jz do_while_not_ok } } void citire() { printf("Numarul de elemente : "); scanf("%d", &n); for (int i=0; i<n; i++) { printf("a[%d] = ", i); scanf("%d", &a[i]); } } void afis() { for (int i=0; i<n; i++) printf("%d ", a[i]); } int main() { citire(); bsort(); afis(); return 0; } == Varianta Pascal + Asm (compilata cu BP 7.0): == code(pas) |program b_sort; const max_N = 1000; n_tests = 100; var N : Integer; a, b : array [1..max_N] of Integer; procedure citire; var f : Text; i : Integer; begin Assign(f, 'bsort.in'); Reset(f); readln(f, N); for i := 1 to N do read(f, b[i]); Close(f) end; procedure flip; var i : Integer; begin for i:=1 to N do a[i] := b[i]; end; var p : pointer; procedure bsort; assembler; asm { les <=> es = seg(p), di = offset(p) } les di, p @do_while_not_ok : mov dx, 1 mov cx, N dec cx mov ax, es:[di] push di @inner_for : mov bx, ax add di, 2 mov ax, es:[di] cmp bx, ax jbe @if_not xchg bx, ax mov es:[di], ax mov es:[di-2], bx xor dx, dx @if_not : dec cx jnz @inner_for pop di or dx, dx jz @do_while_not_ok end; procedure bsort2; var ok : Boolean; i, aux : Integer; begin repeat ok := true; for i := 1 to n-1 do if (a[i] > a[i+1]) then begin aux := a[i]; a[i] := a[i+1]; a[i+1] := aux; ok := false; end; until ok; end; var i : Integer; starttick, endtick : LongInt; time : Longint absolute $0000:$046C; { timer pentru masurarea timpului } const tickspersecond = 18.206; procedure starttimer; begin starttick := time; end; function elapsedtime : real; begin endtick := time; elapsedtime := (endtick - starttick)* (1 / tickspersecond); end; begin citire; p := @a; starttimer; for i:=1 to n_tests do begin flip; bsort; end; writeln(n_tests, ' rulari ale bsort in asamblare au rulat in : ', elapsedtime : 6:3, ' secunde'); starttimer; for i:=1 to n_tests do begin flip; bsort2; end; writeln(n_tests, ' rulari ale bsort obisnuit au rulat in : ',elapsedtime : 6:3, ' secunde'); end. == Output program pascal (pe pc-ul meu: Duron $750$ Mhz): $100$ rulari ale bsort in asamblare au rulat in : $1.263$ secunde $100$ rulari ale bsort obisnuit au rulat in : $4.614$ secunde De precizat este ca nu am optimizat programul aproape deloc (am transcris codul din pascal in asm). Cu optimizari "hardcore" se pot obtine timpi mult mai buni. Diferenta dintre varianta asm si varianta high level language este mai mica pe compilatoarele mai noi, cum ar fi GCC sau FreePascal deoarece acestea stiu genera un cod mai optimizat. Totusi, nici un compilator nu poate bate creierul uman. h2. Linkuri "Link #1":http://www.arl.wustl.edu/~lockwood/class/cs306/books/ "Link #2":http://artofasm/toc.html Cartea "The Art of Assembly Language Programming". Este detaliata. Foarte buna atat pentru incepatori cat si pentru avansati. "Link #3":http://www.goof.com/pcg/doc/pentopt.txt Un tutorial bun pentru optimizarea programelor in asamblare pentru procesoarele din familia Pentium. Tutorialul este pentru avansati. "Link #4":http://www.techtutorials.info/assembly.html Mai multe tutoriale despre assembly language. h2. Doua cuvinte conclusive... Acest articol trateaza "bazele" programarii in asamblare, dupa cum ii zice numele este doar o introducere. Pentru a sti sa programezi in asm, trebuie invatate mult mai multe lucruri. Scopul articolului este de a starni interesul cititorilor si de a le oferi o imagine asupra acestui limbaj. Cei ce doresc sa invete mai multe despre assembly language sunt invitati sa citeasca cartile / tutorialele din sectiunea linkuri.