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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful