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

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

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

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

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

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

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

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

deoarece al<bl ca numere cu semn (-126 < 1) . se sare cu executia la adresa . dealtfel vedem ca SF<>OF (conditia de salt la jl) nop . "Jxx" sunt in concordanta cu rezultatele posibile la "CMP". (offsetul) "adr" in cadrul segmentului de cod curent.instructiunea de efect nul (nu afect.10000010b mov bl.bl . .JNBE (vedem JL.SF=1. corespunzatoare lui "xx". dintre "adr" si offsetul instructiunii urmatoare lui "Jxx". .JNL JG. deoarece nu avem al<bl ca numere fara semn (128 >= 1) . mai exact daca executam succesiunea: CMP opd1..sare.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.. .JNA semn JAE.nu sare.JNG JGE. se executa IP := IP+depl. am pus-o de umplutura et1: jb et2 .opd2 Jxx adr atunci in functie de "xx" avem: JB. 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.00000001b cmp al.JNB semn JA. dealtfel vedem ca nu avem CF=1 (conditia de salt la jb) nop .nici flagurile).trebuie insa ca "depl" sa fie intre -128.PF=1.JNGE JLE. unde "depl" este diferenta .JNAE JBE.OF=0 jl et1 . exceptie: "jmp" . (vezi mai jos) poate face si salturi mai mari Variantele de "Jxx" si config.JZ (equal/zero): sare daca opd1 = opd2 JNE.diferenta al-bl este 10000001 si rezulta: CF=0.127.practic.JNZ (not equal/not zero): sare daca opd1 <> opd2 De exemplu: mov al.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

070Ch . push beta . caz in care programul poate pica.alpha: 01h 02h 03h beta dw 050Ah.@stack mov ss.AX: 0201h (little endian) pop word ptr alpha . redam controlul int 21h . [SP]: 01h 02h 0Ah 05h push beta+2 . mov ds.ax mov ax. int 21h end start Comentarii: .AX: 060Bh (little endian) pop ax .@stack . cs este initializat de sistemul de operare mov ax.se rezolva la executie mov ss. [SP]: 01h 02h 0Ah 05h.1 mov bx. in cea de cod. Exemplul 4: interschimbarea valorilor a doi registrii folosind stiva =========== (la rularea cu TD vom urmari registri): . 060Bh.model small .code start: . [SP]: 0Ah 05h push word ptr alpha .ax .data alpha db 01h.nu sunt necesare "assume" (cele facute implicit sunt OK) mov ax.ax .stack .[SP]: 0Bh 06h 01h 02h 0Ah 05h pop ax . 03h .beta: 0Ah 05H 0Bh 06h 0Ch 07H . sistemului DOS end start .stiva vida. 02h. 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 . alpha: 0Ah 05h 03h mov ah.model small .de ex.cand rulam exemplul de mai sus cu TD.stiva de 512 octeti .@data . [SP]: 0Ah 05h..code start: mov ax.stack . 4ch .redam controlul sistemului DOS.2 push ax push bx pop ax pop bx mov ah. 4ch .

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

Sign up to vote on this title
UsefulNot useful