Diferente pentru introducere-in-asamblare intre reviziile #15 si #16

Nu exista diferente intre titluri.

Diferente intre continut:

h2. Transcrierea unor instructiuni C/PASCAL in asamblare
* IF cond THEN instr
h3. IF cond THEN instr
Exemplu : if (a==5) b=a; // a, b * integer
Exemplu :
mov ax, a
cmp ax, 5
== 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
* IF cond THEN instr1 ELSE instr2
Exemplu:
Exemplu : if (a==b) a-=b; else b-=a;
== code(cpp) |if (a==b) a-=b; else b-=a;
==
Transcrierea in asamblare :
mov ax, a
== 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 :
==
 
* DO { inst } WHILE
h3. DO { inst } WHILE
Exemplu :
int i, a, n;
== code(cpp) |int i, a, n;
i = 0;
a = 0;
do
{
i++;
a+=I;
    i++;
    a+=i;
} while (i<=n);
 
 
Codul in asamblare :
// cx = 0, instructiunea xor cx, cx este
 
== 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
    inc cx
    add ax, cx
    cmp cx, bx
    jne @while
mov a, ax
mov I, cx
 
==
Sau folosind instructiunea loop (pornim invers) :
mov cx, n
 
== code(cpp) |mov cx, n
@while:
add ax, cx
    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).
 
 
 
 
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).
Program demonstrativ
h2. Program demonstrativ
Exemplu de functie in realizata in C/Asamblare (compilator folosit BC++ 3.1):
// BSort.CPP
== code(cpp) |// BSort.CPP
#include <stdio.h>
#include <conio.h>
void bsort()
{
asm {
mov di,seg a
mov es,di
mov di,offset a
// es:[di] inceputul vectorului
// es - adresa segment
// di - adresa offset
};
	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
}
	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
}
	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
}
	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]);
}
	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]);
	for (int i=0; i<n; i++)
		printf("%d ", a[i]);
}
int main()
{
citire();
bsort();
afis();
return 0;
	citire();
	bsort();
	afis();
	return 0;
}
==
Varianta Pascal + Asm (compilata cu BP 7.0):
program b_sort;
== code(pas) |program b_sort;
 
const   max_N = 1000;
        n_tests = 100;
const
max_N = 1000;
n_tests = 100;
 
var
N : Integer;
a, b : array [1..max_N] of Integer;
var N : Integer;
    a, b : array [1..max_N] of Integer;
procedure citire;
var
f : Text;
i : Integer;
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)
    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;
var i : Integer;
begin
for i:=1 to N do
a[i] := b[i];
    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
    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;
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;
    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;
var i : Integer;
    starttick, endtick : LongInt;
    time : Longint absolute $0000:$046C;
{ timer pentru masurarea timpului }
const tickspersecond = 18.206;
procedure starttimer;
begin
starttick := time;
    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;
    endtick := time;
    elapsedtime := (endtick - starttick)*
        (1 / tickspersecond);
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');
    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
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
 
 
 
Linkuri
 
[1]http://www.arl.wustl.edu/~lockwood/class/cs306/books/
 
artofasm/toc.html
 
 
"[1]":http://www.arl.wustl.edu/~lockwood/class/cs306/books/
"[2]":artofasm/toc.html
Cartea "The Art of Assembly Language Programming". Este detaliata. Foarte buna atat pentru incepatori cat si pentru avansati.
[2]http://www.goof.com/pcg/doc/pentopt.txt
 
 
"[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.
[3]http://www.techtutorials.info/assembly.html
 
 
"[4]":http://www.techtutorials.info/assembly.html
Mai multe tutoriale despre assembly language.
Doua cuvinte conclusive...
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.
 
References
 
Visible links
1. http://www.arl.wustl.edu/%7elockwood/class/cs306/books/artofasm/toc.html
2. http://www.goof.com/pcg/doc/pentopt.txt
3. http://www.techtutorials.info/assembly.html
 

Nu exista diferente intre securitate.

Topicul de forum nu a fost schimbat.