Jump to content
juice

Scurt tutorial Assembler

Recommended Posts

Programarea in limbaj de asamblare 8086

Pentru inceput , cum se cuvine sa incep cu inceputul :) , dar cum in asm sunt mai multe inceputuri(de la reprezentarea numerelelor in calculator la editarea primului program , operatiile simple, etc). Sa analizam mai intai programul care asambleaza sursele in asm(TASM).

De obicei in viata de zi cu zi lucram cu numere in baza 10 , poate pentru simplul fapt ca asa e conceput omul cu 10 degete ca si fraza : 24 hours in a day , 24 beers in a case, Coincidence ?:). Asamblorul "gandeste" doar numere in baza 2 si reprezinta totul in baza 16 Sa trec la lucruri mai serioase.

1.1 Traseul de la program sursa la format executabil

Prin fisier ASM se intelege un fisier ce contine un text sursa scris in limbaj de asamblare.

Pentru a putea executa un program in limbaj de asamblare , trebuie sa avem in vedere efectuarea unor pasi:

- editarea textului sursa

- asamblarea

- editarea de legaturi

- eventual depanarea programului pentru detectarea erorilor

- lansarea in executie a fisierului executabil

1.1.1 Editarea textului sursa

Deoarece programul TASM nu contine un editor de texte incorporat, un program in limbaj de asamblare poate fi editat in orice editor de texte avut la dispozitie (ex. in Windows : Notepad,Worpad,etc.). Desigur ca au aparut o serie de IDE, precum Spasm/RosAsm, Visual Assembler si atele.

1.1.2 Asamblarea

Programele scrise in limbaj de asamblare precum si cele scrise in limbaj de programare inalt , trebuie transpuse in limbaj masina inainte de a fi executate. Aceast limbaj este constituit din coduri numerice, fiecare cu o anumita semnificatie pentru CPU.

Asamblorul de fapt este programul in sine care converteste codul sursa din limbaj de asm in limbaj masina si converteste adresele de memorie simbolice ale entitatilor din program in adrese de memorie concrete(fizice). Limbajul masina al unui sistem de calcul este format din totalitatea intructiunilor puse la dispozitie de procesor. Aceste instructiuni se reprezinta sub forma unor siruri de biti, cu semnificatie prestabilita(cod)-limbajul nativ la care procesorul raspunde direct.

Spre exemplu se poate asambla un program x.asm utilizand comanda din programul TASM : tasm /zi x.asm. Optiunea /zi este cea mai avantajoasa pentru ca dupa ce asamblam programul o sa apara toate instructiunile scrise si nu doar adresele de memorie ale acestora reprezentate pe biti in calculator(introducerea informatiei simbolica). In urma executarii acestei comenzi se genereaza fisierul x.obj.

1.1.3 Editarea de legaturi.

Un asamblor genereaza fisiere cod obiect, care urmeaza sa fie supuse procesului de editare de legaturi. Sarcina lui este de a combina fisiere individuale create de catre asamblor intr-un singur program executabil.

Legaturile se fac utilizand comanda : tlink /v x.obj. Se genereaza fisierul x.exe - executabil.

1.1.4 Depanarea ( Debugger )

Este folosit pentru urmarirea executiei unui program si verificarea continutului memoriei de catre programatori( ajuta la verificarea rezultatelor obtinute in urma efectuarii a pasilor anteriori). De altfel erorile de sintaxa daca exista sunt depistate de catre asamblor, dar in general este utilizat pentru depistarea erorilor logice ale programului, erori numite si erori semantice.

Pentru depanare utilizam comanda : td x.exe si este lansat Turbo Debugger-ul.

In urmatoarele randuri sa "mazgalesc" forma generala a unui program scris in limbaj de asamblare :)

Pentru simplul exemplu pe care o sa-l prezint se vor defini trei segmente:

- un segment de date , un segment de cod si unul de stiva cu denumirile data,code, respectiv stiva.

Mai intai e nevoie de putina explicatie in legatura cu registrii procesorului 80x86. Exista cativa registri generali ai UE(unitate executiva):

- AX : acumulator - registrul cel mai des folosit continand unul dintre operanzi pentru majoritatea instrunctiunilor din procesor.

- BX : base register - are rol in adresare.

- CX : registru contor - registru de numarare pentru unele instructiuni care au nevoie de indicatii numerice(ca in MS-DOS :loop);

- DX : data register - impreuna cu registrul AX se foloseste in calculele ale caror rezultate necesita reprezentari pe dublu cuvant DX:AX

- SP : stack pointer - lucrul cu stiva ; stiva e bazata pe LIFO - last in first out

- BP : base pointer - idem

- SS : stack segment

- SP : registrul care pune in cuvinte datele; stiva este organizata in cuvinte.

- BP : puncteaza spre baza stivei

- SI,DI - registri de index - source index respectiv destionation index.

Registrii generali au 16 biti. Pentru a accesa doar un octet din acesi 16 biti folosim in loc de AX , AL = acumulator low sau AH = acumulator high;la fel si pentru ceilalti ,iar asta veti vedea in exemplele de mai jos.

Inainte de a incepe sa programam in assembler trebuie sa intelegem foarte clar ce inseamna bit byte word(cuvant) doubleword(dublucuvant). 1 bit poate avea doar valoarea 1 sau 0. Bitul este de fapt unitatea de baza in reprezentarea informatiei. Toate procesele in calculator sunt reprezentate in biti. Ca sa intelegeti dam exemple : de la programe simple concepute in limbaje de programare de nivel scazut pana la programe in limbaje de nivel inalt totul este reprezentat in procesor cu ajutorul numerelor 1 si 0. Greu de grezut nu ?:), cand stim ca si un fisier .mp3 ce-l ascultam la calculator sau un fisier .avi ce-l vizionam , este doar o succesiune de `enorm de multi biti` iar acesti biti sunt decodati cu programe speciale , in cazul *mp3 e winamp,etc iar la *.avi sunt codecurile. Deci sa facem legaturile de rigoare avand in vedere reprezentarile numerelor in calculator: 8 biti=octet(byte) ,

16 biti(word/cuvant)=2 octeti , 32 biti = doubleword(2 cuvinte) sau 4 octeti.

Avand in vedere acestea sa icepem si programul:

assume cs:code, ds:Data

;o linie precedata de ";" inseamna comentariu deci nici un caracter dupa caracterul ";" nu va fi ;luat in considerare de catre ;asamblor.

;utilizarea directivei assume este necesara pentru a preciza asamblorului continutul carui ;registru de segment sa fie luat in considerare pentru a calcula adresele efective ale ;etichetelor folosite in program; in acest caz avem registrul CS va fi considerata ;adresa de segment corespunzatoare etichetelor definite in segm de cod(vedem mai jos "start:"), iar DS se ;va folosi ca registru de ;segment pentru datele definite data segment

;pur si simplu definim segmentul de date, declaram variabilele. in asm se lucreaza totul in hex ;si apoi e binar pentru a fi ;transformate instructiunile,etichetele,directivele in instructiuni limbaj masina respectiv adrese fizice

a db 5 ; a define byte(1 byte=1 octet=8 biti) si ii atribuim valoarea 5

b dw 7 ; b define word(1 word=2 octeti=16 biti) -> 7

c dd 10 ; c define doubleword(1dd=2 words=32 biti) -> 10

rez dw ? ; aici luam variabila rez de tip word si o lasam neinitializata dupa cum reprezinta ; si caracterul "?"

data ends ; sfarsitul segmentului de date, terminarea declararii de date

code segment ; definim codul de segment numit code

start:

; eticheta start marcheaza pozitia de la care sa inceapa executia programului

; segmentul de cod este incarcat automat in registrul CS in momentul lansarii in executie a programului.

; pe de alta parte registrul de segment de date DS trebuie incarcat in cadrul programului cu adresa unui segment ;de date.

;varianta 1: NU se poate executa o instructiune de forma "mov DS,data" deoarece instructiunea mov ;trebuie sa aiba ca ;operand cel putin un registru general sau o valoare imediata , si se va genera ;eroarea "Illegal use of segment register"

;se poate folosi de altfel intermediar registrul acumulator AX

mov ax,data

mov ds,ax

;varianta 2 - folosim stiva ca depozit auxiliar: salvam pe stiva adresa de segment asociata lui data , dupa ;care scoatem ;din stiva acest cuvant in registrul de date.

push data ; salvarea pe stiva a datelor

pop ds ; scoaterea in ds din stiva a datelor

; ...

;instructiunile programului

;..

mov ax,4c00h ; punem in registrul pricincipal AX valoarea 4c00h in hexa: 4Ch in AH - reprezinta numarul functiei ;intreuperii 21h , functie apelata pentru terminarea unui program , respectiv 00h in AL - valoarea folosita

;ca si cod de retur din programul incheiat. Acest cod poate fi 0 , depinde daca ii asociem o anumita

;semnificatie legata de succesul sau insuccesul unor operatii la iesirea din program si pentru faptul ca

;putem utiliza mai departe aceasta valoare.

int 21h

code ends ;sfarsit segmentul de cod

stiva segment

;definirea unui segment de stiva nu este neaparat necesar; in cazul in care nu specificam un segment ;de acest gen se va folosi implicit ca stiva spatiul ramas neocupat din cadrul unui alt segment. Totusi ;daca stim ca avem nevoie de spatiu mai mare pentru utilizarea stivei este indicata definirea unui ;asemenea segment. Putem rezerva spatiu cu ajutorul instructiunii ORG, specificand numarul de octeti in ;memorie de care avem nevoie.

org 100h ;rezerva un spatiu de dimensiune 100h octeti = 256 octeti

stiva ends

end start ;sfarsitul codului sursa:) huh

Cam aceasta a fost forma generala a unui program in ASM , o programare de nivel scazut bineinteles.

Sa concep un simplu program care efectueaza cateva operatii aritmetice explicand si instrunctiunile folosite.

Calculati expresia : (a*b+c-d)/a

assume cs:code,ds:Data ; directiva assume

data segment ; segmentul de date

db a 2 ; definirea datelor si initializarea lor , numarele a si b sunt reprezentate in calculator pe 8 biti(octet) dupa ; cum se vede (define BYTE)

db b 6

dw c 4 ; numarul c este reprezentat de 2 octeti (2bytes)=1cuvant(word)=define word

db d 9 ; numarul d reprezentat doar pe 8 biti pentru a observa si niste conversii de marimi de adrese in program.

dw rez ? ; si rezultatul in care vom calcula expresia trebuie de altfel sa fie cuvant pe 16 biti

data ends ; sfarsit segmentul de date

code segment

start:

mov ax,data ; cum am explicat si mai sus , punem data in registrul ds folosind ca si registru auxiliar , registrul general mov ds,ax ; AX,cel mai des folosit de altfel

mov al,a ; instructiunea mov pune numarul a pe 8 biti in registrul al care este tot pe 8 biti, deci in ax=a doar 8 biti fiind ; ocupati

mul b ; instructiunea mul , inmuleste ce exista in ax cu destinatia(B). se poate folosi si imul pentru numere cu ; semn. Deci ax = ce am avut inainte dupa "mov" adica a inmultit cu destiatia b(ax=a*B). Trebuie tinut cont ; de faptul ca inmultirea a doua numere converteste automat rezultatul din 8 biti in 16 biti(word) cum avem si ; numarul c de altfel. Nu putem efectua operatii cu date de diferite marimi pe biti.

add ax, c ; adunam la ax numarul c. ax =a*b+c

; acum mai avem de scazut din ax numarul d,dar cum rezultatul in ax este pe 16 biti si numarul d este doar ; pe 8 biti este necesar sa convertim numarul d la 16 biti.

; si cum facem asta?; pai punem numarul d intr-un registru general(retineti operatiile se pot efectua doar pe ; registri) si il convertim.

mov bx,ax ; retinem temporar rezultatul ax=a*b+c in bx pentru a putea utiliza registrul ax la alte operatii.

mov al, d ; ax=d reprezentat pe 8 biti

cbw ; convert byte to word , deci numarul d acum este pe 16 biti si putem efectua calculul.Dar daca inmultim ; spre exemplu doua numere pe 16 biti avem un rezultat pe 32 biti , deci avem nevoie de o eventuala ; conversie si pentru aceasta exista instructiunea cwd(conver word to doubleword).

sub bx,ax ; scadem din bx registrul ax in care avem nr d; bx=a*b+c-d. pe 16 biti.

mov ax,bx ; punem bx in ax pentru a fectua impartirea cu a

div a ; cum in ax avem un rezultat pe 16 biti si trebuie impartit la un numar pe 8 biti nu avem nevoie de conversie.

; sa retinem ca inmultirea a doua numere dubleaza spatiul de biti , iar impartirea il injumatateste iar pentru ;a efectua o impartire trebuie ca deimpartitul sa fie dublu decat impartitorul ca si in cazul nostru bx=a*b+c-d

; cum nu avem registri pe 32 biti retinem un rezultat de 32 biti in doi registri DX:AX(reprezentarea in ;calculator e in ordine inversa AX contine cifrele mai semnificative iar DX cele mai putin semnificative dar in ;asm apar chiar invers

; este pe 16 biti iar numarul a este doar pe 8 biti.

; deci ax=bx/a mai precis rezultatul dorit ax=(a*b+c-d)/a

mov ax,4c00h ; terminarea executiei programului

int 21h

end start.

Sa definim putin limitele define-urilor de numere.

Define Byte (8octeti) poate avea valorea de la [0,255] (256 valori) sau [-128,127] si ca sa intelegem de ce este luata asa aceasta valoare o sa explic , pentru ca nu este pusa la intamplare de cei care au conceput asamblarea. Deci de la -128 pana la 127 sunt 256 de valori. Din capetele acestui interval , insumate trebuie sa rezulte valorea 255 si cum numarul 0 este vazut ca si numar pozitiv, reprezentat in calculator cu numarul de semn pozitiv 0 trebuie sa existe -128 valori negative care incep cu 1. Deci sa retinem ca un numar reprezentat in calculator incepe cu 1 daca are valoare negativ si cu 0 daca e pozitiv. Poate ca intr-un alt tutorial ,cand voi avea timp, voi explica si reprezentarea numerele in calculator cu bitul de semn , caracteristica si mantisa in cod complementar si cod invers.

Inteleg ca este grea programarea in ASM si nu stiu cat s-a inteles si cat nu , si daca a fost util acest tutorial , dar pentru a intelege mai bine limbajul assembler trebuie lucrat foarte mult. Cititi-l de mai multe ori si daca vi se pare de inteles si interesant probabil va genera o avansare in acest domeniu. Assembler-ul cum spunea si teacher-ul meu :) se invata gresind; gresesti si apoi intelegi eroarea si instructiunea , retinand totul mai bine asa in mod logic. Am scris acest scurt tutorial, si pentru faptul ca am considerat a-mi fi utila aceasta antrenare de..neuroni:), m-am ghidat dupa vorba "O materie se invata usor si se retine bine atunci cand o predai sau o explici cuiva". Dupa primele eforturi de a intelege limbajul poate vor fi si dezamagiri dar sa meditam la replica lui

[Winston Churchill] : "Succesul inseamna a fi in stare sa mergi din esec in esec, fara sa-ti pierzi entuziasmul."; tineam s-o intoduc si pe asta aici asa ca fapt divers.

Cu implementare de programe si alte explicatii detaliate...voi reveni , sper , cat de curand:). Pana atunci Bafta.

26 Sept 2006 By JuiCe

Link to comment
Share on other sites

{S}ub_{Z}ero itzi recomand cartea lui Randall Hyde , cu toate ca e cam complexa:) dar daca iti doresti sa invetzi catushi de putin , ca la nivel expert de programare in asm cam greu si te ia naiba daca pici sa lucrezi pe un post programand doar in assembler :) grr

link : http://webster.cs.ucr.edu/AoA/ Art of Assembly si pt toturial in romana..doar..daca ma contactezi , si eu is novice in asm :) tutoriale in romana de asm..cam greu si nu prea :P

Link to comment
Share on other sites

da' , bon , merci virusz pentru aprecierea ta daca pot sa o numesc asa, o sa incerc sa ajut cu toturiale in romana asm , ca in alte parti am fost acuzat :) chestia cu fdisk-ul nu se atribuia unui PC > P3 , ci mai sunt care vin cu calculatoare P1 si din anumite cauze nu vrea nicicum sa iasa partitionarea sau formatarea , bad-uri etc. da' e bine , totusi multumesc pt critici :) trebuie sa existe si d-astea ca doar , perfect nu e nimeni , bafta

Link to comment
Share on other sites

poti sa o numesti asa :D, np :)

contiua sa faci tutoriale ca le ai dar fii antena cnd le scrii!

offtopic:

pai dak vine ala cu P1 la tine poti sa pui hardu' la tine :D na... si nu numai fdisk este utilar de partitionare, sunt si altele care merg si pe p1 ...in fine :D ..dak vine unu' cu p1 la tine sa ii faci compul trimitel acasa sa bea o bere :D

Have Bafta! lol. :D

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...