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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful