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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful