Assembler, lectia 2 - Diverse instructiuni: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1) Registrii procesorului (cei cu "E" sunt la 386+) (recapitulare): - general purpose registers: - segment

registers: EAX, AX, AL, AH - accumulator CS - code segment EBX, BX, BL, BH - base DS - data segment ECX, CX, CL, CH - count SS - stack segment EDX, DX, DL, DH - data ES - extra segment FS (386+), GS(386+) - pointer registers: ESP, SP - stack pointer EBP, BP - base pointer - instruction pointer: EIP, IP - flags register: CF - carry, TF - trace, |--|--|--|--|OF|DF|IF|TF|SF|ZF|--|AF|--|PF|--|CF| ------------------------------------------------15 0 PF - parity, AF - auxiliary flag, ZF - zero, SF - sign, IF - interrupt, DF - direction, OF - overflow - index registers: ESI, SI - source index EDI, DI - destination index

2) Instructiuni referitoare la registrul de flaguri (recapitulare): lahf sahf pushf popf ;copiaza in AH octetul low al reg. de flaguri ;copiaza in octetul low al reg. de flaguri pe AH ;salveaza in stiva (push) registrul de flaguri ;incarca din stiva (pop) registrul de flaguri

3) Instructiuni de setat/sters flaguri individuale (nu au operanzi): STC (face CF:=1), CLC (face CF:=0), CMC (face CF:=1-CF), STD (face DF:=1), CLD (face DF:=0), STI (face IF:=1), CLI (face IF:=0) Obs: pt. restul flagurilor nu avem instructiuni de setat/sters explicite; putem face artificii, de ex. putem face AF:=1 executand: mov ah,10h sahf ;bitul 4 din AH este 1 (si restul 0) ;bitul 4 din reg. de flaguri, i.e. AF, este 1; ; restul devin insa 0

sau mai elegant (fara a altera alte flaguri): lahf or ah,10h sahf ;incarc flagurile in AH ;AH:=AH 0R 10h (bitul 4 din ah devine 1, restul raman la fel) ;salvez AH in flaguri

Mentionam ca instr. "MOV", "XCHG", "LAHF", "LEA", "LDS", "LEs", "PUSH", "POP" (prezentate in lectia 1) nu afecteaza flagurile. In cele ce urmeaza vom nota flagurile modificate de o instructiune astfel: ODITSZAPC ==> inseamna: CF nedefinit, PF afectat, AF devine 1, ZF devine 0

01XU 4) Instructiuni aritmetice pentru intregi: Instructiunile de incrementare/decrementare ("d" poate fi reg.sau din mem.): INC d DEC d ;efect: [d] := [d]+1 si nu afecteaza flagurile ;efect: [d] := [d]-1 si afecteaza: ODITSZAPC ; X XXXXX ;(practic insa, pe ex.simple am constatat ca "DEC" nu afecteaza CF)

Instructiunile aditive sunt de forma "mnemonic destinatie,sursa", unde "destinatie" poate fi registru sau din memorie, "sursa" poate fi imediat, registru sau memorie; operanzii nu pot fi ambii din memorie si trebuie sa aibe aceeasi dimensiune; afecteaza ODITSZAPC X XXXXX ADD s,d ;face [s] := [s] + [d] ADC s,d ;face [s] := [s] + [d] + CF SUB s,d ;face [s] := [s] - [d] SBB s,d ;face [s] := [s] - [d] - CF Toate instructiunile de mai sus seteaza CF=1 daca are loc transport/imprumut la bitul cel mai semnificativ; "ADC" si "SBB" folosesc in calcularea rezultatului pe CF provenit de la instructiunile anterioare (si genereaza un nou CF=0 sau CF=1). Notam ca intre "INC d" si "ADD d,1" exista diferenta importanta ca prima nu afeceaza CF - astfel, putem aduna elementele unui vector (cu "ADD") fara ca incrementarea indicelui (cu "INC") sa afecteze transportul produs de ele. Exemplul 1 (la rularea sub TD se vor urmari registii si flagurile): ~~~~~~~~~~ .model tiny .stack .data .code start: mov ax,01f2h add al,0ch ;rezulta AL=feh, CF=0 (nu avem transport din b7 al lui AL) add al,03h ;rez.AL=01h,CF=1,dar AX=0101h (transp.din AL nu a mers in AH) adc al,05h ;rez.AL=07h (vechiul AL + 05h + vechiul CF), iar noul CF=0 sub al,05h ;rez.AL=02h,CF=0 (nu avem imprumut la b7 al lui AL) sub al,03h ;rez.AL=FFh,CF=1 dar AX=01FFh (impr.pt.AL nu s-a luat din AH) sbb al,0ffh ;rez.AL=FFh, adica ffh(vechiul AL)-ffh-1(vechiul CF), ; si cum am facut iar imprumut pt. b7, noul CF=1; ;in instr. am scris "0ffh" deoarece daca am fi zis "ffh" ; ar fi dat err. la compilare - "ffh" e un identificator si ; ar fi cautat o variabila numita "ffh" mov ax,01feh ;"MOV" nu afecteaza flagurile deci CF ramane 1 inc al ;rez.AL=ffh,CF=1 (nu avem transp.dar "INC" nu afect.flagurile ; deci CF ramane 1 ca inainte) inc al ;rez.AL=00h, AX=0100h (transportul nu s-a transmis in AH), ; CF=1("INC"nu afecteaza flagurile ci CF a ramas 1 dinainte) inc al ;rez.AL=01h,CF=1 (ramas dinainte) dec al ;rez.AL=00h, CF=1 (n-avem imprumut pt. b7 din AL dar "DEC" ; nu afecteaza CF si ramane 1 dinainte) dec al ;rez.AL=ffh, AX=01ffh (imprumutul pt. AL nu s-a luat), CF=1

; (am avut imprumut pt. b7 din AL dar CF=1 pentru ca asa a ; ramas dinainte, deoarece "DEC" nu afecteaza CF) mov ax,4c00h int 21h end start Instructiunile "ADC" si "SBB" folosesc pentru a aduna/scadea numere intregi de mai multi octeti - se aduna/scad byte cu byte (sau word cu word, dword cu dword), folosindu-se transportul de la o adunare/scadere la alta Exemplul 2: ~~~~~~~~~~~ .model small .stack .data a dw 0ff01h,0ff02h,0af03h ;octetii 01h ffh 02h ffh 03h afh ;adica nr. af03ff02ff01h in scr. little endian ; (daca scriem "ff01h" in loc de "0ff01h" etc. ; da err.la compilare,caci sunt identififcatori) b dw 01aah,00aah,0000h ;octetii aah 01h aah 00h 00h 00h ;adica nr. 000000aa01aah in scr. little endian x dw ?,?,? ;dupa x sunt 3 word-uri neinitializate ;adunam a+b word cu word (3 word-uri) si punem rezultatul in x .code start: mov ax,@data mov ds,ax ;copiem a in x (x:=a) mov si,offset a mov di,offset x mov ax,[si] ;la adresari indexate se fol. implicit registrul DS mov [di],ax inc si inc si inc di inc di mov ax,[si] mov [di],ax inc si inc si inc di inc di mov ax,[si] mov [di],ax ;adunam b la x (x:=x+b) mov si,offset b mov di,offset x mov ax,[di] add ax,[si] ;la prima adunare nu adunam CF, dar ea poate genera CF mov [di],ax ;deocamdata x: 00abh ff02h af03h iar CF=1;"mov"nu afect.CF inc si ; ===== <- pr. word a al sumei finale inc si inc di ;"INC"-urile nu afecteaza CF (ram.ca dupa "ADD" dinainte) inc di ; daca faceam "add si,2", "add di,2" se strica CF mov ax,[di] adc ax,[si] ;adun a doua per. de word si CF de la per. anterioara mov [di],ax ;acum x: 00abh ffadh af03h iar CF=0; "mov" nu afectaza CF

inc si ; =========== <- pr. doi word din suma finala inc si inc di inc di mov ax,[di] adc ax,[si] ;per. anterioara a gen. CF=0, dar lucram in general mov [di],ax ;acum x: 00abh ffadh af03h ;un eventual ultim transport nu se mai salveaza in x, dar ramane in CF ; (ca in cazul adunarii intre registri) ;in final obtinem de la pozitia x suma af03ffad00abh in little endian ;operatiile se pot automatiza folosind instr. de ciclare mov ax,4c00h int 21h end start (la rularea cu TD a programului de mai sus se vor urmari in fereastra Watch: a, [a+2], [a+4], b, [b+2], [b+4], x, [x+2], [x+4] iar in fereastra Registers: AX, CF si eventual SI, DI). Instructiunea de luare a opusului este ("d" poate fi reg.sau din mem.): NEG d ;efect: [d] := 0-[d] si afecteaza: ODITSZAPC X XXXXX

Instructiunile multimplicative sunt ("s" este registru sau din memorie): MUL s ;inm. acumulatorul cu [s]; operanzii sunt tratati ca intregi fara semn ;daca "s" e byte: AX:=AL*[s] (AH:=(AL*[s])div 2^8, AL:=(AL*[s])mod 2^8) ;daca "s" e word: DX:=(AX*[s])div 2^16, AX:=(AX*[s])mod 2^16 ;daca "s" e dword: EDX:=(EAX*[s])div 2^32,EAX:=(EAX*[s])mod 2^32 ;pe scurt: AX:=AL*[s], resp. (DX,AX):=AX*[s], resp. (EDX,EAX):=EAX*[s] ;afecteaza ODITSZAPC ; X UUUUX ;in final: ; CF=OF=1 <=> partea hi a rezultatului este semnificativa ; <=> AH<>0 ("s"byte),resp.DX<>0 ("s"word),resp.EDX<>0 ("s"dword) ; CF=OF=0 <=> partea hi a rez. este nesemnif. (rez. a incaput in p. low) ; <=> AH=0 ("s"byte),resp.DX=0 ("s"word),resp.EDX=0 ("s"dword) IMUL s ;similar, dar operanzii sunt tratati ca intregi cu semn iar in final: ; CF=OF=1 <=> partea hi a rezultatului este semnificativa ; CF=OF=0 <=> partea hi a rez. este nesemnif. (rez. a incaput in p. low) ; <=> AH este extensia de semn a lui AL ("s"byte), ; resp. DX este extensia de semn a lui AX ("s"word), ; resp. EDX este extensia de semn a lui EAX ("s"dword) DIV s ;impartire la [s]; operanzii sunt tratati ca intregi fara semn ;daca "s" e byte: AL:=AX div [s], AH:=AX mod [s] ;daca "s" e word: AX:=(DX*2^16+AX) div [s], DX:=(DX*2^16+AX) mod [s] ;daca "s" e dword: EAX:=(EDX*2^32+EAX) div [s],EDX:=(EDX*2^32+EAX) mod [s] ;pe scurt: impart Ax, resp. (DX,AX), resp. (EDX,EAX), la [s] ; catul se pune in partea low: AL, resp. AX, resp. EAX ; restul se pune in partea hi: AH, resp. DX, resp. EDX ;afecteaza ODITSZAPC

02h mul bl . AL=02h. AH. caci AH este semnificativ (parte a rezultatului) chiar . in AH. este semnificativa) . deci ffh din AH nu este extensie de semn ci parte a rezult.code start: mov ax.. care pe 8 biti era 80h. 256 mod -2 = 0 mov ax.adica 256 div 128 = 2. AH.hi. CF=OF=1 (partea hi.01h imul bl . dar operanzii sunt tratati ca intregi cu semn Exemplul 3: ~~~~~~~~~~~ .02h imul bl . este nesemnificativa) . adica 128*2=256 mov ax.AX=0080h. este nesemnif.0080h mov bl.in urmatoarele situatii rezultatul este nedef. U UUUUU . neg.adica 256 div -128 = -2.stack . poz.8123h mov bx. 256 mod 128 = 0 mov AX.0102h mov bl. CF=OF=0 (partea hi. deci AX=0002h . AH. CF=OF=0 (partea hi. este semnificativa) mov ax.produsul AL*BL este -128*2=-256.o intrerupere): . dar pe 6 biti devine ff80h mov ax. > val. el nu s-a propagat .AH=00h. deci AX=00feh .0100h mov bl.deci AH a devenit ffh) . restul depaseste capacitatea partii hi a destinatiei . dar s-a propagat b7 din AL.produsul AL*BL este -128*1=-128.80h idiv bl . AL=feh.AH=00h. .model tiny .data .0100h mov bl.max.) mov ax. (si se gen. < val.0080h mov bl. CF=OF=1 (partea hi. impartitorul este 0 .0002h mul bx . sau cat poz. CF=OF=0 (p. CF=OF=1 (partea hi.cu "MUL bl" rezulta AX=0100h. AH. AX=0246h.02h imul bl . DX.4c00h int 21h . care pe 16 biti este ff00h .0078h mov bl.AX=ff80h. .similar.produsul AL*BL este 128*1=128 mov ax.0080h mov bl. min. asta inseamna cat neg. este semnificativa) . care este 1.AX=ff00h.) IDIV s . deci desi b7 din AL este 1 (AL este f0h).DX=0001h. este nesemnificativa . AH. produsul AL*BL este 120*2=240 mov AX. catul depaseste capacitatea partii low a destinatiei (in cazul "IMUL" .80h div bl .AX=00f0h. daca e nul.AX=0004h (se pierde AH).01h mul bl .

[x+8].adun transportul anterior .EAX e prima cifra a prod. EAX.stack . [a+4]. BX.model small .deci x=20000000h 00000002h ? mov eax.end start (la rularea cu TD a programului de mai sus se vor urmari in fer.".ca numar a=1e1e1e1e20000000h b dd 00000011h .. noua ne trebuie ca sa putem accesa registrii de 32 biti (EAX. 2 din x .?. de 16 biti).offset a mov di. il ad.? .deci EDX=00000001h.daca am transp. EAX=fffffffeh add eax.386" permite folosirea instructiunilor neprivilegiate ale procesorului 80386 si a instructiunilor coprocesorului matematic 80387.. x.edx .data a dd 20000000h.eax .acum x=20000000h 00000000h 00000002h .prod. .dword ptr [si] mul b .4 mov [di].avansez in poz. Registers .la transp. (dword-ul) 2 din a add di. nu se vad in fer.ca numar x=20000000020000000h mov ax.@data mov ds. 1e1e1e1eh . DX si CF.avansez in poz.offset x mov eax.4c00h int 21h end start Comentarii: . iar EDX=transport (00000002h) .4 . Watch: a.general din poz. dword ptr [si] mul b .acum x=20000000h 00000000h ? add di.inmultesc b cu a doua cifra in baza 2^32 din a .la rularea cu TD vom urmari in fer.EDX=00000001h + 0h + CF = 00000002h mov [di].in baza 2^32 (primul dword) .4 . de exemplu sa inlocuim secventa: . .. 2 .ca numar b=11h x dd ?. transport in poz.acolo se vad doar reg. OF).386 . Exemplul 4: inmultirea unui numar lung (ce nu incape in 32 biti) cu un numar ~~~~~~~~~~~ mai mic (ce incape in 32 biti) (cazul fara semn): .ax mov si.).dword ptr [di] . Registers: AX.acum x=20000000h ? ? add si. 2 din x mov [di].transporturile intre diverse pozitii (cifre in baza 2^32) putea fi salvat/ recuperat prin stiva (noi l-am salvat/recuperat prin locatia destinatie x).edx .EAX=fffffffeh + 00000002h = 00000000h + 1(pus in CF) adc edx.salvez ult.salvez transportul din poz.code start: mov ax.00000000h . 1 in poz. EDX (acesti reg. b. 3 din x . EAX=20000000h mov x. va fi in x si rezervam 3 dword .eax .EDX=00000002h. [x+4]..

00000000h mov [di].16 .4 add di.@stack".stack .incarc vechea parte hi a lui EDX (devenita acum low) shr edx. Watch)) . stivei este vechiul EDX. aceste instructiuni nu au operanzi si nu afecteaza flagurile: CBW CWD .acum in vf.ax mov al. de acolo) atentie insa ca la inceputul programului sa initializam si SS (cu "mov ax.ax").eax cu sevcenta: add si. Registers) ~~~~~~~~~~~ x.4 [di]. putem folosi urmatoarele instructiuni de extindere a unui intreg cu semn la o dimensiune mai mare (practic se propaga bitul de semn).vreau sa fac y:=b*c (cu semn) .AX=0001h (b7 din AL a fost 0) mul c .4 ror edx. interschimba primii 16 cu ultimii 16 biti push dx .code start: mov ax.4 di.386 .deplasez bitii din EDX spre dreapta (vezi mai incolo) cu 16 push dx .sp add eax.16 . dword ptr [si] b eax.model small .incarc vechea parte low a lui EDX .practic se . Daca vrem sa facem o inmultire/impartire cu semn dar dim.efect: b7 din AL se propaga in cei 8 biti din AH .dword ptr [di] edx.EAX=AX*c . caci imi trebuie val. "mov ss.vreau sa fac x:=a*c (fara semn) y dd ? .add add mov mov mul add adc mov si.data a db 01h b db 0f1h c dw 0002h x dd ? . dword ptr [si] mul b mov bx. dword ptr [bx] .scot dwordul din stiva pop ax .rotim bitii din EDX cu 16 (vezi mai incolo) .AL=01h cbw .nu putem adresa bazat/indexat direct cu SP adc edx.edx eax. in little endian mov eax.eax pop ax .00000000h [di]. operanzilor nu se potrivesc.efect: b15 din AX se propaga in cei 16 biti din DX Exemplul 5: (la rularea cu TD se vor urmari AX (in fer.@data mov ds. y. (nu pot scoate in DX. EAX (in fer.a .

logica spre raguri mici (spre dreapta).completeaza in stanga cu bitul de semn (deplasat spre dr. rotiri: Instructiunile de shiftare (deplasare) translateaza bitii din locatia unei destinatii "dest" (registru sau din memorie) cu un numar "depl" (constanta byte sau CL) pozitii.completeaza in dreapta cu 0.executam mai multe instructiuni. in ordinea in care sunt incuibate unele in altele. .depl.b . unii biti parasesc locatia "dest"(si se pierd) iar ult.) . daca raportul dimensiunilor este mai mare. ca in penultimul exemplu.a se vedea exercitiile de la sfarsit. Registers)) ~~~~~~~~~~~ . aritmetice de mai sus putem face calcule elementare (o singura op. daca vrem sa evaluam expresii mai complexe.1 .depl. depl . Cu instr.EAX=AX*c mov y. care este 0) shl al.2 sar al.stack . depl .eax mov ax.aritmetica spre raguri mici (spre dreapta). instructiunile sunt: X XXUXX SHL dest.cl .atunci fac succesiv "CBW" si "CWD". .data .code start: mov al. depl SAR dest.1 . shiftari.depl.deci difera de SHR Exemplul 6: (la rularea cu TD se va urmari AL (in fer.AX=fff1h (b7 din AL a fost 1) imul c . . afecteaza ODITSZAPC.completeaza in dreapta cu 0 SAL dest.AL=00011100b (s-a propagat bitul de semn. 4 (byte si dword) . salvand rezultatele partiale de exemplu in stiva .completeaza in stanga cu 0 .11100111b shr al.AL=01110011b (s-a propagat 0) mov cl. le evaluam treptat .eax mov al.AL=11000000b (s-a completat in stanga cu 0) .practic e la fel ca SHL SHR dest.aritmetica spre raguri mari (spre stanga). care evalueaza expresiile elementare componente.AL=f1h cbw . 5) Instructiuni aritmetice pentru numere in virgula mobila .AL=11100000b (s-a completat in stanga cu 0) sal al. .depl.4c00h int 21h end start Procedand ca mai sus pot inmulti/imparti operanzi ai caror dimensiuni sunt in raport de max.TODO 6) Instructiuni logice.logica spre raguri mari (spre stanga). .3 .model small . depl . matematica/instructiune).mov x. putem inmulti/imparti pe bucati. care a iesit din locatie e pastrat in CF.

4ch int 21h end start . --> d.) si apoi CF. ultimul bit care a iesit din locatie e pastrat si in CF.ult. (RCR cu 3): CF=x. depl ROR dest.. . RCR).IMUL.. bagat 1 & 0101.. .DIV. . depl RCR dest.AL=01011111b. depl .. pastrat 1) rcr al. bit ce a iesit . (ROR cu 3): .. . . prin dr.abc.AL=11111000b (s-a propagat bitul de semn. Registers)) ~~~~~~~~~~~ . intra prin stg.ex. . bit iesit prin dr. CF=0 ror al.2 .ult. prin stg.code start: mov al. depl Exemplul 7: (la rularea cu TD se va urmari AL si CF (in fer.0) mov ah.. CF=b . afecteaza ODITSZAPC.model small .data .ex. care este 1) Shiftarile echivaleaza cu inmultiri/impartiri cu puteri ale lui 2.rotire spre raguri mari cu carry (spre stanga cu carry).a CF=b RCL dest.8 . dar care se fac mai rapid ca MUL.abcd --> bcd. ..sar al.rotire spre raguri mici cu carry (spre dreapta cu carry). intra primii depl-1 biti ce ies prin dr.ex. aceeasi ord.IDIV.rotire spre raguri mici (spre dreapta). (RCL cu 3): CF=x. CF=1 (scos 11.ex.. in aceeasi ordine. (ROL cu 3): abcd. CF devine ult. .CF=0 rcl al. CF=c . --> d.. ..6 .xab..prin dreapta intra CF si apoi primii depl-1 biti ce ies . e pastrat si in CF.11100111b rol al.. bit ce a iesit prin stg.prin stg.bitii ce ies prin dr. CF=1 clc . CF devine ult.stack . "ROR" pot interschimba cele doua jumatati ale config.5 . e pastrat si in CF.bitii ce ies prin stg. de biti a destinatiei. .AL=11100101b..AL=11111001b.abcd --> xcd. bagat 0 & 1. pastr. . CF=0 (scos 00101. (in . in aceeasi ordine. abcd. Instructiunile de rotire translateaza bitii din locatia unei destinatii "dest" (registru sau din memorie) cu un numar "depl" (constanta byte sau CL) pozitii. instructiunile sunt: X X ROL dest.rotire spre raguri mari (spre stanga).interschimba continutul lui AL cu AH ... biti care parasesc locatia "dest" printr-o parte intra in locatia lui "dest" prin cealalta parte.a. CF=c . in aceeasi ordine (impreuna cu CF la RCL.4ch int 21h end start Cu "ROL".3 mov ah....4 . bit iesit prin stg. exemplu: rol ax.. intra prin dr.AL=01111110b.

data a db 00110000b . (i.AL=00010000b mov al.face .complement fata de 1) tablele operatiilor pe biti: x | y | x and y | x or y | x xor y ---------------------------------0 | 0 | 0 | 0 | 0 0 | 1 | 0 | 1 | 1 1 | 0 | 0 | 1 | 1 1 | 1 | 1 | 1 | 0 x | not x --------0 | 1 1 | 0 Obs: "NOT" nu afecteaza PF. sursa".d s.Instructiunea "RCL dest.1" are efectul dest := dest*2+CF. nu o shiftare) este propus ca exercitiu la sfarsit. Similar "RCR dest.AL=11001111b mov al.1" permite shiftarea la dreapta (i. injumatatirea) rapida a unei valori multioctet. Exemplul 8: (la rularea cu TD se vor urmari AL. sunt: 0 XXUX0 AND OR xOR NOT s. de 0 au aceeasi paritate (iar"NOT"interschimba 1 cu 0).bl .d d . bitul care a iesit din primul octet). BL (in fer. de 1 si nr. operanzii nu pot fi ambii din memorie si trebuie sa aibe aceeasi dimensiune. deoarece "destinatie" are un nr.d s. Instructiunile logice sunt de forma "mnemonic destinatie. Registers)) ~~~~~~~~~~~ . dublam) rapid o valoarea multioctet: facem "RCL" cu 1 la primul octet.stack .bl .e.4ch int 21h end start Instructiunile logice pot fi folosite pentru diverse artificii (castigam viteza la executie). acest lucru ne permite sa shiftam la stg.a xor al. "sursa" poate fi imediat.face . i. registru sau memorie.a and al. par de pozitii.01010000b mov al. apoi la al doilea (si in el va intra.a or al. ca de exemplu: .code start: mov ax. deci nr.a not al . sau "mnemonic destinatie" unde "destinatie" poate fi registru sau din memorie.e. Un program de acest tip (dar care cere o rotire la stanga.face [s] [s] [s] [d] := := := := [s] [s] [s] not and [d] (conjunctie bit cu bit) or [d] (disjunctie bit cu bit) xor [d] (disjunctie exclusiva bit cu bit) [d] (neaga fiecare bit.e.AL=01110000b mov al.ax mov bl. etc.AL=01100000b mov ah.@data mov ds.model small .bl .face . afecteaza ODITSZAPC instr. prin intermediul CF.

deci CF=1.stergerea continutului unui registru: xor ax. opd2 .AL=01010101b.bitul 2 din AH devine 0.setarea/stergerea/inversarea unor biti/flaguri: lahf . etc. 7) Instructiuni de comparatie: CMP opd1. dar acum CF=0. etc. nu salveaza rezultatul.AL=11111010b .0f0h al."AND" poate fi folosit pt..11111011b . si modifica flagurile ca la ADC: ODITSZAPC X XXXXX TEST opd1.AL=11111111b (am (am (am (am sters sters setat setat bitii de rang par) tetrada superioara a lui AL) tetrada superioara a lui AL) bitii de rang par) mov al.vrem CF=0 caci n-am facut inca nici o prelucrare.al . este negativ and al. s-a schimbat AF:=1. opd1=opd2. de ex.AL=10101010b .0ffh.incarc flagurile in AH or ah. registru.acelasi efect . face CF=0.AX:=0000h . opd2 ."MOV" nu modif.bitul 4 din AH devine 1. logice si shiftari (a se vedea exercitiile de la sfarsit). fata de situatia initiala . ZF=1 ("MOV" nu afecteaza flagurile) . SF=0 mov al. si modifica flagurile ca la AND: ODITSZAPC 0 XXUX0 Operanzii trebuie sa aibe aceeasi dimensiune.00010000b .): Jxx adr . ca la "CMP" rezulta config.0fh al.0ffh al. efect echivalent cu "not al" xor al. ca intreg cu semn. restul raman la fel sahf .AL nu isi schimba valoarea. efect echiv. 8) Instructiuni de salt: Au forma urmatoare ("xx" este un sufix al mnemonicului iar "adr" o adresa (offset) ce poate fi imediat.al .AL=10101010b xor al. restul raman la fel and ah. cu "mov al.AL=11111111b .salvez AH in flaguri.55h . nu salveaza rezultatul.calc.AL=00000000b. SF=0.efect: testeaza flagurile si daca au o anumita configuratie.Al=00001010b . stergerea CF si actualizarea SF: . Obs.0aah . iar b7 este 1) and al. .simularea adunarii si inmultirii folosind op. diferite de flaguri daca opd1<opd2. (operatia nu a provocat transport din b7.0f1h. SF=1 . reflecte faptul ca AL.0ffh .presupunem ca initial CF=1. nu pot fi ambii din memorie iar opd1 nu poate fi imediat. opd1 AND opd2.0".0aah al. . dar in plus . flagurile. iar SF sa . PF:=0 mov and and or or al.calculeaza opd1-opd2.ax .

JNLE (vedem (below/not above or equal): sare daca opd1 < opd2 ca valori fara semn (below or equal/not above): sare daca opd1 <= opd2 ca valori fara (above or equal/not below): sare daca opd1 >= opd2 ca valori fara (above/not below or equal): sare daca opd1 > opd2 ca valori fara semn ca "A" (above) si "B" (below) sunt folosite la compararea fara semn) (less/not greater or equal): sare daca opd1 < opd2 ca valori cu semn (less or equal/not greater): sare daca opd1 <= opd2 ca valori cu semn (greater or equal/not less): sare daca opd1 >= opd2 ca valori cu semn (greater/not less or equal): sare daca opd1 > opd2 ca valori cu semn ca "G" (greater) si "L" (less) sunt folosite la compararea cu semn) JE.10000010b mov bl.JNB semn JA.opd2 Jxx adr atunci in functie de "xx" avem: JB. (offsetul) "adr" in cadrul segmentului de cod curent..SF=1.00000001b cmp al. mai exact daca executam succesiunea: CMP opd1. . flagurilor pentru care se face saltul sunt: JA/JNBE JAE/JNB JB/JNAE JBE/JNA : : : : CF=0 sau ZF=0 CF=0 CF=1 CF=1 sau ZF=1 JG/JNLE JGE/JNL JL/JNGE JLE/JNG : : : : ZF=0 sau SF=OF SF=OF SF<>OF ZF=1 sau SF<>OF JNS : SF=0 JCXZ : (CX)=0 JE/JZ : ZF=1 JNE/JNZ : ZF=0 JP/JPE : PF=1 JNP/JPO : PF=0 JO : OF=1 JNO : OF=0 JMP : este un salt neconditionat Conditiile de salt pt. .JNAE JBE. se executa IP := IP+depl. . "Jxx" sunt in concordanta cu rezultatele posibile la "CMP".nu sare.instructiunea de efect nul (nu afect.bl . se sare cu executia la adresa .PF=1. deoarece nu avem al<bl ca numere fara semn (128 >= 1) .JNG JGE.OF=0 jl et1 .JNA semn JAE.JNZ (not equal/not zero): sare daca opd1 <> opd2 De exemplu: mov al. (vezi mai jos) poate face si salturi mai mari Variantele de "Jxx" si config. am pus-o de umplutura et1: jb et2 .sare.JNBE (vedem JL. corespunzatoare lui "xx".diferenta al-bl este 10000001 si rezulta: CF=0. dealtfel vedem ca nu avem CF=1 (conditia de salt la jb) nop .. deoarece al<bl ca numere cu semn (-126 < 1) .practic.trebuie insa ca "depl" sa fie intre -128. exceptie: "jmp" . dealtfel vedem ca SF<>OF (conditia de salt la jl) nop .JNGE JLE.127.JNL JG. dintre "adr" si offsetul instructiunii urmatoare lui "Jxx".JZ (equal/zero): sare daca opd1 = opd2 JNE.nici flagurile). unde "depl" este diferenta .

. Varianta din dreapta este mai buna in cazurile in care ramurile then sau else sunt prea mari (>128 octeti) si nu se poate sari peste ele cu instructiuni de salt conditionat ("Jxx" altele decat "JMP"). iar aceasta va fi valoarea lui "depl" (valoarea care se aduna la IP). ramura else jmp sfarsit et: .code start: mov ax.c ... in memorie cmp ax. la intalnirea instructiunii "jl et1" compilatorul calculeaza diferenta intre offsetul desemnat de "et1" si offsetul instructiunii urmatoare lui "jl et1".) jxx et1 jmp et2 et1: . analog la "jb et2".bx jb e1 ..ax mov ax.copiem variabilele in registri mov bx.acum stim b<=a jb e2 . in timp ca la "JMP" el poate fi dat si printr-un registru de 16 biti sau printr-o locatie de memorie de 16 biti.et2: nop Etichetele "et1" si "et2" sunt inlocuite la compilare cu adresele (offsetul) instructiunilor care le urmeaza. caci nu putem face CMP cu ambii operanzi mov cx. iar peste ramurile then sau else sare cu "JMP". care poate face si salturi mai mari. b.stack . varianta din dreapta face salturi conditionate mici. Notam ca la instructiunile de salt conditionat ("Jxx" altele decat "JMP") operandul "adr" trebuie sa fie o eticheta din program. etc.model small . lizibilitate): . a.sare daca a<c mov x. c (am indentat pt.. etc. ramura then sfarsit: ..c<=a jmp sfarsit e2: .. ramura else sfarsit: . dintre 3 valori fara ~~~~~~~~~~~ semn stocate in var.a .adica if xx then goto et . ramura then jmp sfarsit et2: .. Putem simula instructiune structurata if-then-else astfel: cmp (sau test. cmp (sau test.sare daca a<b cmp ax..@data mov ds.data a dw 3 b dw 5 c dw 2 x dw ? ..acum stim b<=a.ax ..cx ..) jxx et .b . Exemplul 9: program care pune intr-o variabila x max.

cand au deventi egale.aici X:=2d (adica cmmdc(4d.4c00h int 21h end start (la rularea cu TD se vor urmari a.@data mov ds.a mov bx.cx . c. 03h .aici ajungem daca AX=BX mov x. ~~~~~~~~~~~~ scad pe cel mic din cel mare. x (in fereastra Watch). 20h.b inceput: cmp ax.cx .bx .acum stim a<b jb e3 . BX.acum stim a<b.la compilare "a" se inloc. AX. cu offsetul sau 0003h .stack .mov x. Exemplul 10: Algoritmul lui Euclid cu diferente (cat timp nr. BX (in fereastra Registers)). 30h .model small . sunt diferite.stack .data a db 01h.jump-urile nu modifica flagurile.4ch int 21h end start (la rularea cu TD se vor urmari a.ax .acum stim b<=a<c jmp sfarsit e1: cmp bx.6d)) mov ah. valoarea comuna este cmmdc numerelor initiale): . AX.acum stim a<b<c sfarsit: mov ax. Exemplul 11: Suma a doi vectori: ~~~~~~~~~~~~ .aici ajungem daca AX<BX jmp inceput ab: . b.ax mov ax. b.cx . cu offsetul sau 0000h b db 10h.aici ajungem daca AX>BX sub ax.bx jmp inceput egale: .la compilare "b" se inloc.deci ele au ramas ca dupa"CMP" sub bx. 02h.c<=b jmp sfarsit e3: mov x.bx je egale ja ab .sare daca b<c mov x.code start: mov ax. x (in fereastra Watch). CX (in fereastra Registers)).ax .data a dw 4d b dw 6d x dw ? .model small .

acum x: 11h 22h 33h (la rularea cu TD se vor urmari in fer. b. Registers: AL.model small .[si+b] mov [si+x].code start: mov ax. 08h.x db ?. matematic.al inc si jmp inceput sfarsit: nop mov ah.ax . din care sarim la inceputul ciclului).dpv.ax mov bx. 02h.cand "a" apare intre [] inseamna constanta adresa 0000h . 05h. [b+2]. 3x3. for.ch cbw . [b+1].cl mul nlin mov si.3 jae sfarsit mov al.cand "b" apare intre [] inseamna constanta adresa 0003h . 04h.0 inceput: cmp si. Watch: a.numaram liniile cu CL linie: mov ch.la compilare "x" se inloc.ax .ch mul nlin . implementarile nu sunt insa fidele (de ex. 09h . in ciclul while de la penultimul exemplu avem doua pct. iar in fer. [x+2]. [x+1].code start: mov ax.acum SI=offsetul liniei de indice CL mov al.nr.cand "x" apare intre [] inseamna constanta adresa 0006h .stack .@data mov ds. [a+1]. putem realiza insa si implementari fidele (este un exercitiu la sfarsit).numaram coloanele cu CH coloana: mov al. x.acum SI=offsetul elementului a[CL][CH] in locatia matricii mov al.acum AX=CH (indicele coloanei) scris ca word add si. 4 5 6 . 03h. ? . de coloane a db 01h.@data mov ds. [a+2]. 07h.0 .[si+a] add al.nr. while. 06h. matricea este: 1 2 3 .ax mov si. 7 8 9 . de linii ncol db 3 . ?. Exemplul 12: Transpunerea unei matrici liniarizate: ~~~~~~~~~~~~ . cu offsetul sau 0006h . una dupa alta .offset a mov cl. Ultimele trei exemple sunt si implementari ale unor structuri de tip if-else.matr.initializez contorul cu care vom numara iteratiile .data nlin db 3 .0 .4ch int 21h end start . SI). cu liniile stocate in mem.

et1 .acum DI=offsetul elementului a[CH][CL] in locatia matricii mov al.se sare peste asta et1: jmp [x] nop . .trec la coloana urmatoare cmp ch. fara a imparti prelucrarea pe linii si coloane. "j" in loc de CL.[bx+di] .cl jb coloana inc cl .acum "a" are in locatie: 01h 04h 07h 02h 05h 08h 03h 06h 09h . puteam de asemenea folosi artificii pt. CH.code start: mov ax.mov di. a aduna doua matrici e suf.interschimb AL cu a[CH][CL] mov [bx+si].offset et2 mov y.@data mov ds. .. 2 5 8 . Registers: CL.[bx+si] .a[CL][CH]:=AL inc ch .pt.se sare peste asta et3: mov ah.ax lea ax.nlin jb linie .stack .deci salt la adr. Watches: a.se sare peste asta et2: jmp [BX] .acum DI=offsetul liniei de indice CH mov al. offset y jmp ax nop . CH.adica este matricea: 1 4 7 .AL:=a[CL][CH] xchg al.model small .4ch int 21h end start . offset et1" mov x. [a+1].data x dw ? y dw ? .acum AX=CL scris ca word add di..ax .la rularea cu TD vom urmari in fer. ce arata ca operandul unui "JMP" poate fi si registru ~~~~~~~~~~~~ sau din memorie . SI..4ch int 21h end start Comentarii: .echivalent cu "mov ax. . sa parcurgem locatia lor ca pe un vector (cu un singur indice).puteam sa indexam cu doua variabile "i". Exemplul 13: Ex.trec la linia urmatoare cmp cl.ax .cl cbw . 3 6 9 mov ah. a face programul mai rapid.offset et3 mov bx.al . stocata in BX nop . la adr. stocata in mem. [a+8] iar in fer. DI.

caci dupa saltul inapoi executia ajunge la un mom.0 .initializez contorul cu nr.code start: mov ax.al . dat iar la "LOOPxx".la compilare "a" se inloc.[si+a] . CX cu 1 si daca obt. apoi deoarece este <> 0 se sare. ?.initializez indicele in vectori inceput: mov al. "LOOPxx". cu offsetul sau 0000h b db 10h. 03h .daca "adr" este inainte (avem "depl" pozitiv).stack .decrem. acest curs al executiei poate fi schimbat de prezenta altor "Jxx". nu afecteaza flagurile si sunt de forma urmatoare (unde "adr" este ca la "Jxx" conditionate.3 . 02h. ? .subliniem ca testul (CX)<>0 se face DUPA ce s-a decrementat CX (iar decrementarea ramane facuta chiar daca in urma testarii conditiei nu se face saltul). cu offsetul sau 0003h x db ?.model small .) . cu offsetul sau 0006h .decrem. Registers: CX. iteratiilor de efectuat mov si. 30h . varianta cu "LOOP": ~~~~~~~~~~~~ . Exemplul 14: Suma a doi vectori. (Cx)<>0 si ZF=0 se sare la "adr" .idem Observatii: . deci trebuie sa avem "depl" intre -128.decrem. [x+2] iar in fer.cand "a" apare intre [] inseamna constanta adresa 0000h add al. in particular la LOOP daca initial (CX)=0. atunci nu avem un ciclu ci doar un salt conditionat (doar daca "adr" este inapoia lui "LOOPxx" are loc ciclarea.128): LOOP adr LOOPZ adr LOOPE adr LOOPNZ adr LOOPNE adr .(la rularea cu TD se va urmari la care/peste care linii sare indicatorul instructiunii curente .. iar salt.acum x: 11h 22h 33h mov ah.evident. CX si devine ffffh. 20h.va sari "NOP"-urile. semn ca s-au executat acele "JMP"). .4ch int 21h end start (la rularea cu TD se vor urmari in fer. etc. intai se decrem. . cu test la sfarsit. (Cx)<>0 si ZF=1 se sare la "adr" .[si+b] .la compilare "b" se inloc.cand "b" apare intre [] inseamna constanta adresa 0003h mov [si+x]. 9) Instructiuni de ciclare: Implementeaza structuri de ciclare de tip "for".data a db 01h.cand "x" apare intre [] inseamna constanta adresa 0006h inc si loop inceput .@data mov ds. AL).idem . SI. (Cx)<>0 se sare la "adr" .la compilare "x" se inloc. CX cu 1 si daca obt. Watches: x. CX cu 1 si daca obt.ax mov cx. [x+1].

acum SI este indicele primei aparitii a caracterului in sir.n et1: loop et2 jmp et3 et2: . segment. iar offsetul aparitiei este SI + offsetul lui s. 10) Instructiuni pentru stringuri: Toate instr. de iteratii ce trebuie efectuate + 1 Putem face ciclari numarate de CX si cu "inc cx". sensul de parcurgere a sirurilor este dat de flagul DF si este spre adrese mari (SI.0ffffh inceput: inc si .stack . .'c') sau dupa term.sirului . dar trebuie indicat explicit. Watches: [byte ptr si+s].data s db "abcaabc" c db 'c' . SI. pt.la prima incrementare SI devine 0000h cmp al.CX = lung.. jmp et1 et3: .code start: mov ax. Exemplul 15: Cautarea unui caracter intr-un string: ~~~~~~~~~~~~ .e.offset c sub cx.. iar in fer. sirul sursa se poate folosi si un alt reg. siruri considera implicit ca sirul sursa este pointat de DS:SI.a lui AL(i.4ch int 21h end start (la rularea cu TD se va urmari in fer.. ca ciclul "for" simulat de "LOOP" are testul la sfarsit si nu acopera cazul general cand nr.DI cresc) daca DF=0 si spre adrese mici daca DF=1. Registers: CX.Obs.offset s . "dec cx". iar sirul destinatie de ES:DI. Putem simula un ciclu "for" cu test la inceput astfel (dar atunci saltul este inainte si nu "LOOP" are rolul esential in ciclare ci un "JMP" pus la sfarsit): mov cx.instructiunile nu au operanzi si au forma: mnemonic . adica 2. pt.c mov si.ax mov cx.. "jcxz et". AL).ies la prima intaln. de iteratii poate fi si 0 (el face macar o iteratie). adica 0 + 2 = 2 mov ah.n = nr.@data mov ds.model small . .sirului = 7 mov al.[si+s] loopne inceput .

-1/-2/-4 (in functie de DF).nu modifica flagurile LODSB/LODSW/LODSD . nu de "prefix". nu se face nici o iteratie. si seteaza corespunzator flagurile: ODITSZAPC apoi . dupa fiecare rep. iar la sfarsitul fiecarei iteratii se testeaza conditia ref. . X XXXXX . dupa fiecare rep. modifica SI si DI cu 1/2/4. resp.modifica DI cu 1/2/4. "mnemonic". . modifica DI cu 1/2/4.repeta pana cand (CX)=0 sau ZF=1. doar de executarea instr.nu modifica flagurile STOSB/STOSW/STOSD . apoi . CX initial este nr. de iteratii pe care isi propune sa-l faca "REPxx". X XXXXX . "prefix" poate fi: REP REPZ/REPE . resp. test. instr. . -1/-2/-4 (in functie de DF). "CMP" (deci face sursa-destinatie fara a salva rezultatul) . modifica SI cu 1/2/4.modifica SI si DI cu 1/2/4. flagurile sunt modif. Exemplul 16: ~~~~~~~~~~~~ . Practic. -1/-2/-4 (in functie de DF).repeta pana cand (CX)=0.sau prefix mnemonic unde "mnemonic" indica operatia efectuata iar "prefix" indica faptul ca operatia respectiva se va face repetat pana la indeplinirea unei conditii. si seteaza corespunzator flagurile: ODITSZAPC apoi . se decrementeaza CX cu 1 . daca insa de la bun inceput CX=0. -1/-2/-4 (in functie de DF). la ZF (in cazul REPZ/REPE/REPNZ/REPNE) si daca este satisfacuta se iese. apoi . dupa fiecare rep. .) . decrementare CX.transfera un octet/word/dword de la sursa la destinatie. -1/-2/-4 (in functie de DF). .destinatie fara a salva rezult. resp. . SCASB/SCASW/SCASD .compara octetul/wordul/dwordul de la sursa si destinatie ca la .nu modifica flagurile CMPSB/CMPSW/CMPSD . apoi . se decrementeaza CX cu 1 O iteratie decurge astfel: operatia "mnemonic". resp.compara AL/AX/EAX cu byteul/wordul/dwordul de la destinatie ca la instr. "mnemonic" poate fi: MOVSB/MOVSW/MOVSD .repeta pana cand (CX)=0 sau ZF=0. . resp.transfera un octet/word/dword din AL/AX/EAX la destinatie.transfera un octet/word/dwprd de la sursa in AL/AX/EAX. "CMP" (deci face AL/AX/EAX . se decrementeaza CX cu 1 REPNZ/REPNE .

inlocuim toate mov si.offset a . cu semn este egal cu ..operam pe acelasi string ca sursa si destinatie. 00h .mov ax.DF:=0 si astfel sirul se va parcurge spre adr. (deci acest nul se aloca) b db "abcef".merg pana parcurg toata lungimea lui "a" (CX devine 0) sau .di . mare.aflam prima pozitie unde difera "a" si "b" mov si.mov x.nul cld .1 .pozitionarea implicita a lui DS e tot pe segm.prima poz.x .. curent din "a" in AL si increm.sub ax.ax .avem un singur segm.in acel moment CX privit ca nr. este egal cu nul (din AL).ax mov es.stack . 00h oriunde va aparea in program. offsetul sau se pun in memorie 7 caractere: 'a'. inainte ca el sa atinga 0 .offset b mov cx..data nul equ 00h ."b" are offsetul 7 x dw ? .sir terminat cu caracterul nul (puteam pune si direct ". .offset a mov di.simbolul "nul" se va inlocui cu val.. gasesc o diferenta ("cmpsb" pune ZF:=0) .incarc oct.aflu lungimea lui "a" (un fel de "strlen" din lbj C) mov di.offset a mov cx.dec ax . SI . unde difera este la SI + offset a .@data mov ds.acum x = lungimea sirului "a" (fara nul) .. mari repnz scasb . nul . reamintim si ca DS are aici acelasi continut ca ES .0ffffh mov al.puteam afla acum lungimea sirului "a" si cu: .. .offset a mov di. va pune ZF:=1 si se va iesi.cx . de date mov ax. -lungimea sirului "a" (fara nul)-2 neg cx dec cx dec cx mov x."a" este prima variabila alocata (are deci offsetul 0).nul . 'f'. .x cld ciclu: lodsb literele mici din "a" cu litere mari .ax . . de date. iar de la .code start: assume es:@data . aici "nul" nu se aloca ca o variabila a db "abcdef"..lungimea lui "a" cld repz cmpsb .model small .lungimea lui "a" .offset a mov cx. .cum CX pleaca de la o val. 00h"). care va fi si sursa si destinatie . "scasb" va ajunge sa conchida ca octetul curent din sir .

cmp al.acum DI pointeaza '\' din "p" .di .offset f mov cx.exe".ext al fisierului.0ffffh std .daca oct.mare corespunzatoare e 20h stosb .nul mov ah.offset p mov al.data nul equ 00h p db "c:\borlandc\bin\tasm.x .stack .ax mov es. Regsters: CX. lit. .acum DI pointeaza ultimul caracter din "p" de dinainte de nul.acum "a" contine "ABCDEF".'a' jb altceva . [byte ptr si].numar in lungime si un nul mov si. adica (aici) 8 inc x .20h .) dintr-o cale completa ~~~~~~~~~~~~ . nul f db 100 dup(?) .copiez de la DI pana la nul (inclusiv) sub x.merg inapoi pana gasesc '\' mov x.'z' ja altceva . Exemplul 17: Identificarea numelui fisierului (cu ext. curent > 'z' atunci nu e litera mica sub al. DI. mici repnz scasb inc di .@data mov ds. AL iar in fer. . SI.0ffffh cld repnz scasb dec di dec di .'\' mov cx.curent din "a" si increm DI (acum SI=DI) altceva: loop ciclu .caut sfarsitul sirului "p" mov di.code start: assume es:@data mov ax.decrem.model small .fac DF:=1 ca sa se parcurga sirurile spre adr.daca oct.intotdeauna dif.acum x=lungimea numelui.4ch int 21h end start (la rularea cu TD urmarim in fer.ax . curent < 'a' atunci nu e litera mica cmp al. Watches: a. [byte ptr di]).acum SI pointeaza primul caracter de dupa '\' mov di.nul mov cx.buffer de 100 octeti neinitializati x dw ? .di inc si . CX si daca inca nu e 0 mai prelucrez un car.mica-lit.di mov al.AL in oct.salv.

4ch" apar in zona de cod 100 de instructiuni "nop". Registers AX.[byte ptr si-1].code org 100h start: mov ax. deci in total se vor executa doua "inc ax" si astfel AX va fi 2. si in final "mov ah.cld . apoi "nop"-urile ramase. Exemplul 18: Program care isi duplica o parte a sa.exe".4ch int 21h end start (la rularea cu TD se vor urmari in fer. DI iar in fer.offset et1 mov si. apoi copia lui "inc ax" de la inceputul lui "x".primele instructiuni "mov ax.ax mov ax. . "nop" intregi (caci fiecare are doar un octet). "nop" .. apoi executa noul cod: ~~~~~~~~~~~~ .offset et2 sub cx. [byte ptr di-2].model tiny . f. eventual se va urmari in fer."rep movsb" copiaza zona de cod dintre "et1" si "et2" (zona ce contine o instructiune "inc ax") de la offsetul "x".. "inc ax" (cel dintre "et1" si "et2").4ch int 21h end start Comentarii: . Watches: p.. deci AX este 2 mov ah. in plus. ea se aloca chiar in acel loc si astfel intre "rep movsb" si "mov ah.in ansamblu rularea va exec. "int 21h".la rularea cu TD se va urmari in fer.data . [byte ptr di+1]). "rep movsb". .cs mov ds. deci cand ajunge executia aici gaseste cod valid.offset et1 mov di.cand se ajunge aici s-au executat in total doua "inc ax".[byte ptr si].4ch".acum "f" contine "tasm. . nu exista riscul ca aceasta copie sa ajunga peste instructiunea "mov ah.nul mov ah. [byte ptr si-2].stack . deoarece "x" a fost initializata cu un numar suficient de mare de 90h-uri."90h" este codul unei instr. [byte ptr di-1].offset x rep movsb x db 100 dup(90h) . CPU (se deschide cu View/CPU) zona de cod si cum se inlocuieste primul "nop" cu copia lui "inc ax" (instr. .acum copiez spre dreapta rep movsb . SI. in urma suprascrierii primilor octeti de dupa "x" cu copia lui "inc ax" raman in continuare niste instr. [byte ptr di]."inc ax" are tot un singur octet).. Registers: AL.0 et1: inc ax et2: mov cx..4ch".ax mov es. x.."x" este o variabila declarata in segmentul de cod si initializata cu un numar de 90h-uri (codul lui "nop").cs". . .

dar cu alti parametri. La inceputul rularii programului DS si ES contin implicit adresa de segment a PSP (iar ulterior ii putem face sa pointeze zona de date cu instructiuni de forma "mov ax.@data". .).11) Accesarea argumentelor din linia de comanda: Stim ca un program se poate lansa de pe prompterul interpretorului de comenzi ("command.exe") pentru a fi executat. Eventualele redirectari incluse in ldc nu sunt considerate argumente (ele sunt tratate de interpretor si nu devin date de intrare ale prog. "mov ds. .txt > fis1. PSP contine diverse inf.prin ele putem transmite diverse date de intrare programului. stiva. Programul isi va copia mai intai coada ldc intr-un string din zona de date. printre care coada ldc (terminata cu un caracter CR.n.asm aici: .la offsetul 80h in PSP este un octet ce contine lungimea cozii ldc (in care nu se numara si CR de la sfarsit).txt". "ldc").asm" este linia de comada (presc."/zi" si "fis. Pt. Exemplul 19: Program care isi afisaza coada ldc. ii aloca o zona de memorie ce contine la inceput un preambul de 256 (100h) octeti numit PSP ("program segment prefix") si in continuare imaginea din memorie a programului (cu zona cod. Ne punem problema cum putem accesa dintr-un program asm argumentele in ldc cu care a fost lansat (dintr-un prog. apoi fiecare argument in ~~~~~~~~~~~~ parte.asm" sunt argumentele in ldc (siruri maximale de caractere nealbe. "argv"). Cand sistemul incarca un program (indiferent daca este ". anume: AH = DS = DX = apoi 9 (functia "display string" a intreruperii 21h) adr. . . de exemplu in ldc: c:\work>type fis. lansat). numiti de regula "argc". 0dh) si lungimea ei.com" sau ". separate prin caractere albe). cu tot cu CR de la sfarsit (deci pe o lungime de max. Recomandam ca programatorul sa copieze coada ldc din PSP intr-un string alocat in zona de date a programului iar eventualele prelucrari ulterioare ale argumentelor sa le faca plecand de la acest string. de exemplu: c:\work>c:\borlandc\bin\tasm /zi fis. de segment a stringului afisat offsetul stringului afisat (in segmentul sau) apelam "int 21h" .de la offsetul 81h la offsetul 0ffh in PSP este stocata coada ldc."c:\borlandc\bin\tasm" este specificatorul programului lansat. afisare vom folosi tot intreruperea 21h. ca de regula incepe cu un blank).txt singurul argument este "fis. 127 octeti).sirul " /zi fis. Mai exact: .com") cu argumente in linia de comanda . etc.asm" (obtinut din ldc prin eliminarea specificatorului prog. C se pot accesa cu ajutorul primilor 2 parametri ai lui "main". resp. asociate de sistem procesului respectiv (rularii respective a programului). "coada" ldc (si obs.ax"). de date statice. avand codul ASCII 13d. apoi iterativ va copia de aici cate un argument in alt string si-l va afisa. executat) s."c:\borlandc\bin\tasm /zi fis.

copiez coada ldc (fara <CR>) in stringul "ldc" mov byte ptr es:[di].copiez iterativ cate un argument din "ldc" in "buff" si-l afisez lea si.data seg_psp dw ? ldc_n dw ? ldc db 127 dup(?) . acum DS:SI pointeaza coada ldc din PSP lea di. a inceput un argument si-l copiem in "buff" stosb lodsb cmp al.' ' je et cmp al.copiez "ldc" in "buff" si pun <CR><LF>'$' la sfarsitul copiei (in loc de 0) mov cx.81h .ds:[80h] .13 .event. adaug un caracter 0 la sfarsitul stringului "ldc" mov es:[seg_psp].0 je et2 jmp et1 et2: .ldc .' ' je et2 cmp al.ldc_n lea si.stack . acest '$' nu va fi afisat.0 mov es:[ldc_n].model small .0 .ldc lea di. acum ES:DI pointeaza stringul "ldc" din zona de date rep movsb .a PSP) pt. eventuale alte folosiri mov si.buff . s-a terminat un argument si-l afisam (din "buff") . DS pointeaza deja segmentul lui "buff" mov ah.'$' stosb . . acum ES pointeaza datele.Stringul de afisat trebuie sa se termine cu '$' (afisarea caracterelor va incepe de la adresa DS:DX si se va opri la intalnirea primului '$'). sa incapa ldc fara <CR>. lungimea cozii ldc (fara CR de la sfarsit) mov ch. acum si DS pointeaza datele .ds .afisez "buff" (care acum contine coada ldc. salv.buff et: lodsb cmp al. dar cu un 0 adaugat de noi buff db 1000 dup (?) .cx .DS (adr.de seg.ax .@data mov es. dar DS inca pointeaza PSP mov cl.ldc lea di.buff rep movsb mov al. caracterul <LF> stosb mov al. alte folosiri mov ds. caracterul <CR> stosb mov al.terminata cu '$' in loc de <CR>) lea dx.0 je sf et1: .ax .10 .code start: mov ax.9 int 21h . salvam lungimea cozii ldc pt.

1992 Borland International Assembling file: Error messages: Warning messages: Passes: Remaining memory: 1.4ch int 21h end start Comentarii: .13 stosb mov al. fara sa-l incarcam in TD.i.buff int 21h lea di. .inainte de a initializa DS cu val.obj Turbo Link Version 5.asm None None 1 455k C:\WORK>c:\borlandc\bin\tlink prog.asm Turbo Assembler Version 3. pentru aceasta incarcam programul in TD normal.10 stosb mov al. in total vom vedea pe ecran ceva de tipul: C:\WORK>c:\borlandc\bin\tasm prog.mov al. .1 Copyright (c) 1992 Borland International C:\WORK>prog.si din TD putem rula programul cu argumente in linia de comanda. care formeaza capul de linie in MS-DOS. sa le identifice corect oricum).9 lea dx.'$' stosb mov ah. segment. anume ES.. dar acesta inca nu pointa segmentul de date.buff jmp et sf: mov ah. apoi rulam ca de obicei.la sfarsitul sirurilor afisate am adaugat caracterele <CR> (cod ASCII 13d) si <LF> (cod ASCII 10d). ca in linia de comanda putem lasa oricate blank-uri intre argumente (programul de mai sus este facut a.". compilatorul ar fi folosit implicit DS. putem vedea rezultatele afisate in diverse momente vizualizand ecranul utilizatorului cu Alt-F5 (sau din meniul "Window/User Screen").exe a a bb ccc a bb ccc C:\WORK>_ obs. daca nu asi fi precizat reg. intr-adevar. bb ccc . lui "@data" a trebuit sa accesez variabilele "ldc_n" si "seg_psp" declarate in segmentul de date cu precizarea explicita a registrului segment.. fara ele nu s-ar fi trecut la linie noua intre afisari (totul s-ar fi afisat pe o singura linie). .1 Copyright (c) 1988. linkedita si rula programul direct de pe prompter. apoi setam argumentele din meniul "Run/Arguments. din care revenim cu orice tasta.putem compila.

t2:=1. raspunsul va fi stocat intr-o variabila x de tip byte sub forma 0=neprim.. In program vor fi declarate doar variabilele n (cu initializare) si z. orice n>=3)..5 puncte) (*) La fel ca la problema II. II.4.1) (cate 1 punct pentru fiecare structura simulata) Scrieti programe demonstrative in care sunt simulate cu "CMP" si "Jxx" structurile de control while.5 puncte) (*) Program pentru calcularea celui de-al n-lea termen al sirului lui Fibonacci (t1:=1.z declarate in program si nu se va folosi stiva.4) (2. . Variabila n va fi folosita doar pentru a da si eventual numara iteratiile iar variabila z doar pentru a pune in ea la sfarsit termenul cerut (toti termenii intermediari vor fi stocati in stiva). [byte ptr SI+1]. Numarul este dat intr-o variabila n de tip word declarata cu initializare in program.7) (3 puncte) Program care calculeaza suma divizorilor unui numar natural.z. [byte ptr DI-1].5) (2.3) (3 puncte) (*) Program pentru calcularea z:=cmmdc(x.8) (3 puncte) (*) Program care calculeaza suma cifrelor in baza 10 ale unui numar natural. Registers vom urmari: CX. [byte ptr DI]. in fer.z variabile byte declarate in program. repeat (din lbj. In plus. [byte ptr SI-1]. switch (din lbj. lui Euclid cu impartiri (in final Se va verifica CU TD ca z=2). Numarul este dat intr-o variabila n de tip word declarata cu initializare in program. II.la rularea cu TD putem seta de ex. resp. Numarul este dat intr-o variabila n de tip word declarata cu initializare in program. dar pentru calcularea termenilor se va folosi stiva. do (din lbj.2) (2. C). Numarul n este dat printr-o variabila declarata cu initializare in program. II.y initializate la declarare cu 4.y) (x. II. argumentele (din "Run/Arguments. suma va fi stocata in final intr-o variabila s de tip word. 6) folosind alg. II. II. x. pentru calcularea termenilor se vor folosi maxim trei alte variabile x. pt. tn:=t(n-1)+t(n-2).y. C) resp.") la "a bb ccc". Pascal). case (din lbj. ldc. Exercitii: ---------In general programele se vor rula cu TD. In final valoarea ceruta va fi stocata in z. Watches vom urmari: ldc_n. cele referitoare la argumente in linia de comanda se vor lansa de pe prompter (cu argumente).y.5 puncte) (*) Program de ordonare a trei variabile byte x. suma va fi stocata in final intr-o variabila s de tip word. declarate cu initializare in program (in final Se va verifica CU TD ca x<=y<=z). 1=prim. Variabilele vor fi de tip word..6) (3 puncte) (*) Program care verifica daca un numar natural este prim. Programele marcate cu (*) se vor realiza in clasa. AL iar in fer.y. II. Pascal). buff. [byte ptr SI]. [byte ptr DI+1]. II.

d. 4. calculez suma lor si push aceasta suma (acum stiva contine valoare primei paranteze. adica: 25. sub forma a doua variabile a. Pentru stocarea rezultatului se va declara o variabila c de tip byte urmata de 5 octeti neinitializati. 5) (g) la fel ca (e) (acum stiva contine val. factorialul va fi stocata in final intr-o variabila s de tip word. 3. Numarul este dat intr-o variabila n de tip word declarata cu initializare in program.c.. Se va folosi urmatorul algoritm: (a) push a.5 puncte) (*) Program care calculeaza factorialul unui numar natural. Numarul de bytes (5) va fi dat intr-o variabila n declarata cu initializare si va fi luat de acolo (si eventual incarcat in CX). parantezelor 1. 10. push e (acum stiva contine opz. Suma va fi stocata in final intr-o variabila s de tip word. 2. Numerele vor fi date prin cod.y)+ si eliminarea parantezelor si virgulei.. push b (acum stiva contine (convenim varful spre stanga): 20.2) (e) pop doua valori. calculez diferenta lor si push aceasta difernta (acum stiva contine valoare parantezei mari 3. push c (acum stiva contine opz. unde n este o variabila word declarata cu initializare (numar natural) in program. II. din expresia mare) (h) la fel ca (e) (acum stiva contine valoarea finala: 4) In final valoarea expresiei (4) se va stoca intr-o variabila x. pt. paranteza 3.10) (2. parantezei 3: 3. parantezei 2 si val. ca (e) difera de (C) doar prin faptul ca se face scadere.13) (2. adica: 5 obs. parantezelor 3. parantezei 1: 15. 15. 4. II.5 puncte)(*) Program care calculeaza 1+2+.9) (2. II. a.II. cu transport/imprumut corespunzator pentru perechea urmatoare. 10) (c) pop doua valori. ultimei op.14) (4 puncte) (*) Program pentru evaluarea unei expresii oarecare in forma postfixata (forma postfixata pleaca de la reprezentarea operatiei ca functie cu numele functiei la sfarsit x+y = (x.b. nu adunare) (f) push d.11) (cate 2 puncte pentru fiecare din cele doua operatii) (*) Programe care calculeaza suma/diferenta a doua numera naturale multioctet folosind cicluri LOOP.ele se vor aduna/scadea byte cu byte. adica: 1. dar cu inmultire si impartire. 5 acestia sunt opz. 30) (d) la fel ca (c) (acum stiva contine val. 30 acestia sunt opz.b de tip byte initializate cu cate un sir de 5 octeti .11.+n. Expresia are ca operanzi numere byte si ca operatori "+" si "-" binari. astfel (a+b)*c = ab+c* iar a*c+b*c = ac*bc*+). . 20.e fiind variabile de tip word declarate cu initializare in program cu respectiv valorile 10.5 puncte) (*) Program pentru evaluarea expresiei ((a+b)-(a+c))-(d-e). II. cea care include parantezele 1. II. 4.12) (cate 10 puncte pentru fiecare din cele doua operatii) La fel ca la problema II. parantezei 4 si val. adica: 30) (d) push a. cate o pereche la fiecare iteratie.

.16) (2. 20. (b) fac d := a and b si obtin transporturile de la cele 16 poz. ale sumei (acestea trebuie adunate la pozitii shiftate la stg. Se vor folosi op. rang 7 0 7 0 7 0 Exemplu: 10000001 10000010 11000100 --> 00000011 00000101 10001001 adr.17) (3 puncte) (*) Program care roteste cu 1 la stanga in mod uniform bitii dintr-un sir de octeti declarat si initializat in program (bitul semnificativ care iese din octetul aflat la adresa n sa intre in bitul zero al octetului aflat la adresa n+1).logice si shiftari. 11001000 00001111 --> 11110000 00010011 II. imaginea se va construi in aceeasi locatie. Ex: nr. din memorie sau din stiva.15) (2.1".. suma=CX. 11001000 00001111 --> suma bitilor = 7 II. '-'. curenta in e si cu e(i) byte-ul de la aceasta pozitie. 10.18) (3 puncte) (*) Program care realizeaza adunarea a+b (de 16 biti) folosind op. Ex: nr. b=BX. Se vor folosi op. d. '+'. vom folosi cat mai putine locatii suplimentare (c. cu 1.5 puncte) (*) Program care calculeaza suma bitilor (numarul bitilor egali cu 1) din reprezentarea interna a unui numar natural. '+'. rotire.13. '$' Algoritmul de evaluare generalizeaza cel din problema II. '-'. (a) i:=0 (b) Daca e(i)='$' salt la (f) (c) Daca e(i)<>'+'.'-' (adica e operand) atunci push e(i) si salt la (e) (d) Daca e(i)='+' atunci pop doua valori. calc. II. de exemplu expresia din problema II. de shiftare.5 puncte) Program care construieste imaginea in oglinda a configuratiei din locatia unei variabile word declarata cu initializare in program. iar acestea pot fi registrii. 15.13 va fi data astfel: e db 10. push rezultatul si salt la (e) (e) i:=i+1 si salt la (b) (f) Pop o valoare (este rezultatul final al expresiei) si o salvez in x.1 2 3 II. suma va fi stocata in final intr-o variabila s de tip word. calc. . 4. si anume: (0) Notam cu i poz.Ea va fi data sub forma unei variabile initializata la declarare cu un string ce contine expresia si se termina cu "$". logice. '-'. de shiftare si op. STOP (avem c=a+b) (e) fac e := d shiftat la stg cu 1 (f) fac a:=c. dif. 3. conform urmatorului algoritm: (a) fac c := a xor b si obtin cele 16 cifre ale sumei daca n-am tine cont de transporturile de pe fiecare pozitie. logice pentru a muta/selecta bitii. lor. push rezultatul si salt la (e) Daca e(i)='-' atunci pop doua valori. b:=e si salt la (a) Pentru simplitate putem considera a=AX. dar pot aparea noi transporturi) (c) daca d=0. suma lor. Indicatie: folosirea repetata de "RCL octet.0. e). Numarul este dat intr-o variabila n de tip word declarata cu initializare in program.

Vectorul sortat se va constru in aceeasi locatie ca vectorul sursa.e. 2. iar pentru vectorul de lucru se va declara o variabila urmata de un numar rezonabil de octeti neinitailizati. iar acestea pot fi registrii.19) (3 puncte) (*) Program care realizeaza inmultirea a*b (fara semn. 3 II. produsul=CX. Ex: 4. sa incapa in 16 biti).e. si ca AL=BL=0 (pentru ca rez. II.21 (2 puncte) Ca la problema II. II. Pentru vectorul rezultat se va declara o variabila byte urmata de niste bytes neinitializati.II. iar lungimea lui printr-o variabila initializata de asemenea la declarare. iar lungimea lui printr-o variabila initializata de asemenea la declarare. si salt la (b) Pentru simplitate putem considera a=AX. II. cu 1 (i. II. Vectorul va fi dat sub forma unei variabile initializata la declarare cu un sir de bytes. de 16 biti) folosind shiftari si adunari. Vectorul sursa va fi dat sub forma unei variabile initializata la declarare cu un sir de bytes. 2.24) (5 puncte) Program care determina elementele distincte dintr-un vector de bytes si le pune intr-un nou vector. conform urmatorului algoritm (care se bazeaza pe scrierea lui a ca polinom in puterile lui 2 si apl. folosind triunghiul lui Pascal (construit intr-un vector de n+1 locatii transformat succesiv). II. Toate numerele vor fi de tip byte.20) (2 puncte) (*) Program care calculeaza maximumul elementelor unui vector de bytes folosind un ciclu LOOP. distributivitatii. impart la 2). iar lungimea lui printr-o variabila initializata de asemenea la declarare. vom folosi cat mai putine locatii suplimentare. 3 --> 4. II. cu 1 (i.25) (5 puncte) Program care caluleaza combinari de n luate cate k. dar programul va determina numarul elementelor nule din vector. folosind schema . iar lungimea lor printr-o variabila initializata de asemenea la declarare). 1. inmultesc cu 2).26) (3 puncte) Program care determina valoare unui polinom intr-un punct. fac b:=b shiftat la stg. 2. b=BX.23) (5 puncte) Program pentru sortarea unui vector de bytes. 2. 10 * b = (2^3 + 2^1)*b = b*2^3 + b* 2^1): (a) fac c := 0 (b) daca a=0. 1.20. din memorie sau din stiva.22) (2 puncte) Program care calculeaza produsul scalar a doi vector de byte (vectorii sunt dati sub forma a doua variabile initializate la declarare cu cate un sir de bytes. STOP (avem c=a*b) (c) daca a impar (a and 0001h <> 0) fac c := c+b (d) fac a:=a shiftat la dr. Numerele n si K sunt date sub forma a doua variabile declarate cu initializare. de ex. Vectorul va fi dat sub forma unei variabile initializata la declarare cu un sir de bytes. 1.

27) (15 puncte) Program de inmultire a doua matrici liniarizate. gradul si punctul se vor da sub forma unor variabile byte declarate cu initializare. Matricea se da sub forma unei variabile initializate la declarare cu un sir de bytes. II.28) (8 puncte) Program care calculeaza suma elementelor maxime ale col unei matrici liniarizate (din fiecare coloana se ia cate un singur element maxim). Operatia se va aplica unor stringuri declarate cu initializare in program (si terminat cu 0) iar raspunsul va fi stocat intr-o var. se aduna word-urile. Vectorul coeficientilor se va da sub forma unei variabile byte initializata la declarare cu un sir de bytes. Operatia se va aplica unui string declarat cu initializare in program si terminat cu 0.33) (4 puncte) Program care calculeaza "combinari de n luate cate k" ("n" si "k" variabile declarate cu initializare) folosind triunghiul lui Pascal.30) (5 puncte) Program care numara toate aparitiile unui sir ca subcuvant in alt sir. Rezultatul final va fi stocat intr-o alta variabila din program. Matricile sursa se dau sub forma unor variabile initializate la declarare cu siruri de bytes. Ex: "abadc" --> "cdaba" II. 0=egal. Exemplu: prog 12 0 3 45 ==> afisaza: 60 Indicatie: fiecare argument (care este string) va fi convertit la word. II. 2=mai mare. II. Programul va folosi un singur vector. Ex: 1 2 3 8 1 5 --> 8 + 2 + 5 = 15 1 2 4 II. n de tip byte. in care va genera succesiv liniile din triunghi. dimensiunile lor se dau sub forma a trei variabile byte declarate cu initializare.29) (5 puncte) (*) Program care simuleaza functia "strncmp" din limbajul C. II.31) (4 puncte) (*) Program care construieste imaginea in oglinda a unui sir (imaginea se va construi in aceeasi locatie).lui Horner. II. functia 9. dimensiunile ei se dau sub forma a doua variabile byte declarate cu initializare.32) (6 puncte) (*) Program care se lanseaza cu niste numere naturale date ca argumente in linia de comanda si afisaza suma lor. Bibliografie: . diferenta intre codul ASCII al unei cifre si numarul pe care il reprezinta este 48d (ex: "123" => ('1'-48)*100 + ('2'-48)*10 + ('3'-48) = 1*100 + 2*10 + 3 = 123). Operatia se va aplica unor stringuri declarate cu initializare in program (si terminate cu 0) iar raspunsul va fi stocat intr-o variabila x de tip byte sub forma: 1=mai mic. pentru matricea rezultat se va declara o variabila byte urmata de un numar corespunzator de bytes neinitializati. apoi suma se converteste la string si se afiseaza cu "int 21h".

.| | | informatia continuta). "Limbaje si calculator" Vlad Bazon. CPU . 1992 DANIEL DRAGULICI octombrie. .|b7. pentru scrierea in memorie . fiecare putand transmite -------------| | un bit. Tehnica. "Programarea in assembler" Dan Somnea.. ed. adresare.grafic.fiecare octet are o ADRESA | | ^ ^ | | FIZICA..date.asigura comunicarea dintre -----------------| | diversele componente.o magistrala are un numar fixat | | | | de LINII. lectia 1 . convenim sa reprezentam: | | | | | | | | | V | | | | -----------------| | .| | | | | |... Petrion 5.de ex. 2005 actualizat: 21 noiembrie 2005 2.b0|.ie/~creech/assembly/asm... Teora. daca magistrala are p | controler | | | linii..faqs.| | | | | |. ea poate transmite p biti | de |-------| | simultan.b0|b7. ed.7 |--|--->|An Dm|<--->| | in cadrul octetului sau.. | | |. ed. | | citire| |scriere | | . transfer: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Structura logica a calculatorului: magistrala magistrala de adrese de date | | | | Memoria: | | -----------------| | .. | | | semnale | | | ----------------------| | | de comanda | | | ^ ^ ^ | |<---|A0 D0|<----|->| n n+1 n+2 | | |.dcu.General" Internet: http://www. Assembler.~~~~~~~~~~~~~ 1. | | -----------------| | . MEMORIE . Alexandru Panoiu.Generalitati.semnale): |<-|----|An Dm|<--->| | . 1992 4. Intrenet: http://www. "Gavin's Guide to 80x86 Assembly". |intreruperi | | | .redbrick. .| | | . "x86 Assembly Language FAQ .fiecare bit are un RANG 0.html 2.este formata din OCTETI (BYTE) | |--->|A0 D0|<----|->| fiecare continand cate 8 BITI | | |.. .| | | (numim la fel dispozitivul si | | |.. acestea sunt numere | | | | | | naturale consecutive incepand de | | de | | de | | la 0.org/faqs/assembly-language/x86/general/ 3. . | | | | . Teodor Vladut.| | | Magistralele (adrese. "Microprocesoarele 8086/80286/80386 Programarea in limbaj de asamblare" Irina Athanasiu.

citirea decurge analog. activeaza semnalul de comanda a scrierii (atunci octetii de date intra in memorie in locatia de la adresa aplicata pe magistrala de adrese). 80486 poate accesa pana la 4GB de memorie. daca insa adresa la care trebuie sa ajunga wordul este impara (A0=1). astfel. de ex. daca adresa la care trebuie sa ajunga un word (octetul sau low) este para (A0=0). 3. deci datele aliniate in memorie la adrese pare pot fi accesate mai rapid. date 8 16 16 32 . aplica adresa (scrisa binar) pe magistrala de adrese. va fi stocata sub forma: 0Ah 01h | 00001010 | 00000001 | ------------------------^ octetul ^ octetul adresa: n low n+1 hi adresa unei locatii de mai multi octeti este adresa primului (celui mai putin semnificativ) octet al sau.acestea sunt date multi-octet. 5. se elibereaza magistralele de adrese si de date. sau hexa sub forma 01h 0Ah. daca A0=0 (adresa octetului destinatie este para).-------------| | | | | | | -------| | | | IO 1 |----| | | --------port| | | | | -------| | | IO 2 |---------| | -------port| | | -------| | IO 3 |--------------| -------port | | | | | | | | | | | | CPU parcurge urmatorii pasi: 1. el se emite pe D15-D8. anume octetii mai semnificativi se pun la adrese mai mari. apoi octetul hi prin D7-D0. iar daca A0=1 (adresa este impara). aplica bitii de date (numar intreg de octeti) pe magistrala date. se dezactiveaza semnalul de scriere. la 8086 adresele pot fi doar numere 0..80386SX 80386DX. . 2 octeti (word) sau 4 octeti (dword) . in acest scop compilatoarele/asambloarele ofera optiunea "word align data". Latimile magistralelor pentru diverse generatii de calculatoare: 8080 8086 80286. in timp ce 80486 poate transfera date de 1 octet (byte). adrese 16 20 24 32 M.de ex. el se emite pe D7-D0. deci el poate accesa doar 1MB de memorie (nu pot pune calculatorului memorie decat de max. wordul se poate transmite (prin D15-D0) printr-un singur ciclu (octetul low prin D7-D0. 2. atunci sunt necesare doua cicluri (ele insa se inlantuie automat): intai octetul low se tranmite prin D15-D8.80486 M. octetul hi prin D15-D8).in cazul datelor multi-octet numerice si pointeri se foloseste conventia Intel("little endian").2^20-1.aspect de aliniere (il ilustram pentru magistrale de date cu 16 linii): un octet se poate transmite atat pe liniile D7-D0. care se reprezinta binar sub forma 00000001 00001010. la o singura citire/scriere 8080 poate transfera doar date de 1 octet (byte). 4. valoarea 266 de tip unsigned short in limbajul C.. . cat si pe D15-D8. . 1MB).

.b0| ---------------oct. . deci un acelasi octet de memorie poate face parte din mai multe segmente. cele 5 cifre hexa "zzzzz" ale adresei fizice corespunzatoare unei . cele doua numere se scriu hexa sub forma "segment:offset". pentru anumite scopuri putem folosi mai multi registrii. in cazul registrilor convenim sa reprezentam: |b15. in acest caz "offset" nu poate depasi 2^16. de ex.numarul de ordine al octetului in cadrul segmentului (numarand de la 0).locatia unor registri coincide cu partea low sau hi a locatiei altor registri.hi oct.ele pot fi stocate de ex.numarul de ordine al unui segment ce il contine (numarand de la 0). intern sunt desemnati prin coduri de 3-4 biti. dar nu la orice. in registri de 16 biti. .au fiecare asociata o linie de intrerupere si un grup de adrese (porturi). CPU citeste primul octet.Dispozitivele de I/O: . dar nu pe oricare. .CPU priveste memoria ca impartita in segmente (zone continue de octeti). 16 si 32 biti. de asemenea.. etc. apoi incrementeaza IP pentru a-l pointa pe al doilea.contine cateva locatii de memorie proprii (REGISTRI).controlerul de intreruperi inregistreaza cererile de deservire emise la un moment dat de diverse dispozitive de I/O si comunica CPU pe cea mai prioritara. iar adresa fizica se calculeaza din ele dupa formula: segment*10h + offset (sau in baza 10: segment*16 + offset). acestia n-au adrese explicite ca locatiile de memorie. . 8086 are registri de 8 si 16 biti. un segment incepe de la o adresa fizica multiplu de 16 (10h) (paragraf) si are <= 2^16 octeti = 64K (la masinile cu magistrale de adrese de 32 biti pot exista si segmente mai lungi).fiecare registru are o utilitate specifica. (deci adresele fizice au 20 biti. apoi citeste al doilea octet. pana conchide ca a citit o instructiune intreaga (instructiunile pot avea lungimi diferite). etc. . adresa unui octet (sau a octetului de inceput al unei locatii) este specificata indicand: . . . Unitatea centrala (CPU): .grafic. apoi incepe incarcarea noii instructiuni de la octetul pointat de IP.daca magistrala de adrese are 20 linii. AH (care are 8 biti) contine de fapt bitii b15-b8 din locatia lui AX (care are 16 biti). . .registrii au un numar intreg de octeti iar dimensiunile lor sunt corelate cu latimile magistralelor de adrese si de date. deci segmentele au <= 64K.de exemplu la inceputul rularii unui program CS si IP contin adresa din memorie a primei instructiuni (primul octet al acesteia).. de ex. rezultata dintr-un calcul sau care urmeaza a fi scrisa in memorie). adica 5 cifre hexa) numerele "segment" si "offset" trebuie sa aibe 16 biti (4 cifre hexa) . apoi executa instructiunea. segmentele se pot intersecta (partial sau total) sau nu.b8|b7.. iar in limbajele de programare sunt desemnati prin mnemonice.low (deci invers ca la reprezentarea octetilor in memorie) Adresarea memoriei: . unii pot fi folositi si in alte scopuri.CPU acceseaza dispozitivul respectiv si il deserveste prin intermediul porturilor si magistralelor. 80486 are registri de 8.informatia dintr-un registru poate fi o adresa sau o data (citita din memorie..

resp. 0001:0019. pentru accesarea datelor sau instructiunilor sa nu se specifice de fiecare data atat segmentul cat si offsetul (adrese sau pointeri "far") ci doar offsetul (adrese sau pointeri "near").e folosita pentru alocarea variabilelor dinamice. cele 8 cifre hexa "zzzzz" ale adresei fizice corespunzatoare unei specificari "xxxx:yyyyyyyy" se obtin facand adunarea hexa: xxxx0+ yyyyyyyy --------exemplu (pe desen. "-" = un octet): zzzzzzzz seg=0002h| off=0009h --------------------------------. putem specifica adresa sub una din formele: 0000:0029.daca magistrala de adrese are 32 linii. de ex. la large toti pointerii vor fi far.specificari "xxxx:yyyy" se obtin facand adunarea hexa: xxxx0+ yyyy ----zzzzz . segmentul fiind cunoscut.contine instructiunile programului (in cod masina). adica 8 cifre hexa) numarul "segment" trebuie sa aibe tot 16 biti.(segment) seg=0001h | off=0019h -----------------------------------------. programele ce folosesc modelul small pot avea >64K. compilatorul va optimiza codul a. cea de cod 1 segment.daca unui compilator ii specific (de exemplu prin directive scrise in sursa unui program) specific modelul de memorie pe care il va folosi programul. cea de cod poate avea mai multe.(segment) seg=0000h | off=0029h --------------------------------------------------. exista mai multe MODELE DE MEMORIE: tiny . compact . in functie de dimensiunile acestor zone. dar datele. zona de date .memoria ocupata de un program in executie contine mai multe zone (ele pot avea unul sau mai multe segmente si se pot intersecta sau nu): zona de cod .i.(segment) -------------------------------------------------------------------------^00000h ^00010h ^00020h |=======| (locatie de 7 octeti) adrese fizice ^00029h deci pentru locatia de la adresa fizica 00029h. 0002:0009 (calculele fiind: 0000h*10h+0029 = 0001h*10h+0019h = 0002h*10h+0009h = 00029h) . stiva ocupa un acelasi segment. .zona de date poate avea mai multe segmente. huge . la medium pointerii la cod vor fi far iar cei la date vor fi near. cea de cod 1 segment. o structura de date nu poate depasi insa 64K.contine locatiile variabilelor statice. heap .si zona de date si cea de cod pot avea mai multe segmente.zona de date are 1 segment. medium .zona de date are 1 segment. la tiny si small toti pointerii vor fi implementati near. cum sunt cele folosite in cadrul apelurilor de subrutine (variabile automatice). large . small . (adresele fizice au 32 biti. cod. luate separat. nu pot depasi 64K.e folosita pentru alocarea unor variabile temporare. . programele ce folosesc modelul tiny ocupa in total <=64K si pot fi de tip COM. stiva . o structura de date nu poate depasi insa 64K. dar numarul "offset" poate avea si 32 biti (deci poate depasi 2^16. iar segmentul va fi mai lung de 64K). nu mai avem limitarea referitoare la structuri de date.si zona de date si cea de cod pot avea mai multe segmente. segmentele putand fi separate. codul.zonele de date.

BX. specifica: calcul adrese bazate ECX.pointeaza segmentul de cod activ. .X" are 16 biti si coincide cu partea low a reg. AX.Registrii cei mai importanti CPU (mnemonice si utilizare): . DI folosesc implicit segmentul pointat de ES.registrii generali (general purpose registers): ei pot fi folositi in operatiile uzuale de programator. ES . CH . SP .pointeaza segmentul de date suplimentar curent. cu exceptia adresarilor bazate si/sau indexate cu reg.base pointer . ". fiecare insa are si o utilitate specifica si este luat in consideratie automat de anumite instructiuni (fara sa trebuiasca sa-l precizam): EAX.registru data (data) ut.pointeaza segmentul de stiva activ. ". ." corespunzatori. specifica: acumulatori si pentru intrari/iesiri EBX. DX.L" sau ". adresarile bazate si/sau indexate cu reg. (E)SP folosesc implicit segmentul pointat de SS. toate au 16 biti (reamintim: "segment" e mereu pe 16 biti) fiecare are si o utilizare specifica (e luat automat de unele instr. AL. ".H" are 8 biti si coincide cu parea low. FS (386+). GS(386+) . DH . CX. BH . DL.code segment . CL. resp. "E.stack pointer . poate fi folosit insa si pt. siruri ce folosesc indexari cu reg. dar fiecare are si o utilizare specifica (e luat automat de unele instr. "E. a reg.stack segment . (E)SP si a instructiunilor pt.indica varful segmentului de stiva curent. BL. specifica: op.extra segment . EBP." au 32 biti si exista doar la 386+.X" corespunzator de ex. restul au 16 biti si coincid cu partea low a celor cu "E.): CS .registrii de segment (segment registers): de regula sunt folositi pentru a pointa segmente.se folosesc ca si ES.): ESP. de inmultire/impartire.data segment .registri indicatori de adrese (pointer registers): indica offsetul unor locatii importante si sunt folositi in adresarile bazate. DS . (E)BP. adresarile la date folosesc implicit segmentul indicat de DS..pointeaza segmentul de date activ.. ei pot fi folositi in scopuri generale de calcul. (E)BP." au 32 biti si exista doar la procesoarele 386+ un reg..registru acumulator (accumulator) ut. instructiunile pt. hi. cele cu "E. AH .registru contor (count) ut." corespunzator un reg. BP . intrari/iesiri din porturi accesate direct (DX contine adresa portului) reg. specifica: contor pentru instructiuni de ciclare EDX. DI SS .registru baza (base) ut.. siruri ce folosesc indexari cu reg. avem: AH AL 7------07------0 15--------------0 Ax 31----------------------------0 EAX .indica inceputul ultimului bloc incarcat in stiva (blocul este cuprins intre SS:SP si SS:BP).

trace .adresarea in cadrul altor segmente.daca IF=1 este activata acceptarea semnalelor de intrerupere externa. CLC. iar cel destinatie de DI: ESI.source index EDI. indicator sau flag. ei pot fi folositi in scopuri generale de transfer si calcul. cealalta are 16 biti si coincide cu partea low a celei cu "E.n. DI . dupa fiecare instructiune se genereaza un semnal de intrerupere intern (pe nivelul 1) (rutina care trateaza intreruperea se executa insa cu TF=0). siruri considera implicit ca sirul sursa este parcurs de SI. pentru rularea pas cu pas. indicatorii pot fi setati/stersi explicit (instructiuni ca STC.e utilizat in depanare.daca DF=1. fiecare din ei avand o semnificatie si un mnemonic .transport/imprumut intre bitii de rang 3-4. SAHF. pozitia indicatorilor in registru este: |--|--|--|--|OF|DF|IF|TF|SF|ZF|--|AF|--|PF|--|CF| ------------------------------------------------15 0 indicatorii si semnificatia lor cand au valoarea 1: CF .la executia unei instructiuni aritmetice cu semn s-a produs depasire (iar rezultatul s-a memorat trunchiat).s. instructiunile pt.carry . AF .instruction pointer . e folosit de operatiile cu numere zecimale codificate binar.registrul indicator al instructiunii curente: indica offsetul instructiunii ce urmeaza a fi executate (in segmentul de cod curent). cele cu "E. . elementele unui vector) si sunt folositi in adresarile indexate. daca DF=0.interrupt . . LAHF) .". ." are 32 biti si exista doar la 386+.rezultatul este 0. ZF .low al registrului in/din AH (instr.registrul indicatorilor de conditii (flags register): are 16 biti. SF .sign ." corespunzatori.. DF .bitul cel mai semnificativ al rezultatului e 1. PF .zero . indicand modul cum s-a terminat operatia..overflow . respectiv CS:IP..) sau putem salva/incarca oct.parity .adresa instructiunii ce urmeaza a fi executate este CS:EIP (386+).auxiliary flag .registrii index (index registers): indica deplasamentul unor date in cadrul unor locatii importante mai mari (de ex. daca TF=1. dupa executarea fiecarei instructiuni unii dintre indicatori sunt pusi pe 1 (set) sau 0 (clear). SI .direction .. TF . IF nu are efect in cazul semnalului de intrerupere nemascabila.destination index . dar au si o utilizare specifica (sunt luate automat de unele instr.) .. siruri le vor parcurge de la adrese mici la mari. cea cu "E." au 32 biti si exista doar la 386+.transport/imprumut in bitul cel mai semnificativ. IP . OF . restul au 16 biti si coincid cu partea low a celor cu "E.de exemplu instructiunile pt. la numere intregi (in complement fata de 2) inseamna rezultat negativ. EIP. par de 1..octetul low al rezultatului are un nr. le vor parcurge invers. IF .

.stack . .b: 0Ah 01h 0Bh 01h 0Ch 01h (little endian) c db ? .creaza executabil ". extensiile "asm".cream sursele asm intr-un acelasi director.lst)) Se linkediteaza cu: tlink [/t] [/v] fisier.genereaza un listing detaliat (fisier.inceputul segmentului de date a db 0ah. 1010b . "exe". "com" se pot omite. 10Bh. "c:\work".bat: c:\borlandc\bin\td %1 . "obj".bat: c:\borlandc\bin\tasm /zi /l %1. pentru depanare.deschidem Notepad.1.asm l.obj d.in acelasi director cu sursele ("c:\work") cream fisierele batch urmatoare: a.obj (optiuni: /t .ext (unde "ext" este "exe" sau "com") In cele de mai sus.se includ in obj si informatii pentru depanare /l .inceputul segmentului de stiva. 10. de fiecare data cand dorim sa asamblam/linkeditam/depanam un program "fisier.asm (optiuni: /zi . vom da din aceasta consola comenzile: a fisier l fisier d fisier Exemplul 1: =========== .ext sau. si cu el vom edita sursele asm.se includ si informatii pentru depanare) Se executa cu: fisier. 10Ch . Se compileaza cu: tasm [/l] fisier.deschidem o consola Command prompt si in ea comutam directorul curent in cel care contine sursele asm ("cd c:\work").com" (doar daca in program am folosit modelul tiny) /v . un segment de date . 12q.c: -- . 10d.bat: c:\borlandc\bin\tlink /v %1. Daca avem instalat in sistem Borland C++ 3.a: 0Ah 0Ah 0Ah 0Ah 0Ah b dw 10Ah.model small . cu td fisier.Exemple comentate de programe in TASM: -------------------------------------Se editeaza cu un editor de fisiere text (ex.asm".data . putem lucra eficient astfel: . de ex. Notepad).un segment de cod. .

al: 05h (octetul aflat la distanta 3 de "f") . 04h .o eticheta ..@data ax.ax: 040Ah...-...f . in cadrul ei) .marcheaza o pozitie (offset) in segm.ax: 5d . directa: operandul este in mem.acum DS...e . 'abc' .00ffh .ax al. bazate se fol. adica seg. si cel pointat de SS in cazul BP.ax . . el este implicit cel pointat de DS in cazul BX .al al. "val" o valoare inclusa la compilare in codul instructiunii.. . unde "reg" este BX sau BP iar . 03h. iar in instructiune apare adresa sa . .adr.ax ax. pt.byte ptr f+3 byte ptr f+3. 050Bh. diverse instructiuni: .ax: 01FFh word ptr c. exemple de adresare: .adr.adr.al .al ax. 02h.f: 0Ah 04h 0Bh 05h 0Ch 06h x dw ? ..word ptr a word ptr a.ax: 0302h (wordul aflat la 1 octet distanta de "e") .forma adresarii este "[reg]" sau "[reg+val]". ES pointeaza acelasi segment . atribuita direct unui registru segment mov es.al: 03h (octetul aflat la distanta 2 de "e") .. ax: 00FFh a.d db 3 dup(0Bh)... 060Ch .. nu merge mov b. a referi elementul unei structuri (BX sau BP va .ax mov dl.adr.al . sau.in ax ajunge adresa segmentului lui "b". imediata: valoarea este inclusa la compilare in codul instructiunii mov mov mov mov ax. in instructiune apare adresa sa mov mov mov mov mov mov mov mov mov mov ax..offset b . bazata: operandul este in mem. adica 5 (0005h) . .b: FFh 01h 0Bh 01h 0Ch 01h ax.. ah:00h.d: 0Bh 0Bh 0Bh 0Ch 61h 62h 63h e db 01h.. prin registri: valoarea este intr-un registru mov cx.daca nu precizam segmentul.e+2 e+2...y: -. contine offsetul structurii.adr.al .al: FFh.inceputul segmentului de cod start: ..a: FFh 0Ah 0Ah 0Ah 0Ah. de cod mov ax..seg b bx.-y dw ? . mov mov mov mov mov mov mov ax.ax: 010Ah ("al" ramane 0Ah dinainte) ax..ax . prin intermediul registrului BX sau BP.@data .e: 01h 02h 03h 04h f dw 040Ah.ax .in ax ajunge offsetul lui "b" in seg..acum bx = ax ..b b.c: FFh d: 01h 0Bh 0Bh 0Ch 61h 62h 63h ...5 ax. 0Ch.de date . iar "val" deplasamentul elemen.e (tipuri diferite) ah.code .."data" e o constanta (operand imediat) si nu poate fi mov ds. nu merge mov ax.ax .word ptr e+1 word ptr e+1....x: -.al (tipuri diferite) byte ptr b.b .

deplasamentul elementului in structura respectiva mov mov mov mov bx.ax si. a referi elementele unui vector. codul instructiunii.2 . programul va incepe de la eticheta . ". stiva (in acest prog. SI sau DI va contine indicele in vector al structurii.cu ".idem (ds e considerat implicit) . indexata: e la fel ca cea bazata.byte ptr [bx+si+1] . SI. efect: reda controlul sistemului DOS . "start" mov ah. . . reg2 este SI sau DI iar "val" o valoare inclusa la compilare in . a referi elem.ax ds:[si+2]. unde "reg1" este . date. resp.idem [si+2].sfarsitul programului. bazata si indexata.[BP+1] .adr. el este implicit cel pointat de DS in cazul BX .al: 05h.pregatire: in stiva este scris continutul lui ax (050Bh). octetului low 0Bh) in segmentul pointat de SS mov bp.daca nu precizam segmentul. unei structuri din stiva . trebuie precizat "mov ax.[bx+2]" foloseste implicit ds mov [bx+2]. iar "val" .avem cate un singur segm. altul decat .2 al.pregatire mov ax.forma adresarii este "[reg1+reg2]" sau "[reg1+reg2+val]".adr. cel pointat de ds.ax: 050Bh (de la "f" pointat de BX se mai parcurg 2 octeti) .ds:[bx+2] ax. mov mov mov mov mov mov mov si. caci "mov ax.ds:byte ptr [bx+si+1] . .ax: 050Bh ax. iar SP contine offsetul word-ului scris (deci al . din AH).[bx+offset f] . adresa sa prin intermediul unuia din reg. indexate se folosesc pt.offset f ax.code". val. stiva).la fel ca dupa primele doua instr. . pt. DI. registrul segment implicit este in ambele cazuri DS.ax mov ds:[bx+2]. BX sau BP.offset f .pregatire mov al. cod.la fel ca dupa primele doua instr.[si+offset f] .incarcam AH cu 4Ch si apelam intreruperea 21h (ea preia ca .adr. bazate si indexate se fol.es:[bx+2] . deci ax: 0505h mov bx.pregatire ax.data".pregatire si.ax mov es:[bx+2]. si cel pointat de SS in cazul BP. cu ". . daca "f" era intr-un segment pointat de es.pregatire ax. param.offset f . operandul este in mem. din acest grup .sp . DI in loc de . . . .2 . pt. date.ds:[si+2] . BP si unuia din reg. sau dintr-un vector de structuri (BX sau BP va contine offsetul vectorului.stack numar" specificam ca stiva va avea dimens.ax push ax .stack" specificam ca ceea ce urmeaza face parte din segmentul de cod. mentionata aici.aici e acelasi lucru caci am facut inainte ca es = ds. iar in instructiune apare . 4ch int 21h end start Comentarii: .adr. din acest grup .[bx+2] ax.[si+2] . dar se foloseste SI. ".es:[bx+2]" . BX si BP.idem . BX.pregatire .mov mov mov mov bx.al: 05h al.

. 201h).dword (double word: 4 octeti) DQ .tbyte (ten bytes: 10 octeti) . de la poz "d" gasim octetii: 0Bh 0Bh 0Bh 0Ch 61h 62h 63h (la stringuri nu se aplica conventia little endian ci doar la numere si pointeri). anume adresa primului element . "word ptr".qword (quad word: 8 octeti) . mem. tipul poate fi insa fortat cu "byte ptr". lasand un antet de 100h (256) bytes la inceputul segmentului de cod (unicul segment al programului dealtfel). carora li s-a asociat un tip (numele unei variabile este asemeni numelui unui vector in limbajul C.byte (1 octet) DW .code org 100h .ax") . anume 2 octeti (este vector de word). ca "b" este un vector de dimensiune neprecizata si cu elemente word.o instructiune poate avea 0. aceasta deoarece sistemul de operare incarca excutabilele ".sursa" efectueaza "destinatie := sursa". care reprezinta o constanta.es".variabilele sunt considerate pozitii in mem. ca de ex. mem. se ia de la adresa "b" (si se pune in AX) o cantitate care ar corespunde primului element. numerelor BCD numele "a" si "b" desemneaza offseturile 0000h. (ex: nu merge "mov [bx].com" in memorie de la offsetul 100h.).intre ei sunt 5 octeti egali cu 10 (in declaratie sufixul indica baza). facand o analogie cu limbajul C. etc.es" "mov ds.word (2 octeti) DD . 1 sau 2 operanzi. daca insa fac "mov ax.b". etc.2" dar merge "mov ax.). dw.01h si 02h (iar AX va avea val. al carui nume reprezinta adresa primului sau element (offsetul 0005h).2" "mov ds. iar de la offsetul "b" gasim octetii 0Ah 01h 0Bh 01h 0Ch 01h etc. trebuia sa specificam ".operanzii trebuie sa aibe acelasi tip (db.instructiunea "mov destinatie. reale DT . respectiv 0005h fata de inceputul segmentului de date .[bp]" sau "mov ds.m.ax" si: "mov ax.model tiny"..ax") . de la adresa "b" se numara 14 octeti. "c" (aflata la 2*3=6 octeti dupa "b") este un octet neinitializat. la poz.de "numar" octeti (implicit este 512). de aceea nu trebuie sa folosim "org 100". . ajungandu-se la adresa desemnata de variabila "e".element de tipul precizat in declarare). executabilele ". tipurile posibile sunt: DB . argumentele in linia de comanda. iar in AX ajung cei 2 octeti de dupa "e" . merg insa succesiunile: "mov ax.utilizate pt. . aici sistemul de operare pastreaza cateva informatii despre program. 10Ah se memoreaza cu octetul low primul: 0Ah 01h. s.intr-un registru segment nu se poate atribui o valoare imediata (ex: nu merge "mov ds.d. (reamintim: in conventia Intel nr. ne putem gandi de ex. daca fac "mov ax.operanzii pot fi imediati. directiva "org 100h" spune compilatorului ca la rulare executabilul va fi incarcat de la offsetul 100h si astfel compilatorul va calcula corect offsetul variabilelor atunci cand va inlocui in codul generat numele lor cu adresa. felul lor si modul de . nu pot fi ambii zone de memorie sau ambii registri segment.utilizate pt. registri sau zone de memorie. caracteristici: .exe" insa sunt incarcate de sistemul de operare in memorie de la offsetul 0000h si folosesc in general segmente speciale pentru date.[bp]" "mov [bx]. nr. . iar segmentul de cod sa-l incepem asa: . nu 14 word (deci nu e ca in limbajul C).com".a.[b+14d]".daca am fi dorit sa cream un executabil "..

es:variabile2 inceput: mov ax.) rulam pas cu pas cu F7 (putem rula continuu pana la o instructiune data cu F4)..zona de date poate avea mai multe segmente ..contine expresii pe care le urmarim.code . deci AL:=06h mov al. etc.de ex.contine registrii Watches .a . date. dar putem scrie si asa int 21h .ne intereseaza doar ca AH:=4ch. iar in TD deschidem (din View/. linkeditam si lansam in depanare programul asa cum am indicat mai inainte.ds:variabile1. in mediul TD se lucreaza ca in mediile Turbo .es:[0000h].un segm.ds:a.ds:b.07h.03h .la compilare numele "c" se inloc.la compilare numele "b" se inloc.e.ax mov ax.ds:[0003h]. in care precizam (printre alte inf. i.08h. i. le putem decl. numit "variabile1" ce contine date a db 01h.la compilare numele "a" se inloc. numit implicit "STACK" variabile1 segment .model compact .contine zona de cod Registers .b . Fiecare segment declarat in program are un nume. de cod. in timpul rularii urmarim registrii si expresiile din Watches.09h . . mov al.face implicit mov al. putem redimensiona/muta ferestrele cu Ctrl-F5/sageti/Enter. cu offsetul 0000h variabile2 ends . stiva. ". declarate cu ". folosind directive complete de segmentare.02h. zecimal punem 2d. cu offsetul 0000h b db 04h. in general. unicele segmente de cod. etc. ". mov al. numit "variabile2" ce contine date c db 06h.stack" au primit implicit numele "_TEXT".05h .variabile1 mov ds. numit implicit "_TEXT" assume cs:@code. resp. cu offsetul 0003h variabile1 ends variabile2 segment .es:c. deci AL:=01h mov al. iar o expresie se insereza/editeaza/sterge cu Enter/Enter/Delete.stack .e.face implicit mov al. deci AL:=04h mov ax.asamblam. in fereastra Watches mutam cu sageti selectorul pana unde vrem sa inseram o expresie.un segm.code".variabile2 mov es.data". mov al.) si numele lor: Exemplul 2: ~~~~~~~~~~~ .un segm.) fereastrele: CPU . "_DATA" resp. 4c00h . adaugate sunt considerate implicit hexa (pt. de stiva. i. 3d.ds:[0000h]. aici introducem: a (sau [a] sau ds:[a]) [a+1] [byte ptr b] [byte ptr b+1] [c] [byte ptr d] [e] [e+1] [e+2] [byte ptr f+2] [byte ptr f+3] atentie ca aici constantele 2.ss:@stack.e.face implicit mov al.c . "STACK". 3.ax mov al. in exemplul anterior. daca vrem mai multe segmente.adresare posibile sunt comentate in program pentru "mov" dar sunt valabile si in cazul altor instructiuni.un segm. si le putem permuta cu F6.

de cod/stiva/variabile1/variabile2 si nu precizeaza reg.daca in prog. "b".ds:variabile1. totul va fi OK daca la mom.a" s-ar traduce prin "mov al.a" si "mov al.a" sa se trad.variabile2 mov es."assume cs:@code. avand numele implicit "_TEXT" (la modelele medium. este altul. respectiv AL=09h.ax (trecerea prin AX este necesara deoarece numele segmentelor "variabile1" si "variabile2" sunt niste constante (operanzi imediati) si nu pot fi atribuite direct unor registri segment).ds:[0003h]". respectiv 0000h. astfel.ax mov ax. compilarii.code nume").ds:[0000h]".@code mov cs. adica 0000h. ss:DGROUP iar daca modelul de mem. care conform "assume" s-ar fi tradus prin "mov al.variabile1 mov es. respectiv "mov al.[0000h]" si conteaza daca offsetul 0000h este masurat in segmentul "variabile1" (caz in care am obtine AL=01h) sau in "variabile2" (caz in care am obtine AL=06h). la compilare numele "a".in programul de mai sus avem un singur segment de cod. "b" si pe ES in cazul lui "c".variabile1 mov ds. large. instructiunile referitoare la "a".analog.es:variabile2" este o directiva de compilare (este tratata la mom. faptul ca am facut "assume ds.es:[0000h]". notam ca daca am fi facut aceleasi "assume" dar am fi atribuit invers: mov ax. huge putem sa-i dam un nume scriind ".end inceput . putem scrie (cum am si facut) "assume cs:@code". 0003h.ss:@stack.ax mov ax.acest lucru nu poate fi asigurat la mom. . astfel. "b".ax dar este facuta implicit de sistemul de operare cand lanseaza programul (va pointa segmentul de cod ce contine pct. ds:DGROUP. stiva am facut "assume ss:@stack". care sunt offseturile lor in segmentele din care fac parte. totul e sa o mentionam si la "end" Comentarii: . prin"mov al. "c" care nu indica reg. pt. daca nu dorim sa folosim acest nume in "assume". .ax atunci "mov al. "mov al.de start. initializarea lui CS nu poate fi facuta insa explicit. de segment sunt traduse in instructiuni masina ce folosesc implicit pe DS in cazul lui "a".compilatorul va face implicit: assume cs:_TEXT.variabile1" face ca la compilare "mov al.ds:[0000h]".nu punem "assume"-uri si modelul de mem. "c" sunt inlocuite cu niste constante. compilarii si de aceea am inclus in cod secventa (care se trateaza la mom.putem numi oricum eticheta ce marcheaza punctul de start al . executiei): mov ax. instructiunea "mov al. nu executiei) ce instruieste compilatorul sa traduca toate instructiunile ce se refera la entitati declarate in segm."variabile2" . executiei DS chiar va pointa segm. gen: mov ax."variabile1" iar ES chiar va pointa segm. adica am fi obtinut AL=06h.ar fi masurat offseturile 0000h si 0003h in segmentul "variabile2" (pointat de DS). prin "mov al. masina ce folosesc implicit CS/SS/DS/respectiv ES. este "small" sau "compact".care aici e "inceput").variabile2 mov ds.c" se va trad. intr-adevar. de segment in instr. programului. similar.b". va face implicit: .

) . date si stiva nu mai este necesar sa folosim "assume" ("assume"-urile implicite sunt OK) si este suficient sa initializam doar DS (daca folosim variabile) si SS (daca folosim stiva).. cu model "small" sau "compact" si care folosesc cate un singur segment (cu numele implicit) pt.| -----> --------------------------------------------------^ <----.. cod. este posibil sa nu vedem acolo valorile cu care le-am initializat pana nu trecem cu executia (cu F7) de partea care initializeaza registrii segment pentru date (partea cu "mov ax. Obs: Cand rulam programul cu TD.nu merge "pop cs" (desi merge "push CS") (CS poate fi incarcat din stiva doar prin returul dintr-o subrutina in context far) Obs.ce contine printre altele segm.pointeaza segmentul stiva curent (ca adresa de segment). .intr-adevar. ceea ce permite o citire naturala a acesteia.operandul poate fi indicat ca la "mov" (imediat.@data".. Stiva este folosita pentru a salva/recupera valori temporare si pentru a aloca variabile automatice in cadrul apelurilor de subprograme. SP ... bazat.ax") .concluzie: la programele simple.: Faptul ca stiva creste spre adrese mici face ca SP sa pointeze mereu inceputul ultimei date incarcate. Instructiunea "push operand" (unde "operand" este word) efectueaza: SP := SP-2 (decrementeaza SP cu 2) SS:[SP] := operand (pune operandul la adresa SS:SP) Instructiunea "pop operand" (unde "operand" este word) efectueaza: operand := SS:[SP] (pune in operand wordul de la adresa SS:SP) SP :=SP+2 (incremeteaza SP cu 2) Caracteristici: . TD foloseste pentru accesarea variabilelor vizualizate registrii segment respectivi si daca acestia au valori necorespunzatoare afisaza informatia luata din alta parte.de segm.assume cs:nume_TEXT.. ss:DGROUP unde"DGROUP"e un gr..... ds:DGROUP.pointeaza varful stivei (ultimul octet incarcat) (ca offset). incarcata (ca offset) (e important la subrutine). nu sfarsitul ei.^ ^ SS stiva creste SP BP spre adrese mici SS . BP ... "mov ds. incarcata zona deja ocupata | | segment stiva V V --------------------------------------sensul cresterii adreselor | |====|. Exemplul 3: =========== . daca avem in program variabile initializate si le vizualizam in fereastra Watch.pointeaza octetul urmator ultimului octet din ultima inreg..de date si stiva. ea este gestionata de trei registri: ultima inreg. ..

redam controlul sistemului DOS. push beta .ax . in fereastra Watches vom introduce: [byte ptr sp] (sau ss:[byte ptr sp]) [byte ptr sp+1] [byte ptr sp+2] [byte ptr sp+3] [byte ptr sp+4] [byte ptr sp+5] [alpha] [alpha+1] [alpha+2] Atentie ca daca facem multe "push" iesim din zona alocata stivei si intram in alte zone . sistemului DOS end start .. redam controlul int 21h .data alpha db 01h. 03h .2 push ax push bx pop ax pop bx mov ah. [SP]: 0Ah 05h push word ptr alpha .@stack . caz in care programul poate pica.se rezolva la executie mov ss. 060Bh.@stack mov ss.ax mov ax.stack .cand rulam exemplul de mai sus cu TD.stiva de 512 octeti .1 mov bx.[SP]: 0Bh 06h 01h 02h 0Ah 05h pop ax .model small .alpha: 01h 02h 03h beta dw 050Ah. in cea de cod. [SP]: 0Ah 05h. 02h.code start: .AX: 0201h (little endian) pop word ptr alpha . [SP]: 01h 02h 0Ah 05h push beta+2 . 070Ch .stack .stiva vida.@data . 4ch . int 21h end start Comentarii: . alpha: 0Ah 05h 03h mov ah.AX: 060Bh (little endian) pop ax . cs este initializat de sistemul de operare mov ax.ax .code start: mov ax.nu sunt necesare "assume" (cele facute implicit sunt OK) mov ax.model small .beta: 0Ah 05H 0Bh 06h 0Ch 07H . 4ch . mov ds.de ex. [SP]: 01h 02h 0Ah 05h. Exemplul 4: interschimbarea valorilor a doi registrii folosind stiva =========== (la rularea cu TD vom urmari registri): .

1992 3.ca lds. ed. Intrenet: http://www.copiaza in AH octetul low al reg. ed. Teodor Vladut. urm. de flaguri sahf . folosind o a treia variabila.Alte instructiuni: xchg opd1. ed. folosind doi registri (nu se va folosi "xchg").interschimba continutul operanzilor.dcu. se incarca in "reg". 2 (segmentul) se incarca in DS. seamana cu "mov reg.ie/~creech/assembly/asm. Teora. "Programarea in assembler" Dan Somnea. 1992 DANIEL DRAGULICI octombrie.3) (0.5 puncte) Program care interschimba doua variabile word initializate. "reg" are 16 biti les reg. urmatorii 2 segmentul).salveaza in stiva (push) registrul de flaguri popf . . neinitializata (nu se va folosi "xchg"). se iau primii 4 octeti de la acea adresa si se privesc . "Microprocesoarele 8086/80286/80386 Programarea in limbaj de asamblare" Irina Athanasiu.opd .offset opd" lds reg. I.opd . "Gavin's Guide to 80x86 Assembly".html 2. folosind stiva (nu se va folosi "xchg").opd ."opd" e privit ca o adresa. 2005 actualizat: 18 octombrie 2005 ."reg" are 16 biti. I. operanzii trebuie sa fie de acelasi tip byte.5 puncte) Program care interschimba doua variabile word initializate. Bibliografie: ~~~~~~~~~~~~~ 1. offsetul. Tehnica. "Limbaje si calculator" Vlad Bazon. word lea reg. primii 2 (offsetul) .2) (0.copiaza in octetul low al reg.incarca in registru offsetul operandului. .opd2 .1) (1 punct) Program care interschimba doua variabile word initializate. de flaguri pe AH pushf .redbrick.incarca din stiva (pop) registrul de flaguri Exercitii (se vor rula cu TD): -----------------------------I. . Petrion 4. Alexandru Panoiu. ei insisi ca fiind o adresa (little endian: primii doi . dar se incarca ES in loc de DS lahf . .