Professional Documents
Culture Documents
Bitii din registrul Flag sunt indicatori de stare care se pozitioneaza functie de rezultatul ultimei
operatii aritmetice sau logice si se testeaza de instructiunile de salt.
Instructiunile de transfer a datelor si salt nu pozitioneaza indicatorii.
1
Programele trebuie sa fie modulare si relocatabile - sa poata fi incarcate oriunde in memorie si sa poata rula
din acea zona.
Modulele vor cuprinde informatii de acelasi tip rezultate din compilarea programelor.
Un segment poate cuprinde mai multe module asamblate de Link-Editor.
Un program poate cuprinde mai multe segmente. Exista 4 tipuri de segmente :
segment de cod ce contine numai instructiuni de program cu adrese relative la inceputul
segmentului, bazat cu registrul de segment CS;
segment de date ce contine numai date din program, bazat cu registrul DS ;
segment de date comune pentru mai multe segmente, bazat cu registrul ES ;
segment de stiva ce contine datele gestionate ca stive, bazat cu registrul SS ;
Implicit adresele datelor din program se bazeaza cu reg.DS, adresele de salt cu reg.CS si adresele de stiva
indicate de SP (Stack Pointer) cu reg.SS.
Segment de cod
CS=1000 000 -salt la adresa 250 din seg.
… JMP CS :250 de cod plasat la adresa
1000 indicata de CS
(adresa absoluta 1250)
250
MOV AX,DS :[150] -incarca z din seg. de date
bazat cu DS de la adr. 150
-incarca x de la adr.40 din
MOV BX,ES :[40] seg.Extern bazat cu ES
Segment date locale
DS=2000 000
- adresa absoluta
150 2000+150=2150
Z=350
Segment de stiva
SS=7500 ….. Contine toate stivele
…. folosite in program
2
Calculul adresei fizice
15 0
Cod Offset Adresa Adresa relativa in
instr. (Deplasament) segment
0
15 +
CS Adresa inceput segment 0000
0
19 =
Adresa de memorie fizica
BX RAM
COD instr. Adresa relativa operand Operand2
Adresarea indexata
ADD AX,X[SI] din tabloul X se ia elementul indicat de SI (adr.in tablou)
3
Tablou X +SI
COD instr. Adresa relativa tablou X X1 X2 X3 Xi
Adresarea cu baza
ADD AX,[BX+5] BX indica o zona de date, iar 5 este adr.relativa in zona
BX Zona de date +5
COD instr. Adresa relativa zona Oper2
Datele pot fi : locale in segment specificate prin adresa relative la care se adauga [DS]
comune mai multor segmente (ext) spec.prin adr.rel. si se adauga [ES]
temporare care se pastreaza in stive in segmentul de stiva adr. [SP]+ [SS]
Pentium si I486 cuprind procesor si coprocesor care lucreaza in paralel. Coprocesorul nu are mecanism
de calcul al adresei si salt, care se realizeaza de processor.
4
COD adr.rel -instr. pe 3 octeti, adresare directa ADD BX,alfa
In toate cazurile de mai sus implicit la adresa relativa se aduna continutul reg. DS.
Daca se doreste sa se specifice al registru segment decat cel implicit DS sau SS pentru stiva, se adauga in
fata un octet suplimentar care specifica reg.segment explicit.
Instructiunile care fac referire la memorie contin o extensie de cod notata Mod r/m care specifica modul de
adresare folosit (reg-reg, bazata, indirecta,indexata) si are structura:
5
001 CX CL ECX CS
010 DX BL EDX SS
011 BX DL EBX DS
100 SP AH ESP FS
101 BP CH EBP GS
110 SI DH ESI
111 DI BH EDI
PUSHA salveaza toare registrele in ordinea data de codul registrului.
Pentru utilizarea registrelor pe 32 biti se introduce un octet extensie de cod si inca unul pentru utilizarea
adreselor pe 32 biti.
Pentru exercitii se va folosi programul de depanare AFD si se vor studia structurile instructiunilor utilizate.
Adresele din memorie au octetii inversati.
Specificarea lungimii operandului cand nu rezulta din reistrul folosit se specifica prin :
/B pentru un octet si /W pentru 2 octeti (word).
Pentru exercitii se pot folosi instructiunile de mutare, aritmetice si logice pe 1 sau 2octeti.
MOV reg_dest,reg_sursa transfer intre registre
MOV reg,[adresa] transfer din memorie in registru (citire din memorie)
MOV [adresa],reg transfer din registru in memorie (memorare registru)
MOV reg,valoare incarcare imediata in registru
MOV adresa,valoare memorare imediata in memorie
Cand se specifica adresa, ea poate fi directa, indirecta,sau/si indexata.
PUSHA memorare toate registrele in stiva
POPA incarcare toate registrele din stiva
ADD dest,sursa se aduna sursa la destinatie cu un singur operand in memorie
SUB dest,sursa se scade din destinatie sursa
AND dest,sursa operatia logica SI intre sursa si destinatie
OR dest,sursa operatia logica SAU intre sursa si destinatie
XOR dest,sursa operatia logica SAU EXCLUSIV intre sursa si destinatie
6
1.5. Utilizare AFD (Advanced Full screen Debuger)
Exista mai multe ferestre deplasarea cu tastele F4 sus, F8 jos,F9 stinga, F10 dreapta
In fiecare fereastra se poate modifica direct pe ecran continutul registrelor, adreselor de memorie, a
continutului celulelor de memoriei.
Schimband adresa sau reg.segment se schimba zona de memorie afisata.
Valorile din register si memorie sunt reprezentate in hexazecimal.
Fereastra din dreapta jos da continutul ASCII al locatiilor de memoriei din fereastra 2.
F4 afiseaza Help-ul programului
F1 Step executa o instructiune de program( pas de program).
F1 StepProg executa un program terminat cu INT 3 (termina un task si revine in AFD).
Fereastra CMD de comanda permite introducerea de comenzi :
D adresa -afiseaza in hexa si in limbaj de asamblare o zona de program.
R reg=val initializeaza registre
M n adresa afiseaza zona de memorie in fereastra 1 sau 2 (n=1,2)
A adresa asambleaza un program de la adresa (>100), reg seg. CS (Exit-Ctr/Home)
G adresa lansare un program de la adresa bazata cu CS (oprire cuCtr/Esc)
L prog incarca un program .exe in memorie la adresa
W fis,adr,lung scrie intr-un fisier o zona de memorie de lungime specificata
QUIT terminare AFD si iesire in DOS sau Windows
7
2. INSTRUCŢIUNI ARITMETICE SI LOGICE
2.1. Instrucţiuni de mutare
Instrucţiunile de mutare realizează transferul datelor intre registre, intre registre şi memorie, intre
registre şi stiva. Transferurile se pot executa intre registre de aceeaşi lungime, iar la transferul intre
registre şi memorie lungimea este dată de registrul folosit.
Instrucţiunile de mutare nu modifică indicatorii de condiţie.
Toate mutările se pot face pe 1,2,4 sau 8 octeţi. Mutările sunt de forma:
Prin mem vom înţelege o locaţie de memorie specificată prin orice mod de adresare (directă,
indirectă, indexată). La indexare se pot folosi numai registrele SI si DI, iar la adresarea cu bază se pot folosi
numai BX şi BP. La toate adresările se foloseşte un registru de segment implicit sau explicit. Registrele
segment implicite sunt:
CS - pentru instrucţiunile de salt în program
DS - pentru toate datele utilizate
SS - pentru adresarea stivei prin SP (Stack Pointer) sau când baza este BP.
Exemple:
MOV CL,DH - reg-reg pe 1 octet unde orice combinaţie este posibilă
MOV SI,DX - reg-reg pe 2 octeti aproape orice combinaţie este posibilă
MOV EDX,EBX - reg-reg pe 4 octeti
MOV BP,3420 - încărcare imediata constanta intr-un registru pe 2 octeţi
MOV ECX,3420 - încărcare imediata constanta intr-un registru pe 4 octeţi
MOV b/[4200],54 - încărcare imediata const. intr-o adresa de mem. pe 1 octet
MOV w/[4200],54 - încărcare imediata const. intr-o adresa de mem. pe 2 octeţi
In memorie constanta 0054 se va memora pe cei 2 octeţi inversaţi 5400.
Inversarea se produce la orice memorare de registru si la orice citire din memorie.
MOV BX,[3450] - încărcare conţinut adresă de memorie intr-un reg. pe 2 oct.
MOV EBX[3450] - încărcare conţinut adresă de memorie intr-un reg pe 4 oct.
MOV [2400],DS - memorare conţinut registru într-o locaţie de memorie
MOV X,DX - memorare conţinut reg. într-o locaţie de memorie in ASM
MOV [BX],DX - memorare conţinut reg. într-o locaţie de memorie indirect
MOV DX,X[SI] - încărcare reg. din memorie cu adresă indexata din tabel X
MOV CX,[BX+SI+5]- încărcare reg. din memorie cu adresa indirecta si indexata
Când nu se poate da implicit prin registru lungimea în AFD se precizează explicit prin:
b/ - byte (1 octet) şi w/ - word(2octeţi).
În limbajul de asamblare (ASM sauTASM) lungimea explicită a operanzilor se dă prin:
MOV byte ptr[BP+5],25 - încărcare imediata in memorie pe 1 octet
MOV word ptr[BP+5],25 - încărcare imediata in memorie pe 2 octeţi (word)
8
MOV dword ptr[BP+5],25 - încărcare imediata in memorie pe 4 octet (double word)
MOV qword ptr[BP+5],25 - încărcare imediata in memorie pe 8 octet (quadword)
MOV tbyte ptr[BP+5],25 - încărcare imediata in memorie 10 octeţi(ten byte la VF)
STIVA 0
PUSH BX SP=SP-2 si BX [SP]
POP BX [SP] BX si SP=SP+2
SP BX Top vârful stivei
Alpha
N Y
Este echivalenta cu: MOV AX,offset adresa offset = adresa relativa calculata
La coprocesor nu exista dispozitiv de calcul al adresei si se poate folosi LEA
9
LDS reg16,dwpointer - reg16=offset adresa DS= adresa segment
LES reg16,dwpointer
Încarcă registrul segment DS sau ES si registrul general de la o adresa de 4 octeţi unde se găseşte
adresa relativa a operandului si adresa segmentului din care face parte. Se foloseşte la comunicarea intre
segmente pentru pregătirea registrelor de segment.
SI DS sauES
Adunare ADD
Adunare cu carry ADC reg,reg
Scădere SUB reg,mem
Scădere cu SBB dest,sursa mem,reg Lungime
împrumut (borow) reg,const 1, 2 sau 4
SI logic pe bit AND mem,const octeţi
SAU OR
SAU Exclusiv XOR
Comparaţie (scadere) CMP
Comparaţie cu SI TEST
Instrucţiunile logice se fac bit cu bit iar indicatorii se poziţionează funcţie de întregul rezultat. Pentru a
selecta un bit sau un grup de biţi din rezultat se foloseşte o mască.
C=1 nu înseamnă depăşire.
Depăşirea poate apărea la adunarea numerelor de acelaşi semn şi S diferă de acest semn.
La adunarea numerelor negative apare obligatoriu C=1 fără a fi depăşire.
10
depasire transfer spre S depas.
Comparaţia CMP dest,sursa face scădere dest-sursa fără a modifica dest, dar cu poziţionarea indicatorilor
funcţie de rezultatul scăderii.
S=0 dest > sursa S=1 dest < sursa Z=1 dest=sursa
Comparaţia TEST dest,sursa face un SI logic intre biţii din dest şi sursă fără a modifica dest, dar cu
poziţionarea indicatorilor funcţie de rezultat.
Z=1 toţi bitii din rezultat sunt 0, Z=0 cel puţin un bit din rezultat este 1 (S nu are sens)
Indicatorii de condiţie se pot modifica prin program:
Instrucţiunile LAHF şi SAHF sunt folosite pentru a prelua indicatorii de condiţie din coprocesor şi ai testa
in procesor folosind instrucţiunile de salt condiţionat JZ. Reamintim că nu exista instrucţiuni de salt la
coprocesor.
Calculele zecimale se fac în binar pe un octet, utilizând obligatoriu registrul AL şi sunt urmate de o
corecţie zecimală. Corecţiile zecimale nu au argumente şi folosesc informaţii din indicatorii de condiţie C
şi AC (auxiliar carry).
11
Corecţia constă în a aduna 6 la cifrele hexa ale rezultatului care depăşesc 10.
Vom exemplifica pentru DAA si AAA
DAA AAA
operanzi BCD 54 + operanzi 34+
78 ASCII 38
Rezultat binar CC + 6C
Corecţie +auxcarry 66 corecţie 6
Rezultat zecimal 32 Forţează 0 si C=1 02 +
30
Rezultat ASCII afişabil 32
Adresa
100 MOV SI,0 ; index I=1 –registrul de segment implicit este DS
103 MOV CX,8 ; contor pentru cicluri (număr de elemente tablou)
106 MOV AX,[SI+0] ;AX=X(I)
109 ADD AX,[SI+10] ;AX=X(I)+Y(I)
10C MOV [SI+20],AX ; memorare rezultat la Z(I)
10F ADD SI,2 ; incrementare index pentru rândul următor(I=I+1)
112 LOOP 106 ; salt pentru CX # 0 şi face CX=CX-1
114 INT 3 ; terminare program si revenire in AFD
Pogram 2 de adunare a doua numere zecimale BCD sau ASCII de lungime 8 octeţi.
Adunarea se va face din dreapta spre stânga octet cu octet. Se memorează in Carry transportul dintre ranguri
si aduna la fiecare rang si carry cu ADC (iniţial C=0). Programul permite operaţii pe orice lungime,
modificând numărul de octeţi (CX)
DS:0 X SI
12
.. 31 35
DS:10 Y +
.. 33 39
DS:20 Z =
.. 35 34
Operaţiile aritmetice sunt definite în dispozitivul aritmetic pentru numere subunitare, dar pentru
adunare şi scădere sunt valabile şi pentru numerele binare întregi. Considerăm 2 numere întregi A şi B
pentru care facem o adunare pe 16 biţi. Din punct de vedere al dispozitivului aritmetic adunarea se face ca
pentru numere subunitare cu virgula după bitul de semn şi avem:
Ca sa obţinem rezultatul corect in întreg (A+B) trebuie ca rezultatul sa-l înmulţim cu 2**15 adică sa
deplasam virgule cu 15 cifre binare spre dreapta.
(A+B)=(A+B)*(2**-15)*2**15
15 ……2 1 0
S
Virgula zecimala pt nr. întreg
Virgula zecimala pentru nr. subunitar
13
Sunt instrucţii cu un singur operand, deînmulţitul/deîmpărţitul este implicit în registrul acumulator (Al, AX,
EAX), iar celălalt operand poate fi într-un registru sau în memorie.
Rezultatul înmulţirii este de lungime dublă faţă de operanzi şi se obţine pentru operanzi pe 16biţi în DX şi
AX în prelungire.
La înmulţire numerele se consideră subunitare şi niciodată nu poate apare depăşire.
La IMUL (înmulţire de întregi cu semn) se face o corecţie de deplasare spre dreapta a rezultatului cu o
poziţie binară. Numerele sunt văzute ca subunitare şi avem:
Pentru ca rezultatul sa fie corect în întreg virgula trebuie deplasată cu 30 poziţii spre dreapta, deci în faţa
ultimei cifre binare. Rezultatul obţinut trebuie împărţit la 2, care echivalează cu o deplasare dreapta cu un
bit.
IMUL
15 0
AX S X X - număr întreg în AX (X*(2**-15)
*
Op16 S Y Y – număr întreg pe 16biţ (Y*(2**-15)
31 = 0
Rez 32cb S X* Y 0 Rezultat X*Y pe 32 biţi în DX şi AX
DX AX (X*Y)*2**-30 necesare 30 depl.dreapta
Virgula ca nr.zecimal - virgula ca număr întreg
Impărtirea presupune ca deîmpărţitul este în registrul acumulator (AX, DX:AX sau EDX:EAX)
împărţitorul este într-un registru sau memorie.
La împărţire trebuie să avem deîmpărţitul < împărţitorul văzute ca numere subunitare fiindcă rezultatul
trebuie să fie subunitar. În caz contrar avem depăşire.
In figură văzut ca subunitar 4250 < 35 şi nu apare depăşire .
Restul are semnul deîmpărţitului.
IDIV 1 0
5
DX:AX S X 4250 X - număr întreg în AX (X*(2**-30)
14
/
Op16 S Y 35 Y – număr întreg pe 16biţ (Y*(2**-15)
3 = 0
1
Rez 16biţi S Rest Cât Rezultat X/Y pe 16 biţi
DX AX în DX -rest şi AX – cât
Virgula ca nr.zecimal - virgula ca număr întreg
La împărţire numărul din AX trebuie extins spre stânga în DX, prin copierea bitului de semn. Operaţia se
face prin intrucţiunile:
CBW - Convert Byte to Word - extindere AL pe AX
CWD - Convert Word to Double word - extindere AX pe DX:AX
CDQ - Convert Double word to Quad word - extindere EAX peEDX:EAX
Există şi instrucţiuni de extindere cu Zero MOVZX sau cu Semn MOVSX prin mutare:
MOVSX CX,BL
MOVZX EAX,CX
MOV AX,4520
CWD - extindere pe DX:AX
IDIV CX - Cât în AX şi Rest în DX
Exemplu de calcul expresie: E=(A*B+C)/(A+B) unde A,B,C sunt numere întregi 16 biţi
MOV AX,A
15
Deplasările aritmetice - spre stânga se consideră înmulţiri cu 2**N ţi pot da depăşire
- spre dreapta se consideră împărţiri cu 2**N
La toate deplasările biţi care ies din registru trec prin Carry.
Prezentăm în figurile de mai jos modul de efectuare a operaţiilor de deplasare:
S
0 C SHR Shift logicRight
S
C ROR Rotate Right
S
C ROR Rotate Right whith carry
Testarea unui bit dintr-un registru se face prin deplasarea lui în Carry sau în Semn.
Testarea mai multor biţi dacă sunt pe 1 se poate face prin secvenţa:
MOV AX,X
AND AX,0C0H - masca ce indică primi 2 biţi
CMP AX,0C0H - verifica dacă rezultatul este egal cu masca
JZ OK - cei 2 biţi sunt pe 1
Dacă trebuie verificaţi biţii care sunt pe 0 se face înainte complementarea lui X (NOT).
Testarea unui bit se face şi prin instrucţiunea TEST care face AND între cei 2 operanzi, poziţionează
indicatorii de condiţie, fără a modifica operandul destinaţie. Se poate folosi instrucţiunea imediată cu masca
bitului testat:
16
TEST AX,02H
JNZ bit2 ; bitul 2 din dreapta este 1
3. LIMBAJUL DE ASAMBLARE
Programul sursă scris în limbaj de asamblare va avea extensia .ASM şi trebuie să treacă prin mai
multe faze pentru a fi transformat în program executabil direct (Prog.EXE).
Asamblorul prelucrează un fişier text sursă (Prog.asm), scris cu un editor de texte şi generează un
modul obiect (Prog.obj) care conţine instrucţiuni şi date ce sunt plasate de la adresa 000. Se mai generează
şi un fişier listing al programului compilat (Prog.lst). Programul sursă poate face referire prin directiva
INCLUDE şi la alte fişiere sursă (subprograme), care vor fi înglobate prin copiere în programul sursă.
Modulele obiect nu sunt executabile, dar pot fi depuse in biblioteci (Bibl.lib).
LINK EDITORUL prelucrează modulele obiect obţinute prin compilare (asamblare) şi alte module
obiect din biblioteci. Din asamblarea lor rezultă un program executabil (Prog.exe), în care adresele
17
modulelor şi adresele relative din instrucţiuni sunt recalculate şi se face legătura între modulele care fac apel
la alt modul (subprograme). Adresele din instrucţiuni se recalculează relativ la începutul segmentului ţinând
cont de adresa modulului în segment. Un program poate conţine mai multe segmente. Adresele simbolice
definite în alt modul trebuie date ca EXTRN, iar cele care sun referite din exterior declarate cu PUBLIC.
Asamblorul va genera câte un tabel cu etichetele referite în exterior (EXTRN) şi unul cu etichetele
care pot fi referite din exterior (PUBLIC), în care se specifică adresa lor din modul. Tabelele de definiţii
externe şi referinţe externe se păstrează în modulele obiect şi vor fi folosite de linkeditor pentru rezolvarea
referinţelor externe prin completarea adreselelor care fac referire la etichete din alte module. În fişierul
Prog.map se găsesc noile adrese ale modulelor şi ale etichetelor definite ca externe.
Programul executabil (Prog.exe) poate fi lansat ca o comandă DOS, care prelucrează datele şi se
obţin rezultatele. Prin programul EX2BIN se poate obţine o variantă Prog.com a programului.
20 c1 mov ax,bx
n2 Definiţii externe Pr2
0 Pr3.obj n1+n2 Simbol Adr.unde
e definit
c1 20
n n3 n
Tipuri de constante
B binare 0111011B
H hexazecimale 0BA56H ; MOV CX,0FFH
O octale 6573Q ; MOV SI,342Q
D zecimal 4586D sau 7500 ; implicit numerele se consideră zecimale
18
DD Define Double word ; definire pe 4 octeţi
DQ Define Quadword ; definire pe 8 octeţi
DT Define Ten Byte ; definire pe 4 octeţi
EQU constanta ; da etichetei valoarea constantei
ORG adresa ; forţează contorul de amplasare la adresa specificată
ALIGN n ; unde n=1,2,4,8,16 aliniere contor amplasare la multiplu
INCLUDE fisier.asm ; copiază în acel loc o secvenţă de program (subprogram)
Exemple:
A1 DB 12,0,0ACH,345Q,041H,’TREN rapid’
A2 DW 9542,0DE89H,20,0,’TR’
A21 DW A1,A2 ; se generează adresele relative a lui A1 şi A2
A4 DD 54,89589BAH
A41 DD A1,A2 ; adresele relative a lui A1 şi A2 cu adresa segmentului
A7 DW 20 DUP(20h)
P1 EQU 16 ; eticheta P1 echivalată cu 16 (adresă port)
MOV DX,P1 ; DX=16
CR EQU 0DH ; Cod ASCII CR
Definire segmente
Un segment este cuprins între directivele SEGMENT şi ENDS
nume_seg SEGMENT [align],[combinare],[’clasa’]
....
nume_seg ENDS
align - page - segmentul începe la multiplu de 256
- para - multiplu de 16 (paragraf)
- word - multiplu de 2
- byte - multiplu de 1
19
Combinarea cu alte segmente:
- none -implicit
- public
- common - segmente care se încarcă în paralel în aceeaşi zonă de memorie
- memory -segmente tratate împreună de editor şi plasate la sfârşitul memoriei
- AT adresa - specifică adresa la care se încarcă segmentul
- stack - segment definit ca stivă şi tratat ca public ( bazat cu SS)
ASSUME CS:seg1,DS:seg2,ES:seg3,SS:seg4 precizează registrele segment utilizate la adresarea
datelor din fiecare segment.
Dacă programul conţine numai câte un segment de fiecare tip se poate simplifica scrirea specificând
unde începe segmentulde code .CODEde date DATA şi stivă .STACK. Rezervarea spaţiului pentru stivă se
face pe lungimea dată şi automat se încarcă reg.SS.
20
Modulul de date se numeşte implicit @DATA referit pentru încărcare registru segment DS. Dacă se
scriu programe complexe cu multe segmente de diferite tipuri trebuie să se utilizeze segmentarea explicită
prin definire segmente cu nume cu directiva SEGMENT.
; ---------------------------------------------------Lab3_1.doc
; Programul numara bitii de 1 din fiecare element
; al tabloului X si memoreaza numarul de biti
; in elementele tabloului NX
; ---------------------------------------------------
Dosseg ; mod DOS de tratare segmente
.model small ; model pe cu segmente de 64Ko
.stack 256 ; rezervare 256 octeti pentru stiva
; Segmentul de date
; -------------------------------------
.data
X dw 7676h,9541h,5463h,2234h,0FFEEh
NX db 5 dup(0) ; nr biti elemente tab X
N equ 5 ; numar elemente tablou X
; Segmentul de code al programului
; -------------------------------------
.code
st1: mov ax,@data ; initializare registrul segment de date DS
mov ds,ax ;
mov si,0 ; index in tabloul X
mov di,0 ; index in tabloul NX
mov dh,N ; nr. elemente tablou
; Ciclu pentru numarare biti element X(I)
c1: mov ax,X[si] ; incarcare element X(I)
mov cx,16 ; numar ranguri binare
c2: shl ax,1 ; deplasare stinga cu un rang
jnc c3 ; bitul este zero
inc NX[di] ; bitul este 1
c3: loop c2 ; urmatorul rang
add si,2 ; urmatorul elment din X(I)
inc di
dec dh ; verificare sfirsit tablou X
jnz c1
int 3 ; terminare program
end st1 ; adresa lansare program
Programul execută calcule şi funcţie de rezultatele obţinute, se poate ramifica utilizând instrucţiunile
de salt condiţionat şi necondiţionat.
21
După fiecare instrucţiune aritmetică sau logică, funcţie de valoarea rezultatului se poziţionează
indicatorii de condiţie, care pot fi testaţi de instrucţiunile de salt condiţionat. Trebuie menţionat că
instrucţiunile de mutare şi cele de salt nu modifică indicatorii.
Saltul de tip far (îndepărtat) se face între segmente şi se modifica atât IP cât şi registrul de segment CS în
care se încarcă adresa segmentului care conţine eticheta destinaţie.
S1 SEGMENT
EXTRN et5:FAR - definire et5 ca etichetă externă
......
JMP far ptr et5 - salt în segmentul S2 care conţine eticheta et5
.....
S2 SEGMENT
PUBLIC et5 - definire eticheta et5 ca definiţie externă
Et5 LABEL FAR - definire eticheta et5
La salturile indirecte adresa la care se face saltul se specifică într-un registru. Adresa poate sa să se
refere la un tabel de adrese de salt care pot fi selectate prin modificarea dinamică a registrului folosind
indexarea.
22
JMP word ptr [BX] - BX conţine adresa unei tabele de adrese de salt
In exemplul de mai sus s-au generat 2 tabele cu adrese de salt. Tabela Tadr1 conţine adrese locale în
segment generate pe 16 biţi (NEAR) ce vor fi încărcate în IP, iar Tadr2 conţine adrese de tip FAR generate
pe 4 octeţi care conţin adresa relativă în segment (deplasament) şi adresa segmentului din care face parte
eticheta şi care va fi încărcată în registru CS. Eticheta et1 care este locală, în Tadr1 se generează pe 2 octeţi
iar în Tadr2 se generează pe 4 octeţi fiindcă face parte dintr-un tabel de adrese de tip FAR.
In registru BX s-a încărcat tabela de adrese locale pe 16 biţi Tadr1 şi în registrul SI adresa relativă a
unei adrese de salt din tabelă ca multiplu de 2. La JMP word ptr [BX] se sare la una din adresele et1,et2 sau
et3. Prin word ptr se precizează că adresele de salt sunt pe 2 octeţi şi valoare se încarcă în registru IP. La
JMP far ptr [BX] se apelează o adresă din tabela Tadr2 şi primi 2 octeţi se încarcă în IP iar următorii 2 în
CS.
Instrucţiunile de salt sunt de tip SHORT (+127 la -127) sau NEAR ( procesoa-rele pe 32 de biţi)
şi pot referi etichete numai din segmentul curent. Ele nu pot referi etichete din alt segment. Forma generală
a instrucţiunii este:
23
Transport C=1
Paritate para P=1 - numărul biţilor de 1 este par
Depăşire O=1
4.3. Proceduri
24
Parametrii procedurii se plasează înaintea chemării în registre, intr-o zonă de memorie sau în stivă.
La scrierea procedurii se stabileşte modul de transmitere a parametrilor. Parametrii pot fi transmişi prin
valoare sau prin adresă. Tehnicile de transmitere a parametrilor spre subprograme se vor discuta în capitolul
4.
Vom exemplifica cu utilizarea unei proceduri care face media a 2 numere întregi X şi Z care se
plasează în registrele AX şi BX. Rezultatul se obţine la ieşirea din procedură în AX şi se va plasa la
revenirea în programul principal în variabila Z.
DOSSEG
.MODEL SMALL
.STACK 100H
.DATA
X DW 2540
Y DW 15417
Z DW 0 ; Z=(X+Y)/2 rezultat
C2 DW 2 ; constanta 2
.CODE
; Pregătire parametrii...
ST1: MOV AX,X ; primul parametru
MOV BX,Y ; parametru 2
CALL Pmed ; chemare subpr. Adr.de revenire în stivă (Top stiva=IP)
MOV Z,AX ; memorare rezultat
...
Pmed PROC NEAR ; procedură locală (near)
ADD AX,BX ; AX= X+Y
CWD ; se putea SHR AX,1
IDIV C2 ; AX=(X+Y)/2
RET ; revenire în program la adresa de revenire din stivă (IP=Top stivă)
Pmed ENDP ; sfârşit procedură
END ST1
La chemarea unui subprogram prin CALL, se pune adresa de revenire (IP) în stivă şi se sare la
prima instrucţiune din procedură (IP=offset Pmed). In procedură se execută secvenţa de instrucţiuni până la
instrucţiunea RET, care încarcă în IP adresa din vârful stivei revenind la instrucţiunea următoare după
CALL.
Instrucţiunea CALL se deosebeşte de JMP doar că depune în stivă registru de instrucţiuni IP, care va
fi utilizat de RET pentru a reveni în program şi a continua cu instrucţiunea următoare.
La chemarea unei proceduri de tip FAR, care poate fi în alt segment, instrucţiunea CALL are adresa
pe 4 octeţi şi depune în stivă atât IP cât şi CS şi încarcă din adresa instrucţiunii noile valori pentru IP şi CS.
O procedură de tip FAR se deosebeşte de una de tip NEAR doar prin faptul că instrucţiunea RET
incarcă din stivă atât adresa de revenire în IP cât şi adresa segmentului în CS. Se recomandă ca procedurile
să fie globale (de tip FAR) pentru a putea fi păstrate în orice segment şi să poată fi apelate din oricare
segment de program. Instrucţiunea RET are codul C3H pentru proceduri de tip NEAR şi CBH pentru cele
de tip FAR.
Far CALL
- pune în stivă IP şi CS
- salt în afara segmentului curent şi trebuie modificat IP şi reg. CS
Luăm pe rând cifrele şi eliminăm primi 4 biţi (3 din faţă) şi obţinem valoarea lor în binar.
Calculul numărului binar corespunzător îl facem iterativ folosind valoarea cifrele codificate în binar
astfel:
N=1*10000+4*1000+2*100+5*10+7
Se poate calcula iterativ fără a folosi puterile lui 10 după algoritmul
N=0 N=((((0+1)*10+4)*10+2)*10+5)*10+7
Programul prezentat mai jos citeşte de la tastatură un număr ASCII de maxim 5 cifre ASCII
( reprezentabil pe 2 octeţi) memorat la adresa Z1 şi apelează o procedură de conversie care funcţionează
după acest algoritm.
26
Funcţia DOS de afişare mesaj are codul 9 (09H) care se pune în AH şi cere adresa mesajului în DX.
Mesajul de afişat se va termina obligatoriu cu $.
Funcţia DOS de citire mesaj de la tastatură are codul 10 (0AH), care se pune în AH şi cere adresa
şirului de recepţionat în DX. Zona ce recepţionează şirul (Z1) are în primul octet numărul de octeţi maxim
aşteptaţi, iar în octetul 2 numărul de octeţi recepţionaţi (şirul se termină cu enter).
La chemarea procedurii de conversie CZB în BX se încarcă adresa primului caracter din şirul de
cifre zecimale şi în CX numărul de cifre zecimale. Rezultatul va fi returnat în registrul AX
; --------------------------------------
; Conversie zecimal ASCII - binar 2 octeti
; --------------------------------------
.286c
dosseg
.model small
.stack 100
.data
; numar zecimal ASCII introdus de la tastatura
z1 db 10,0,10 dup (30h),10,13,'$' ; nr zecimal
zece dw 10
n db 0 ; numar cifre zecimale
dw 17394 ; pentru verificare rezultat
bin dw 0 ; numar binar rezultat
m1 db 13,10,'Introduceti un numar de 5 cifre:',13,10,'$'
.code
st1: mov ax,@data
mov ds,ax
mov dx,offset m1 ; afisare mesaj dialog
mov ah,9
int 21h
mov dx,offset z1 ; adresa numar zecimal
mov ah,10 ; asteptare numar
int 21h
mov bx,offset z1+2 ; adresa prima cifra
mov cx,0
mov cl,z1+1 ; numar de cifre numar zecimal
call czb ; procedura conversie zec-bin
mov bin,ax ; memorare numar binar
int 3
; -----------------------------------------
; Procedura conversie zecimal ASCII -binar 2 octeti
; - intrare BX = adresa numar zecimal, CX = numar cifre zecimale
; - iesire AX = numar binar
; -----------------------------------------
czb proc
xor ax,ax ; AX = 0
mov si,ax ; index prima cifra
mov n,cl ; numar cifre zecimale
c3: mov cl,[bx+si] ; incarcare cifra ASCII
27
and cl,0fh ; anulare primii 4 biti
mul zece ; N = N*10
add ax,cx ; N = N*10 + cifra
inc si ; urmatoarea cifra
dec n
jnz c3
ret
czb endp
end st1
Considerăm un număr binar N pe 16 biţi care trebuie afişat pe monitor în ASCII. Conversia în
zecimal se face în procedura CBZ, împărţind repetat numărul cu 10 şi reţinem resturile împărţirii din DX,
care se memorează într-o zonă ZEC din dreapta spre stânga. Ieşirea din ciclu se face când câtul împărţirii
din registrul AX este zero.
La intrarea în procedură se verifică dacă numărul este negativ, caz în care se complementează şi se
poziţionează un indicator (CH=1). Înainte de ieşirea din procedură se verifică indicatorul şi dacă numărul a
fost negativ i se pune un – în faţă, iar dacă a fost pozitiv se pune un +.
La chemarea procedurii se încarcă în AX numărul binar ce trebuie convertit, în BX adresa zonei
ZEC unde se va pune şirul zecimal şi în SI poziţia ultimului octet în şir.
La revenirea din procedură se afişează rezultatul cu functia DOS având codul 9.
Se putea utiliza numai SI care să conţină adresa ultimului octet din şir
MOV SI,offset zec+5
.286c ; --------------------------------------
dosseg ; Conversie binar - zecimal ASCII
.model small ; --------------------------------------
.data
; numarul zecimal ASCII rezultat se afiseaza
zec db 6 dup (20h),10,13,'$' ; rezultat zecimal
zece dw 10
n db 0
bin dw -17394 ; numar binar de convertit
m1 db 13,10,'Numarul in zecimal este:',13,10,'$'
.code
st1: mov ax,@data
mov ds,ax
mov dx,offset m1 ; afisare mesaj de dialog
mov ah,9
int 21h
mov si,6-1 ; index ultima cifra zecimala
mov bx,offset zec ; adresa zona numar zecimal
mov ax,bin ; numar binar
call cbz ; conversie binar zecimal
mov dx,offset zec ; afisare rezultat conversie
28
mov ah,09h
int 21h
mov ah,4Ch ; terminare program – iesire in DOS
int 21h
.286c ;---------------------------------------
Dosseg ; Utilizare subprograme de conversie
.model small ; Calcul c = a*b de la tastatura
.data ; --------------------------------------
Prelucrarea textelor este o operaţie foarte frecvent întâlnită în editoarele de texte şi compilatoare.
Din acest motiv de la primele calculatoare comerciale, pentru a obţine o performanţă ridicată, s-au introdus
instrucţiuni specializate pentru prelucrarea şirurilor de caractere (în 1965 IBM 360). Din această categorie
fac parte operaţiile:
Mutare şir de caractere MOVS (Move String)
Ştergere zonă de memorie STOS (Store String)
Încărcare ciclică elemente şir LODS (Load String)
Comparare şiruri de caractere CMPS (Compare String)
Căutare caracter în şir SCAS ( Scan String)
Traducere şir dintr-un cod în altul XLAT
Mutare şir
Mutarea unui şir de octeţi (caractere) dintr-o zonă de memorie în alta se poate face printr-un ciclu
utilizând instrucţiunile de transfer, chiar şi între segmente:
MOV SI,offset Sir1 ; adresa sir1
MOV DI,offset,Sir2 ; adresa sir2
MOV CX,Lung ; Lungime şir ( număr de cicluri)
C1: MOV AL,DS:[SI] ; încarcă un caracter din prima zonă
MOV ES:[DI],AL ; Mută în Zona 2 (chiar în alt segment)
INC SI ; incrementare indexi pentru caracterul următor
INC DI
LOOP ; ciclu
DS:Si
Sir1 F A C U L T A T E
ES:Di
Sir2 F A C U L T A T E
Această operaţie poate fi făcută mai simplu utilizând instrucţiunea MOVSB, care nu are argumente şi cele
două şiruri şi lungimea transferată se specifică în registre.:
31
MOVSD - mută 4 octeţi (dword) de la adresa DS:SI la adresa DS:DI
- SI=SI+4 pentru D=0 şi SI=SI-4 pentru D=1
Sir1 Sir2
F A C U L T A T E MOVSB
F A C U F A C U F A C U F D=0 stg-dr
F A C U F A C U L T A T E D=1 dr-stg
LODS (Load String) încarcă un element de la adresa DS:SI în AL, AX, sau EAX şi incrementează
(D=0) sau decrementează (D=1) registrul index SI. Are formele:
LODSB [DS:SI] AL şi SI=SI+/-1,2,4
W AX
D EAX
STOS (Store String) memorează conţinutul registrului AL, AX sau EAX la adresa destinaţie ES:DI
şi incrementează (D=0) sau decrementează (D=1) registrul index DI.
STOSB AL [ES:DI] şi DI=DI+/-1,2,4
W AX
D EAX
SCAS (Scan String) compară succesiv elementele unui şir de la adresa ES:DI cu conţinutul
registrului AL, AX sau EAX şi poziţionează indicatorii de condiţie. Se pot astfel căuta caractere într-un şir.
SCASB AL compară cu [ES:DI] şi DI=DI+/-1,2,4
W AX
D EAX
CMPS compară şirul indicat de DS:SI cu şirul indicat de ES:DI element (caracter) cu element şi
poziţionează indicatorii de condiţie. Comparaţia se face prin scădere din elementul indicat de DS:SI cel
32
indicat de ES:DI. Operaţia se poate face prin repetiţie şi se va opri la primul element diferit din cele 2
şiruri care va poziţiona indicatorii şi va da sensul comparaţiei.
CMPB [DS:DI] se compară cu [ES:DI[ şi SI=SI+/-1,2,4
W AX DI=DI+/-1,2,4
D EAX
Toate instrucţiunile pe şiruri pot fi repetate atâta timp cât CX # 0. Ieşirea din ciclu se face când
CX=0 sau funcţie de valoarea indicatorului Z. REP nu se aplică la instrucţiunile aritmetice şi logice.
Pentru pregătirea registrelor se pot folosi şi instrucţiunile care încarcă adrese dacă se cer transferuri
de date între segmente:
LDS reg,dwpointer IP=offset adresa, DS =adresa segment
LES reg,dwpointer IP=offset adresa, ES =adresa segment
Căutarea unui caracter punct într-un şir se poate face folosind SCASBcu secvenţa:
CLD ; setare direcţie stânga - dreapta
MOV CX,200 ; lungime şir
MOV DI,offset sir ; adresa şir
MOV AL,’.’ ; caracter căutat punct (de referinţă)
REPNZ SCASB ; ciclu atâta timp cât caracterul nu este punct
; -------------------------------------Lab5_0.doc
; Programul exemplifica modul de utilizare a
; instructiunilor de prelucrare siruri de caractere
; -------------------------------------
33
pr1 segment
assume cs:pr1,ds:pr1,es:pr1
n equ 25
sir1 db 'facultatea calculatoare $'
sir2 db 30 dup(20h)
sir3 db 'facultatea mecanica $'
zona db 50 dup('A'),'$'
st1: mov ax,pr1
mov ds,ax
mov es,ax
; Muta zona de memorie
; -------------------------------------
mov cx,n ; lungime sir
mov si,offset sir1 ; sir sursa
mov di,offset sir2 ; zona destinatie
cld ; df=0 directie stinga dreapta
rep movsb ; mutare sir
; Sterge zona
; -------------------------------------
mov al,'B' ; caracter ce se copiaza
mov di,offset zona ; adresa inceput zona
mov cx,20 ; lungime zona
rep stosb ; memorare reg AL in zona
; Translatie zona spre dreapta
; -------------------------------------
std ; DF=1 directie dreapta-stinga
mov cx,16 ; lungime sir
mov si,offset sir2+15 ; adresa ultim octet din sir
mov di,offset sir2+26 ; adresa ultim octet destinatie
rep movsb ; mutare sir dreapta-stinga
; Comparatie siruri: sir1 cu sir3
; -------------------------------------
mov si,offset sir1 ; adresa sir sursa
mov di,offset sir3 ; adresa sir destinatie
mov cx,16 ; lungime de comparatie
cld ; DF=0 directie stinga-dreapta
repe cmpsb ; repeta atit timp cit octetii sint egali
jl calc ; sir1 < sir3 ( primul octet diferit)
mov dx,offset sir3 ; afisare sir3
jmp short c2
calc: mov dx,offset sir1 ; afisare sir1
c2: mov ah,9 ; functie afisare
int 21h
; Cautare punct in sir1
; -------------------------------------
mov di,offset sir1 ; adresa sir
mov cx,25 ; lung sir
cld ; DF=0
mov al,'.' ; caracter cautat (referinta)
repnz scasb ; cautare octet = AL
34
mov dx,di ; afisare restul sirului
mov ah,09h
int 21h
; Cauta caracter diferit de 'B' in zona
;---------------------------------------
mov di,offset zona ; adresa zona de memorie
mov cx,50 ; lungime zona
mov al,'B' ; caracter de referinta
repz scasb ; cauta primul octet # AL
mov dx,di ; afisare text ce urmeaza
mov ah,09h
int 21h
int 3h ; revenire in AFD
mov ax,4C00h ; revenire in DOS
int 21h
pr1 ends
end st1
; -------------------------------------Lab5_2
; Afisare text fara prima propozitie
; -------------------------------------
pr1 segment
assume cs:pr1,ds:pr1,es:pr1
mesaj db 13,10,'Introduceti un text: ',13,10,'$'
mesaj1 db 13,10,'Textul scurtat este: ',13,10,'$'
sir1 db 50,0,50 dup (' '),'$'
st1: mov ax,pr1
mov ds,ax
mov es,ax
mov dx,offset mesaj
mov ah,09h
int 21h
mov dx,offset sir1 ; asteptare text
mov ah,10
int 21h
mov bl,(sir1+1) ; lungime text introdus
mov bh,0
mov (sir1+2).[bx],'$' ; caracterul $ la sfirsit
cld ; directie stinga dreapta
mov di,offset sir1+2 ; adresa text
mov cx,50 ; lungime maxima
mov al,'.' ; caracter cautat
repnz scasb ; cautare '.'
mov dx,offset mesaj1 ; afisare mesaj
mov ah,09h ; DI poziţionat pe primul octet după punct
int 21h
mov dx,di ; afisare rest text
mov ah,9
int 21h
mov ah,4ch ; terminare program cu iesire in DOS
35
int 21h
pr1 ends
end st1
XLAT este instrucţiunea care realizează traducerea unui text codificat într-un cod în alt cod folosind un
tabel de traducere plasat la adresa indicată de BX. Codul caracterului din AL este considerat index în tabelul
de coduri şi XLAT returnează în AL caracterul din tabelul de coduri corespunzător indexului .
BX XLAT
Tabel de coduri W A T Z E U F R C pentru AL=03
Index în tabel 0 1 2 3 4 5 6 7 8 .... rezultă AL=K
Pentru a converti un text scris cu litere mici în litere mari vom ţine cont că:
Literele mari au codurile: A 41H,B 42H,C 43H, E 44H, F 45H, G 47H, H 48H, I 49H
J 4AH, K 4BH,..... .....Y 59H, Z 5AH
Literele mici au codurile: a 61H, b 62H, c 63H, e 66H, f 65H, g 67H, h 68H, i 69H
j 6AH, k 6BH,..... .....y 79H, z 7AH
Codul lui ‚a’ 61H = 6 x 16 + 1 trebuie să fie index pentru ‚A’ în tabel. Prima literă din tabelul de
coduri va fi plasată la adresa 6 x 16 + 1=65. La începutul tabelei vom plasa 65 de spaţii, care vor înlocui alte
coduri care pot apare în afară de litere mici.
În continuare se trec codurile pentru litere mari în ordine alfabetică.
; -------------------------------------Lab5_1.doc
; Utilizare XLAT pentru codificare text
; Se convertesc literele mici in litere mari
; -------------------------------------
pr1 segment
assume cs:pr1,ds:pr1,es:pr1
n equ 25
; Tabela coduri
tcod db 6*16+1 dup(' '),'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
db 7 dup(' ')
; Text de codificat
text db 'facultatea de matematici aplicate$'
dw 20 dup(0)
; -------------------------------------
36
st1: mov ax,pr1
mov ds,ax
mov es,ax
mov bx,offset tcod ; adresa tabela coduri
mov si,0 ; index in text
mov cx,offset st1 - offset text -1 ; lungime text
c1: mov al,text[si] ; un octet din textul de tradus
xlat ; traducere octet
mov text[si],al ; memorare octet tradus
inc si ; urmatorul caracter de tradus
loop c1
; Afisare text dupa traducere
calc: mov dx,offset text
mov ah,9
int 21h
c2: mov ah,4ch ; iesire in DOS
int 21h
pr1 ends
end st1
37
IN AL,DX DXport AL - se citeşte din portul indicat de DX
AX,DX AX în AL,AX,EAX
EAX,DX EAX
DS:SI
Zona
Port
DX Adresa port
Instrucţiunea cu repetiţie se poate utiliza pentru a scrie în cuvintele de comandă ale unor cuploare
(placă video, disc,imprimantă ...). Pentru periferice nu se poate folosi REP, fiindcă nu se poate realiza
sincronizarea între viteza de transmisie DRAM şi viteza redusă a perifericului.
Citire şir de caractere dintr-un port într-o zonă de memorie indicată de ES:DI
Port2 EQU 50
CLD
MOV DI,offset buffer ; adresă zonă de memorie unde se citeşte
MOV DX,port2 ; adresa port utilizat
MOV CX,2000 ; număr de octeţi de citit
38
REP INSB ; citire 2000 octeţi din portul 50 în buffer
Subprogramele se pot considera nişte cutii negre legate între ele, care realizează o funcţie prin
prelucrarea parametrilor formali de intrare şi returnează rezultate transmise programului chemător prin
parametrii formali de ieşire. Pentru a realiza funcţia dorită se pot folosi algoritmi diferiţi care sunt
transparenţi pentru utilizator. Aceeaşi funcţie poate fi implementată prin subprograme diferite, care pot fi
echivalente.
X1
X2 Y1(X1,X2,...Xn)
... Subprogram Y2(X1,X2,...Xn)
..........
Xn
Definirea unui subprogram se face formal pe baza unui algoritm care primeşte variabile formale de
intrare, care sunt prelucrate de o secvenţă de instrucţiuni care calculează variabilele de ieşire.
39
Parametrii se pot transmite spre subprograme:
prin Valoare caz în care valoare parametrului se transmite subprogramului
prin Adresă când sunt tabele cu multe elemente şi adresa tabelului se transmite subprogramului,
care va folosi metode de adresare indirectă sau/şi indexată.
Din păcate nu există adresare indirectă prin memorie şi subprogramul nu se poate implementa în
acest mod. S-ar permite exploatarea variabilelor plasate în diferite locuri în programul principal direct din
subprogram. La calculatoarele clasice toate limbajele de programare foloseau această metodă de transmitere
a parametrilor spre subprograme.
40
6.3. Transmiterea parametrilor prin registre
Este cea mai simplă metodă de transmitere a parametrilor, dar este limitată pentru număr redus de
parametrii. In subprogram se recomandă să se salveze registrele care se modifică şi să se refacă înainte de
revenirea din subprogram (RET). Este mai simplă salvarea tuturor registrelor la început prin PUSHA şi
refacerea la sfârşit prin POPA. În registre se pot încărca valorile parametrilor sau adresa lor. In cazul
subprogramelor de conversie zecimal-binară şi binar-zecimală discutate deja, s-a transmis în BX adresa
şirului de cifre zecimale codificate în ASCII şi în AX numărul binar iniţial sau rezultat.
; --------------------------------------Vhexa.doc
; Afisare zona de memorie in hexa
; --------------------------------------
.286c ; set comun 286
dosseg
.model small
.data
date dw 65278,1234h,24,26,62,721
.code
st1: mov ax,@data
mov ds,ax
mov cx,6 ; numar de cuvinte
41
mov si,0 ; index in zona
l1: mov ax,date[si]
call far ptr pnum ; afisare hexa continut AX
add si,2 ; cuvintul urmator
loop l1
; Terminare program
mov ax,4C00h
int 21h
42
mov ah,2
int 21h
ret
; secventa de intarziere
mov cx,0fh ; secventa de asteptare afisare
del: push cx
mov cx,0ffh ; ciclul 2 de asteptare
del2: nop
loop del2
pop cx
loop del
popa
ret
putc endp
end st1
;---------------------------------------
Program de sortare caractere dintr-un text introdus de la tastatură
Se introduce de la tastatură un şir de maxim 80 caractere de lungime variabilă, care se memorează
într-un buffer. Se cheamă o procedură de sortare care utilizează metoda inversiunii şi ordonează caracterele
din buffer funcţie de valoarea codului ASCII. Procedura se poate modifica pentru a primi ca parametru în
BX adresa unui text oarecare precedat de lungimea lui (lungimea poate fi transmisă în CX).
* ====================================SORT.doc
* Sorteaza un sir de caractere prin metoda inversiunii
* ====================================
sdate segment ; segmentul de date
dim equ 80 ; lungime maxima tabel
buf db 80,0,dim dup(?) ; buffer pentru sirul de caractere
in_msg db 'introduceti sirul de caractere:',10,13,'$' ; mesaj dialog
out_msg db 'sirul sortat:',10,13,'$' ; mesaj de dialog
cr db 10,13,'$' ; carriage return si line feed
sdate ends ; sfarsit segment date
sstiva segment stack ; segment de stiva
db 100 dup(?) ; rezervare spatiu stiva
stiva equ $ ; eticheta baza stiva
sstiva ends ; sfarsit segment stiva
cod segment ; segment de cod
assume cs:cod,ss:sstiva,ds:sdate,es:sdate ; afectare reg.segment
start: mov ax,sdate ; incarcare adresa segment date in registrul DS
mov ds,ax
mov es,ax ; incarcare adresa segment date in registrul ES
mov ax,sstiva
mov ss,ax ; incarcare adresa segment stiva in registrul SS
43
mov sp,offset stiva ; incarcare adresa top stiva in registrul SP
mov ah,09h ; cod functie DOS afisare mesaj
mov dx,offset in_msg ; adresa mesaj
int 21h ; intrerupere DOS
mov ah,0ah ; cod asteptare sir de la tastatura
mov dx,offset buf; adresa buffer intrare
int 21h
mov ah,09h ; afisare CR,LF
mov dx,offset cr
int 21h
; pregatire chemare procedura
call sortare ; chemare procedura de sortare sir
mov ah,09h ; afisare mesaj - sirul sortat:
mov dx,offset out_msg
int 21h
mov ah,09h ; afisare sir sortat
mov dx,offset buf[2]
int 21h
mov ah,4ch ; terminare program, iesire in DOS
int 21h
* ================================
* Procedura sortare sir de caractere in zona buf
* ================================
sortare proc near ; declaratie procedura
sta: mov dx,0
mov cx,0
mov cl,buf[1] ; lungime sir introdus in CL
dec cx ; numar cicluri L-1
jz s_end ; nu s-au introdus caractere
44
s_end: mov bl,buf[1] ; lungime sir
mov bh,0
mov buf[bx+2],'$' ;inserarea $ dupa sirul sortat
ret ; iesire din procedura
sortare endp ;sfarsit procedura
cod ends ; sfarsit segment
end start ; adresa de lansare si sfarsit program
* =========================================
BX X
Zona memorie S N X(1) X(2) X(3) .........
(parametrii)
In programul prezentat se consideră tabloul X cu 5 elemente, dar el poate avea oricâte, deoarece el este
ultimul parametru. La chemarea procedurii in se încarcă în BX adresa zonei de memorie care conţine
parametrii. In procedură se descrie structura zonei de parametrii prin adresa lor relativa in zonă cu directiva
EQU. Mnemonicele S1, N1, X1 vor fi folosite în procedură pentru referirea indirectă prin BX a
parametrilor. Adresarea lui S pentru iniţializare se face prin:
mov word ptr [bx+s1],0 ; s=0
Trebuie folosit word ptr fiindcă nu se utilizează registru şi trebuie precizată lungimea operanzilor
folosiţi. Adresa BX + s1 este echivalentă cu BX +0. Pentru a referi un element de tablou direct în programul
principal se foloseşte şi indexarea cu SI:
c1: mov ax,[bx+x1+si] ; x[i]
; --------------------------------------Lab7_0
45
; Calcul medie elemente tablou X
; Parametrii spre subpr. transmisi prin zona de memorie
; --------------------------------------
DOSSEG
.MODEL SMALL
.STACK 256
.286C
.DATA
s dw 0 ; s = media
n dw 5 ; nr. elem. din tabloul x
x dw 1,-92,83,-424,53
.CODE
st1: mov ax,@DATA
mov ds,ax
mov bx,offset s ; adresa zona parametrii
call sp1 ; chemare subprogram
int 3 ; valoarea medie s-a memorat in S de catre procedura
; -----------------------------------------
; Procedura calcul medie elemente tablou
; Intrare: BX adresa zona parametri
; -----------------------------------------
sp1 PROC near
; Adrese in zona de parametrii
s1 equ 0 ; Suma rezultata
n1 equ 2 ; numar de elemente
x1 equ 4 ; Tabloul de elemente
pusha ; salvare registre
mov si,0 ;i=1
mov word ptr [bx+s1],0 ; s = 0
mov cx,[bx+n1] ; numar elemente
c1: mov ax,[bx+x1+si] ; x[i]
add [bx+s1],ax ; s=s+x[i]
add si,2 ; i=i+1
loop c1
mov ax,[bx+s1] ; AX = suma elemente
cwd ;extindere pentru impartire
idiv word ptr [bx+n1] ; s = s/n media
mov [bx+s1],ax ; memorare medie
popa ; refacere registre
ret
sp1 endp
46
end st1
Definirea structurii unei zone de memorie se poate face cu directiva STRUC, care creează o machetă şi
ataşează fiecărei etichete o adresa relativă la începutul zonei. Definirea echivalentă pentru zona de
parametrii din procedura anterioară se poate face:
Pentru variabilele din structură nu se rezervă spaţiu de memorie. Directiva DW este utilizată
numai pentru a preciza lungimile operanzilor şi a calcula adresele relative ataşate etichetelor. Folosind acest
mod de definire pentru o structura nu trebuie să calculăm poziţiile parametrilor în zonă. Dacă adăugăm noi
parametrii sau le modificăm lungimea, nu trebuie să ne preocupe ce adrese se generează, ca în cazul
utilizării directivei EQU.
O structură de date defineşte un tip ca o colecţie de una sau mai multe variabile, de tipuri diferite,
grupate sub un singur nume pentru utilizare.
nume_struc STRUC
-------- ; definiţie variabile formale
-------- ; care compun structura
nume_struc ENDS
Variabilele dintr-o structură pot fi declarate cu sau fără valori iniţiale. Valorile iniţiale sunt cele
implicite care servesc la generarea unei zone cu acea structură.
Putem defini tipul compus dată pe 4 octeţi format din zi, lună, an;
date STRUC ; definire structura data
zi db 0 ; ziua
luna db 0 ; luna
anul dw 0 ; anul
date ENDS
Putem defini o variabilă structurată de tip date şi cu valori ale câmpurilor:
D1 date <15,2,1978> ; 15 februarie 1978
47
Pentru a genera datele personale pentru un student vom scrie:
Radu <’Radu’,’Arad,25,15,9,75,’AC34F’> ; nume,adresa,varsta,datan,Cods
Toate limbajele de nivel înalt folosesc transmiterea parametrilor prin stivă, care este un caz
particular de transmitere a parametrilor printr-o zonă de memorie. In procedură trebuie definită structura
datelor din stiva.
In stivă procedura va găsi mai multe tipuri de date:
Parametrii subprogramului transmişi de programul principal
Adresa de revenire în programul principal (după CALL) - valoare lui IP şi CS
Registrele salvate de procedură
Variabilele locale ale procedurii
Stiva procedurii, care poate şi ea sa cheme subprograme
Pentru orice procedură se începe cu proiectarea structurii stivei şi definirea ei printr-o structură de date,
care se va folosi la adresarea parametrilor şi variabilelor locale.
Vom concepe un program care utilizează o procedură de calcul a mediei numerelor pozitive şi cele
negative dintr-un tablou de numere întregi cu semn.
Parametrii de intrare vor fi adresa tabloului (atx) şi numărul de elemente (nv)
Parametrii de ieşire sunt media elementelor pozitive MP şi negative MN
Variabile locale suma si numărul elementelor pozitive şi negative(S1,K1,S2,K2)
Se vor salva în stivă registrele BP, BX, FLAGS şi CX.
Cu aceste precizări structura stivei văzută de procedură va fi:
48
In procedură se fac secvenţele de operaţii;
Se salvează registrele şi se memorează SP în BP, care va deveni referinţa pentru adresarea
elementelor din stivă.
Se alocă spaţiu în stivă pentru cele 4 variabile locale (S1,K1,S2,K2) prin decrementarea cu 4*2=8 a
lui SP
Registrul SP va adresa în continuare stiva procedurii
Se defineşte structura Z şi adresele variabilelor locale faţă de BP
Se iniţializează variabilele locale
Se calculează printr-un ciclu suma elementelor pozitiveS1, a celor negative S2 şi numărul lor k1
respectiv k2
Se calculează media elementelor pozitive peste adresă tablou(ATX) şi negative peste N
Se eliberează spaţiul ocupat de variabilele locale prin incrementarea lui SP cu 8
Se refac registrele salvate
Se revine în programul principal cu RET care încarcă din stivă IP şi CS
Dacă la revenirea din procedură mai rămân parametrii reziduali în stivă se utilizează
RET N unde N este valoarea cu care se incrementează SP.
La revenirea în programul principal trebuie ca stiva să fie goală adică sa aibă aceeaşi poziţie ca la apelul
procedurii.
; -----------------------------------------Lab8_1
; Transmiterea parametrilor prin stiva
; Subprogram calcul medie elemente pozitive
; si negative dintr-un tablou X
; -----------------------------------------
NAME MEDIA1
SSTIVA segment 'stack'
dw 100 dup (?)
stiva equ $ ; virful stivei
SSTIVA ends
;------------------
;segment date
;------------------
SDATA segment
MP dw 0 ; medie elemente - pozitive
MN dw 0 ; - negative
N dw 10 ; numar elemente tabel X
X dw 15,-12,-6,19,-7,17,18,0,-1,1
SDATA ends
;-------------------------
;segment program principal
;-------------------------
SPR segment
assume cs:SPR,ds:SDATA,ss:SSTIVA
st1: mov ax,SDATA ; initializare registre segment
mov ds,ax
49
mov ax,SSTIVA
mov ss,ax
mov sp,offset stiva
; ------------------
; Chemare subprogram
; ------------------
push N ; depune in stiva - nr.elemente
mov ax,offset X ; - adresa tablou
push ax
call far ptr medie ; chemare subprogram
; rezultatele s-au depus in stiva peste parametrii de intrare
pop MP ; extrage medie elem. - pozitive
pop MN ; - negative
int 3
; ------------------------------------------
; Subprogram calcul medie elemente pozitive
; si negative dintr-un tablou X
; ------------------------------------------
MEDIE proc far
; Pregatire stiva
push bp ; salvare reg BP
mov bp,sp ; reg bp baza in stiva
push bx ; salvare registre
pushf
push cx
sub sp,8 ; alocare spatiu variabile locale
; --------------
; Corp procedura
; --------------
; Structura stiva relativ la adr. de baza din BP
; Zona variabile locale
s1 equ -14 ; suma elemente pozitive
k1 equ -12 ; contor elemente pozitive
s2 equ -10 ; suma elemente negative
k2 equ -8 ; contor elemente negative
z struc ; descriere structura parametrii
bpv dw ? ; reg BP vechi
ipv dw ? ; reg IP - adresa de revenire
csv dw ? ; CS - adresa segment prog.principal
atx dw ? ; adresa tabel X
nv dw ? ; nr. de elemente tablou X
z ends
50
; -------------
; initializare variabile
mov cx,word ptr [bp+nv] ; contor cicluri
mov bx,word ptr [bp+atx] ; BX adresa tablou X
mov ax,0 ; initializari
mov si,0 ; index adresare in X
mov [bp+s1],ax ; variabile locale
mov [bp+k1],ax
mov [bp+s2],ax
mov [bp+k2],ax
51
end st1
; -----------------------------------------
Se scrie programul principal, care transmite în AX valoarea lui N, iar procedura Fact va returna în
AX rezultatul N!.
S-a făcut o exemplificare grafică a algoritmului pentru N=5.
La intrarea în procedură vom găsi în stivă adresa de revenire notată C2.
In procedură se decrementează AX şi se cheamă recursiv procedura Fact.
La fiecare Call de procedură se pune în stivă adresa de revenire C3.
Când AX=1 se sare la eticheta C1 unde se initializează AX=1!=1 şi BX=I=1.
Prin RET se revine la adresa din vârful stivei C3 unde se face BX=I+1=2 şi se calculează 2!.
Prin RET se revine la C3 unde se calculează BX=I+1=3 şi AX=I*2!=3!
Prin RET se revine la C3 unde se calculează BX=I+1=4 şi AX=I*3!=4!
Prin RET se revine la C3 unde se calculează BX=I+1=5 şi AX=I*4!=5!
Prin următorul RET se revine la C2 în programul principal şi AX=5!
; ----------------------------------------------------
; Program recursiv pentru calcul factorial
; Intrare AX=N Iesire AX=N!
;-----------------------------------------------------
Pfact Segment 'code'
assume cs:pfact,ds:sdate,ss:stiva
st1: mov ax,sdate ; initializare registre segment
mov ds,ax
mov ax,stiva
mov ss,ax
52
mov sp,offset top ; initializare stiva
mov ax,n ; AX=N pregatire apel subprogram
call Fact ; chemare subprogram recursiv N!
end st1
Dacă se transmite prin stivă şi valoarea lui N la fiecare apel recursiv, atunci procedura PFACT se
modifică, fără a modifica programul principal.
In acest caz evoluţia stivei este cea din figura următoare. Este o succesiune de adrese de revenire şi de valori
ale lui N la chemarea procedurii.
N Stiva AX
1 1!=1
C3
2 2 2!=2*1!
C3
3 3 3!=3*2!
53
C3
4 4 4!=4*3!
C3
5 N=5 5!=5*5!
SP Adresa C2
FACT PROC
CMP AX,1
JZ GATA ; N=1 si 1!=1
PUSH AX
DEC AX ; N=N-1
CALL FACT ; apel recursive
C3: POP BX ;N=N+1
IMUL BX ;N! = N*(N-1) !
GATA : RET
FACT ENDP
Se observă că deşi există un singur RET efectul lui este diferit, fiindcă el face un salt la o adresă din
vârful stivei, care depinde de structura stivei.
54
In figura următoare se prezintă schematic modul de structurare a datelor la un program reentrant.
CS Program reentrant
------------
------------ cod pur
------------
DS DS
Zona date user1 Zona date user2 Zona date user3
N -------- -------
S -------- -------
X------- -------- -------
--------- -------- ------
Stare registre
Structură Zonă
0 Număr linii introduse
2 Index prima linie liberă în zona
4 Linie 1
44 Linie 2
84 Linie 3
--------
Deoarece folosim pentru simulare consola unui singur calculator vom stabili structura liniei de text care va
conţine:
NA – Număr de caractere aşteptate
NR – Număr de caractere recepţionate
NRT – Numar terminal 0,1,2 (număr user)
CDA – Comanda introdusă care poate fi A – afişare text introdus
Text – linie text de maxim 40 carctere I – introducere linie de text
S – Stop oprire lucru pentru utilizatorul curent
Structură liniei de la consolă
BUF NA NR NRT CMD Linie text (max 40 caractere)
55
Comanda (A-afişare,I-introducere,S- stop)
Număr terminal (nr user)
Număr caractere recepţionate
Număr caractere aşteptate
Deoarece liniile introduse sunt de lungime variabilă, trebuie păstrată lungimea lor în zona de lucru.
Pentru afişarea acestor linii s-a utilizat o macroinstrucţiune de afişare AFIS, care pune după ultimul caracter
din fiecare linie semnul $, pentru ca restul de caractere până la 40 să nu se afişeze.
Pentru a putea calcula adresa fiecărei zone, care se va încărca în registru BX, s-a generat o tabelă de
adrese zone TZ. De aici adresa zonei se ia indexat cu numărul terminalului.
; ----------------------------------------------------------------------
; REENTR * Program reentrant de introducere si afisare texte (Lab8)
; -----------------------------------------------------------------
; structura buf NA - nr caractere asteptate
; buf+1 NR - nr caractere receptionate
; buf+2 TR - nr terminal
; buf+3 c-da A-afisare, I-introducere, S-stop
; buf+4 linie text, lung=40 caractere
.286
stiva SEGMENT stack ; segment stiva
dw 100
top equ $ ; virful stivei
stiva ENDS
56
Sd1 ENDS
; Segment de code
prr SEGMENT 'code'
assume cs:prr,ds:sd1,es:sd1,ss:stiva
; afisare text cu lung pe octet 1 si urmat de CR,LF
afis MACRO buf1
pusha
mov ah,0
mov al,buf1 ;lungime
mov si,ax
mov word ptr buf1[si+1],0a0dh ;CR si LF
mov buf1[si+3],'$'
mov dx,offset buf1+1 ;inceput text
mov ah,9 ;afisare
int 21h
popa
ENDM
;
st1 label far
mov ax,sd1
mov ds,ax
mov es,ax
mov ax,stiva
mov ss,ax
mov sp,offset top
c1: mov ah,9
mov dx,offset mes ;afisare mesaj
int 21h
mov dx,offset buf;asteptare mesaj
mov ah,10
int 21h
cmp buf+3,'s' ;terminat
jnz c2
mov ah,4ch ; sfarsit program
57
int 21h
c2: mov ch,0
mov cl,buf+1 ;nr caractere receptionate
inc cx ;se memoreaza si lungimea
mov bh,0
mov bl,buf+2 ;nr terminal
and bl,0fh
shl bx,2 ;NT*4
lds ax,tz[bx] ;adresa zona
mov bx,ax
cmp buf+3,'i' ;introducere
jnz c3
; Introducere rind text
mov di,bx ;inceput zona
add di,[bx+index] ;adresa rind liber
mov si,offset buf+1 ; adresa rind in bufer cu lung
rep movsb ;transfer rind in zona
inc [bx+n] ;nr inregistrari in zona
add [bx+index],40 ;index rind curent in zona
jmp c1
c3: cmp buf+3,'a' ; afisare text zona selectata
jnz c1
; Afisare text introdus
mov dx,[bx+n] ;nr linii text
mov si,bx ; SI=adresa zona
add si,4 ;prima linie
c4: mov cx,40 ;lungime
mov di,offset buf+1 ; adresa rind curent
rep movsb ; mutare rind in bufer
afis buf+1 ;afisare sir cu lung pe octet 1
dec dx ;contor linii
jnz c4 ;afisare rind urmator
jmp c1 ;dialog - Terminare prin S la dialog
prr ENDS
END ST1
7. MACROINSTRUCTIUNI
7.1. Funcţii DOS de intrare/ieşire
58
Funcţiile DOS sunt un caz particular de subprograme existente în sistemul de operare DOS, care
se apelează prin întreruperi. Apelul funcţiilor DOS este independent de Versiunea sistemului de operare.
Transmiterea parametrilor se face prin registre sau prin zonă de memorie.
Oricare comandă DOS are o funcţie corespondentă care poate fi apelată din programe scrise în limbaj de
asamblare. Se pot construi aplicaţii care utilizează comenzile DOS în programe. Din această categorie face
parte şi Norton Commander, sau Windows Commander.
Apelarea unei funcţii DOS de intrarea ieşire se face printr-o secvenţă de forma:
Intreruperea 21H serveşte la apelarea a zeci de funcţii indicate prin codul funcţiei ce se încarcă în
registrul AH. Fiecare funcţie necesită un număr de parametrii care se încarcă în registre.
Oprire program cu revenire în DOS se realizează cu funcţia care are codul 4CH
MOV AH,4CH ; cod funcţie revenire în DOS
INT 21H
03H Citire în AL un caracter de la intrarea AUX, care este în mod normal portul de
comunicaţii seriale COM1 (2400 bauds, fără paritate ,1bit de Stop, 8 biţi de date).
06H Intrare ieşire directă fără ecou serveşte la transmiterea caracterelor funcţionale(CTRL+)
Dacă DL=FFH aşteaptă un caracter în AL de la tastatură
Z=1 dacă nu s-a tastat caracter şi se aşteaptă
Z=0 dacă s-a apăsat o tastă caracterul se găseşte în AL
AL=0 indică recepţia unui caracter funcţional a cărui cod se citeşte prin următoarea c-dă
Dacă DL#FFH se afişează caracterul din DL
DX
NA NR Text
59
NA - număr de caractere maxim aşteptate (dacă se introduc mai multe de NA-1 se ignoră)
NR - număr de caractere recepţionate până la ENTER
2CH Obţinere ora curentă CH - ora (0..23), CL – minutul, DH secunda, DL – Sutime secundă
60
61
7.3. Definire macroinstrucţiuni
Definirea unei macroinstrucţiuni se face ca pentru un subprogram din limbajele de programare de nivel
înalt specificând:
numele macroinstrucţiunii prin eticheta directivei MACRO
lista de parametrii formali utilizaţi
secvenţă de instrucţiuni care definesc algoritmul pe baza parametrilor formali, ai variabilelor şi
constantelor din program
sfârşitul unei macroinstrucţiuni se specifică prin directiva ENDM
etichetele din secvenţa de instrucţiuni cu directiva LOCAL
Exemplul 1. Afişare şir de caractere prin apel funcţie DOS definită ca macroinstrucţiune.
AFIS MACRO mesaj ; definire macroinstrucţiune AFIS
MOV DX,offset mesaj ; adresă text de afişat terminat cu ’$’
MOV AH,9 ; cod funcţie DOS
INT 21H ; apel funcţia de afişare
ENDM ; sfârşit secvenţa de definiţie
62
Exemplul 2. Medie aritmetică a două numere definită ca macroinstrucţiune:
MED MACRO X,Y,Z ; definire medie Z= (X+Y)/2
MOV AX,X
ADD AX ,Y ; AX=X+Y
SHR AX,1 ;AX=(X+Y)/2
MOV Z,AX ; Z=AX memorare rezultat
ENDM
Media C între două numere A şi B se va calcula prin:
MED A,B,C
Pentru conversia unui număr Xzec din zecimal în binar la adresa X se va scrie:
C_ZB Xzec,5,X ; este similară unei instrucţiuni cablate
Macroinstrucţiunile se folosesc pentru algoritmi care se realizează prin secvenţe scurte de câteva
instrucţiuni. La fiecare utilizare se generează secvenţa de program din definirea MACRO. Nu se vor defini
macroinstrucţiuni pentru algoritmi care se realizează cu un număr mai mare de instrucţiuni (conversii,
înmulţire de matrici, etc.).
Pentru cazul unei aplicaţii cu algoritmi mai complecşi se va folosi programarea modulară:
Se vor analiza funcţiile ce trebuie realizate, pentru care se vor definii proceduri.
63
Se va defini fiecare procedură pentru a specifica algoritmul folosit şi se vor stabili convenţiile de
transmitere a parametrilor spre procedură.
Se va defini o macroinstrucţiune pentru fiecare procedură, care va defini secvenţa ce pregăteşte
parametrii, apelează procedura şi memorează rezultatele.
Se va scrie un program principal care va utiliza macroinstrucţiuni pentru a realiza funcţiile dorite.
Apelul subprogramelor devine transparent la acest nivel şi programarea se simplifică
Exemplul 4. Program complex care utilizează proceduri şi macroinstrucţiuni care pregătesc parametrii
pentru apelul procedurilor. In cadrul programului se realizează funcţiile:
Se citesc 10 numere zecimale de la tastatură de 1...5 cifre ( numărul de cifre în octet buf+1)
Se converteşte în binar pe 2 octeţi fiecare număr citit şi se memorează într-un tabel
La conversia zecimal binară se verifică fiecare caracter introdus dacă este cifră( 0...9)
Se afişează tabelul nesortat
Se sortează tabelul în ordine crescătoare
Se afişează tabelul sortat convertind în zecimal fiecare număr binar în buffer
64
; Program care utilizeaza macroinstructii pentru chemare subprograme
; - Citire un sir de numere ; Conversie zecimal binar ; Memorare in tabel
; - Sortare tabel ; Conversie binar zecimala ; Afisare elemente tabel sortat
; ------------------------------------------------------------------------------------
dosseg
.model small
.data
buf db 7,8 dup(?) ; buffer primire 7 cifre
table dw 10 dup(?) ; tabel numere binare receptionate
mes db 'Introduceti 10 nr. intregi cite unul pe linie',13,10,'$'
smsg db 'Nr. sortate sunt:',13,10,'$'
bufs db 10 dup (20h),13,10,'$'
inval db 'Nr. invalid',13,10,'$' ; mesaj pentru numar invalid (litera semn,)
zece dw 10 ; constanta 10 pentru conversiiBinar zecimale
cr db 13,10,'$ ; cr si lf
.stack 256 ; segment stiva
.code ; segment de cod program
PRINT MACRO msg ; afisare mesaj terminat cu $
mov dx,offset msg
mov ah,09h
int 21h
endm
GET MACRO buff ; citire sir
mov dx,offset buff ; adr. buf. receptie
mov ah,10
int 21h
print cr ; rind nou
endm
PUTC MACRO ; afisare caracter din DL
push ax
mov ah,2
int 21h
pop ax
endm
CONVBIN MACRO buff ; conversie zecimal binara sir
mov si,offset buff
inc si
mov cl,[si] ; contor nr. cifre
inc si ; prima cifra
xor ch,ch
call dectobin ; chemare subprogram
endm
SORT MACRO tab,cnt ; sortare tabel de n elem
mov si,offset tab ; adresa tabel intregi
mov cx,cnt ; nr elemente tabel
call selsort ; subpr. sortare tabel
endm
SCRIE MACRO tab,cnt ; afisare tabel n elemente intregi
Local s1
mov cx,cnt ; nr. elemente
65
mov di,0 ; index in tabel
s1: mov ax,tab[di] ; T(I)=>AX
mov bx,offset bufs ; adresa bufer conversie
mov si,7
call cbz ; subpr. conv. bin-zec si afisare
add di,2
loop s1
endm
; include bindec.inc ; se pot copia subprogramele de conversie bin-zec si zec-bin
;------------------------------
CBZ PROC near
; Afiseaza un numar binar din ax dupa ce il
; converteste in zecimal cu + sau - in fata
;------------------------------
or ax,ax ; pozitionare indicatori
jns pos ; numar pozitiv
neg ax ; val absoluta
mov dl,'-'
putc ; afisare un caracter din dl
pos: call printr ; procedura recursiva conv bin-zec
print cr ; rind nou
ret
CBZ ENDP
; ---------------------------
PRINTR PROC near
; In AX nr pozitiv binar, resturile MOD 10
; afisate in ordinea inversa obtinerii
cwd ; pregatire impartire DX=0
idiv zece ; N/10 restul in dx, citul in AX
or ax,ax ; cit=0 ?
jz gata1 ; da
push dx ; memorare rest
call printr ; apel recursiv
pop dx ; reface restul
gata1: or dl,30h ; cifra ASCII
PUTC ; afisare cifra din dl
ret
PRINTR ENDP
; ---------------------------
SELSORT PROC near
; Procedura sortare tabel elemente binare
; SI - adresa primul element; CX - nr. de elemente
; ----------------------------
mov bx,si
c1: dec cx
jz gata
push cx
mov si,0
mov dh,0
c2: mov ax,[bx+si]
66
cmp ax,[bx+si+2]
jl c3
xchg ax,[bx+si+2]
mov [bx+si],ax
inc dh
c3: add si,2
loop c2
or dh,dh
pop cx
jz gata
jmp c1
gata: ret
SELSORT ENDP
;--------------------------------------
SELS PROC near ; Subprogram sortare prin selectie
; SI - adresa primul element ; CX - nr elemente
; -------------------------------------
cld ; directie stg-dr
dec cx
nextp: push cx ; n-1 cicuri
lodsw ; primul element [SI]
mov di,si ; cautare in sir nesortat
nexte: scasw; ; compara ax cu[DI]
jle ismin ; ax<=[DI]
xchg ax,[DI-2] ; noul minim
ismin: loop nexte
mov [si-2],ax ; memorare minim
pop cx
loop nextp ; cauta urmatorul minim
ret
SELS ENDP
;--------------------------------------
DECTOBIN PROC near
; Procedura conversie zec-binara cu semn
; SI - adresa prima cifra
; CX - numar cifre
dec cx ; ciclu semn
cld ; df=0
lodsb ; primul caracter
cmp al,'-' ; semn minus
stc ; cf=1
jz minus
cmp al,'+' ; semn plus
jz plus
inc cx ; fara semn, corectie contoare
dec si
plus: clc ; cf=0
minus: pushf ; salvare indicatori
xor bh,bh
xor ax,ax ; N=0
67
cwd
next: mov bl,[si] ; o cifra zecimala
cmp bl,'0' ; verificare numeric
jl nodigit ;err.
cmp bl,'9'
jg nodigit ;nu-i cifra
sub bl,30h
mul zece ; N=N*10
add ax,bx ; N=N*10+cifra
inc si
loop next ; urmatoarea cifra
popf ; reface indicatori
jnc pozitiv
neg ax ; numar negativ
clc
pozitiv: ret
nodigit: print inval ; mesaj numar invalid
popf
xor ax,ax
stc ; setare CF=1 nr.invalid
ret
dectobin endp
; -------------------------------------
; Program principal
; -------------------------------------
pp: mov ax,@data ;initializare reg segment
mov ds,ax
mov es,ax
print mes ; mesaj dialog
mov cx,10 ; numere de introdus
mov di,0 ; prima pozitie in tabel
cit label near
push cx
push di
get buf ; asteapta un numar
convbin buf ; AX nr. binar rezultat
pop di
pop cx
jc cont ;daca c=1 atunci nr citit este invalid
mov table[di],ax ; memorare numar binar in tabel
inc di
inc di
cont: adc cx,0 ; neglijare numar eronat
loop cit
scrie table,10 ; afis. tabel nesortat
sort table,10 ; sortare tabel
scrie table,10 ; afisare tabel sortat
mov ah,4ch ; stop
int 21h
end pp
68
8. UTILIZAREA FISIERELOR PE DISC
In memoria centrală se poate memora un volum redus de date care pot fi adresate într-un timp
foarte scurt de ordinul 10nsec. Aceste date nu sunt persistente ele fiind pierdute la deconectarea
calculatorului.
Pe hard/floppy disc se memorează persistent ca fişiere volumele mari de informaţii şi programele,
care pot fi ulterior regăsite şi citite în memoria centrală pentru prelucrare. Informaţiile pe disc se pot
memora numai ca fişiere pentru care se asigură gestiunea spaţiului de memorare şi securitatea accesului
prin utilizarea funcţiilor DOS. Timpul de acces la informaţiile de pe disc de cca 10msec este de 1 milion de
ori mai mare decât la RAM.
Din acest motiv nu se recomandă utilizarea directă a informaţiilor din fişierele disc ci se citesc
blocuri întregi de informaţie în RAM unde se va face prelucrarea.
Floppy discul de 3 ½ inch are ambele fete active şi câte un cap de citire pentru fiecare faţă rezultând
o capacitatea de 1.44Mocteţi.
2 feţe x 80 piste x 18 sectoare/pistă x 512 octeţi/sector = 1.44Mo
Sectoarele sunt subdivizini ale pistei pentru a putea adresa mai fin informaţia. Uzual se folosesc sectoare de
512 octeţi atât pentru floppy cât şi pentru hard discuri. Sectoarele sunt separate de spaţii goale ’gap’
corespunzător a cca 10-12 octeţi.
Pista 0
Hard discul este format dintr-un pachet de 2-5 discuri de 3½ inch, ce au ambele feţe active şi au un
sistem de capete magnetice de citire mobile, câte unul pentru fiecare faţă activă. Scrierea se face serial prin
dipoli magnetici pe cercuri concentrice numite piste. Un disc are funcţie de capacitate peste 10.000 de piste.
O pistă este împarţită în sectoare, a căror număr diferă de densitatea permisă de tehnologie. Pistele de pe
aceeaşi verticală formează un cilindru. Poziţionarea blocului capetelor de citire pe un cilindru este realizată
automat de electronica de pe disc şi de interfaţa cu discul. Pentru a minimiza mişcările mecanice,
69
parcurgerea şi numerotarea pistelor se face pe cilindrii de sus în jos. La un moment dat este selectat un
singur cap de citire, deci o singură pistă de pe cilindru. Cilindrii se numerotează de la exterior spre interior.
Selectarea unui sector de pe pistă se face dinamic prin numărul său plasat ca informaţie de control la
începutul sectorului. Discul se învârte continuu cu viteză constantă de 2400, 3600, 5200 sau 7200rot/minut.
La turaţii mai mari debitul instantaneu de octeţi transferaţi este mai mare ( de 3 ori mai mare la 7200rot faţă
de 2400).
Structura unui sector este:
Prezentăm ca exemplu un hard disc de 40Mo care mai respectă structura fizică:
5 feţe active pe 3 discuri fizice în pachet (5 capete de citire)
976 cilindri =82.960 sectoare x 512 octeţi =40Mo
1cilindru = 5 piste x 17 sectoare/pistă = 85sectoare x 512octeţi =42.5Ko
1 pistă =17sectoare x 512octeţi = 8.5Ko
DiamondMax Plus 9 PATA MAXTOR Ultra DMA133 7200 RPM:
MODEL CYL HDS :SECT MaxCil Max LBA GB Capacity
“L” in model denotes ATA/133 2 MB Transfer, “P” - 8 MB Buffer PATA = Parallel ATA MAXTOR.com
NOTE: NEVER enter more than 16,383 cylinders in the system BIOS. This may potentially cause data loss.
Adresa sectorului se ia la discurile actuale global fiindcă numărul de biţi alocaţi iniţial pentru cilindru
este insuficient şi nu se mai poate respecta structura. Apare în acest caz o structură logică de adresare (LBA)
care pentru discurile Maxtor de 80GB (LBA=160 milioane de sectoare) avem CIL=16.000, HEAD=16 şi
SECT=63, în timp ce numărul real de cilindrii este de 160.000. Se foloseşte aceeaşi tehnologie, dar
capacitatea diferă funcţie de densitatea radiară (nr. cilindri ) şi numărul de discuri în pachet.
Logic un disc este văzut în program ca o memorie cu N sectoare de 512 octeţi, 160.000.000 pentru un
disc de 80MB.
70
Sectorul de boot conţine programul de preîncărcare în RAM a nucleului DOS format din fişierele
sistem IO.SYS şi MSDOS.SYS
File Alocation Table (FAT) conţine tabela de alocare discului
Root directory conţine directorul rădăcină pentru 128 fişiere disc (4K)
Zona fişiere împărţite în clustere. Unele fişiere pot fi director.
Cluster-ul este unitatea de alocare pe disc şi poate fi de 1-64 sectoare (0.5-32K). Numărul total de
clustere este limitat la 64.000 de capacitatea de adresare a tabelei de alocare FAT, care conţine intrări pe 16
biţi. La floppy disc alocarea se face la nivel de sector (cluster=512oct), iar la discurile mari pentru
cluster=32K capacitatea de adresare este de 2GB. Aceasta a dus la mărirea adresei de cluster din FAT la 32
biţi, care permite 2 miliarde de clustere. In ultimii 15 ani s-au trecut 10 bariere de capacitate, care au impus
modificarea nucleului BIOS (Basic Input/Output System).
Tabela de alocare a discului (FAT) conţine o intrare pentru fiecare cluster de forma:
FAT
Nr.clust Ch
Intrarea de director a unui fişier conţine adresa primei intrări în FAT, care specifică adresa primului
cluster alocat şi următoare intrare (Ch) din FAT pentru fişier. La crearea unui fişier i se alocă un cluster şi
când acesta este plin i se alocă următorul.
Pentru discul curent se ţine în memorie în 2 exemplare tabela de alocare FAT.
Fiecare fişier are un atribut care indică modul de acces:
Atribut
00 A D V S H R A-archive, D-subdirector, V-etichetă volum, S-sistem,
H-hide, R-Read-only
Spaţiul pentru un fişier este discontinuu pe disc, fiind format din clustere plasate în diferite zone
ale discului, unde s-a găsit un cluster liber. La ştergerea unui fişier clusterele alocate se eliberează pentru a fi
realocate. Pentru programator un fişier este un spaţiu continuu, care se adresează relativ la începutul
fişierului.
Sistemul de operare DOS asigură gestiunea şi securitatea informaţiilor pe disc ca fişiere (inclusiv
sistem). Pentru crearea, ştergerea, scrierea, citirea şi actualizarea fişierelor există funcţii DOS care se
apelează din program prin INT 21H. Parametrii necesari se transmit prin registre sau printr-o zonă de
71
memorie pentru dialog ataşată fişierului numită FCB (File Control Bloc). Există 2 modalităţi de exploatare
a fişierelor, care au concepte diferite şi funcţii specifice, dar aceeaşi organizare fizică:
Utilizare FCB pentru comunicare cu sistemul şi se citesc/scriu înregistrări de lungime dată.
Adresarea se face la nivel de înregistrare.
Utilizare indicator logic (handle), care face referire la un FCB din sistem şi permite adresarea
fişierului la nivel de octet relativ la începutul fişierului.
Exploatarea cu FCB presupune declararea unui FCB pentru fiecare fişier utilizat.
Structura FCB cuprinde pe 36 octeţi informaţii furnizate de program şi informaţii returnate de sistem după
executarea unei operaţii (funcţii):
DS:DX
0 1 9 12 14 16 20 22 24 32 33
Cod Nume Ext Nr.bloc Lung Lung Data Timp rez Nr.inreg Nr. inreg.
disc fişier inreg fişier in bloc acc direct
FCB SRUC
Drive db 0 ; cod disc utilizat
Fnume db 8 dup (20h) ; nume fişier
Fext db 3 dup (20h) ; extensie nume
Lrec dw 80 ; lungime înregistrare
Lfis dd 0 ; lungime fisier
Fdate dw 0 ; data de creare
Ftime dw 0 ; ora de creare
Frez db 8 dup(0) ; rezervat
Fnrc db 0 ; număr articol curent în bloc
Frand dd 0 ; numar inregistrare in acces direct (random)
FCB ENDS
Orice citire de informaţie de pe disc în acces direct necesită o poziţionare pe disc pentru că FAT
este păstrată în memorie. Când se specifică adresa unui sector ce trebuie citit din fişier (relativ la începutul
fişierului), din FAT se stabileşte rapid numărul clusterului care îl conţine şi rezultă numărul sectorului fizic
în care se găseşte.
Inaintea apelării unei funcţii DOS se va încărca în DS:DX adresa FCB fişier utilizat.
După executarea unei funcţii DOS A=00 indică operaţie reuşită.
72
14H - Citeşte secvenţial o înregistrare din fişierul indicat în FCB, de lungime precizată în octet 14 din
FCB. Adresa bufer este zona curentă DTA (Disc Transfer Area). Octetul 32 din FCB (nr.înreg.în
bloc) se pune iniţial pe zero şi ulterior se
incrementează automat după fiecare citire. Se trece automat de la un bloc la altul.
15H - Scrie secvenţial o înregistrare din DTA în fişier de lungime dată de FCB+14 . Extinderea
fişierului se face automat dacă un cluster s-a umplut.
16H - Deschidere fişier nou cu numele dat în FCB. Scrie o intrare în directorul curent.
Dacă nu există spaţiu AL=0FFH.
17H - Redenumeşte fişier din FCB cu numele din octeţii FCB +17H
19H - Obţine cod disc curent în AL
1AH - Stabileşte adresa DTA (Disc Transfer Area) zonă tampon curentă dată în DX.
La iniţializare sistem adresa DTA=80H.
21H - Citire în acces direct de pe fişier, de pe sectorul dat în FCB+33.
22H - Scriere în acces direct din DTA cu specificare adresă sector disc în FCB+33.
Scrierea pe ultimul sector din fişier se face pentru rezervare spaţiu.
Pentru a simplifica scrierea programului se vor folosi macroinstrucţiuni pentru apelul funcţiilor
DOS.
Scrieţi un fişier cu un editor de texte (NotePad, F4 din Windows Commander) şi citiţi-l cu un
program, care foloseşte macroinstrucţiunilele definite.
Modificaţi conţinutul textului din fişier şi afişaţi-l cu un editor.
Modificaţi lungimea înregistrărilor FCB+14 şi afişaţi fişierul
; *********************************************
; Utilizare fisiere prin fcb DS:DX contine adresa FCB
; Citire text tastatura
; Scrire text pe fisier
; Citire de pe fisier si afisare
; Se utilizeaza macro definiti si control erori
; **********************************************
dosseg
.model small
.stack 100
.data
b1 db 10,13,10,13 ; CR si LF
buf db 20,80 dup(20h),10,13,'$' ; Buffer I/O
FIS db 0,'fisier txt',0,0,0,20 ; FCB fisier
db 26 dup (?)
er db ' Operatie eronata',10,13,'$'
start db ' Dialog:',10,13,'$'
LFCR db 10,13,'$'
.stack 256
.code
73
or al,al ; test eroare
jz gata ; operatie corecta
mov ah,coder
mov er,ah
afis er ; cod eroare pt fiecare macro
gata label near
endm
; Program principal
pp: mov ax,@data ;
mov ds,ax
mov es,ax
; afis buf
open fis ; deschidere fişier existent
mov fis+14,30 ;lungime inregistrare RCS
; create fis ; se crează la prima rulare
mov fis+32,0 ;nr inreg.=0
mov cx,5 ;contor nr inregistrari
75
9. EXPLOATAREA FIŞIERELOR CU INDICATOR LOGIC (HANDLE)
Alocarea fişierelor pe disc este discontinuă pe clustere a căror adresă se află din tabela de alocare a
discului (FAT). Programatorul vede fişierul ca fiind continuu, iar adresa unei informaţii se dă relativ la
începutul fişierului. Există un singur mod de organizare a fişierelor pe disc, cel prezentat la începutul
capitolului şi două moduri de exploatare:
Exploatarea fişierelor cu utilizare FCB a fost prima modalitate existentă în DOS şi realizează
citirea/scrierea din fişier la nivel de înregistrare, specificând lungimea înregistrării şi numărul
înregistrării transferate.
Exploatarea fişierelor cu indicator logic permite adresarea informaţiei la nivel de octet faţă de
începutul fişierului, specificând lungimea transferată în octeţi. Metoda a apărut în DOS V3, când
prin apariţia hard-disc-ului pe PC XT (10MB), sau introdus subdirectoare şi trebuia specificat
numele fişierului şi calea. In FCB se putea specifica numai numele fişierului.
In DOS V3 s-a adăugat un nou set de funcţii pentru exploatarea informaţiilor din fişiere schimbând şi
principiile de lucru. La iniţializarea sistemului se alocă un număr de peste 100 de FCB-uri gestionate de
sistem. Aceasta este limita numărului de fişiere care vor putea fi deschise simultan în aplicaţii. Numele
fişierului inclusiv calea se dă într-un text ASCII de lungime variabilă terminat cu 00H definit sub forma:
Fis1 DB ’C:\Prog\Laborator\PLA\Fisier1.txt’,0
La deschiderea fişierului se încarcă în DS:DX adresa textului care dă numele fişierului. Se caută
fişierul în directorul specificat şi i se alocă un FCB sistem al cărui handler (pointer) se returnează în
registrul AX şi se va încarcă în BX înaintea apelării altor funcţii care se referă la acel fişier. După
executarea oricărei funcţii CF=0 dacă operaţia a reuşit şi CF=1 dacă a apărut o eroare.
Dacă se utilizează exploatarea cu indicator logic atunci trebuie specificată adresa primului octet
citit/scris din fişier şi lungimea în octeţi a informaţiei transferate. Adresa octetului curent referit din fişier se
ţine în pointerul de citire/scriere (din FCB-ul alocat), care se modifică cu funcţia de poziţionare (41H). La
deschiderea fişierului adresa curentă este 0 şi se referă la începutul fişierului.
Fisier.txt
Adr.in fisier
(Pointer cit/scr)
76
Memorie
DS:DX
3CH Creare fişier (Create) Creează în directorul specificat o etichetă de fişier nouă.
AH=3CH codul funcţiei de creare fişier nou
DS:DX =adresă şir ASCII cu numele fişierului urmat de 00H
CX conţine atributul fişierului
00 – fişier normal
01 – fişier read/only (protejat la scriere)
02 – fişier ascuns
04 – fişier sistem
Ieşire dacă CF=0 atunci AX conţine indicatorul logic (handle) atribuit fişierului
CF=1 operaţie eronată şi AX conţine codul erorii
(3 nu s-a găsit calea, 4 prea multe fişiere deschise, 5 acces interzis)
3DH Deschidere fişier existent (Open) se poate deschide orice fişier inclusiv cele ascunse.
Intrare AH=3DH codul funcţiei DOS
AL conţine codul de acces
(0 citire permisă,1 scriere permisă, 2 scriere citire, primii biţi acces partajat)
DS:DX =adresă şir ASCII cu numele fişierului urmat de 00H
Ieşire AX conţine indicatorul logic (handle) sau cod de eroare (CF=1)
3EH Inchidere fişier Inchide fişierul al cărui indicator logic s-a dat în BX
AH=3EH cod funcţie DOS închidere fişier
BX =indicatorul logic al fişierului
3FH Citire dintr-un fişier (Read) indicat prin BX care conţine indicatorul alocat (handle), într-o zonă de
memorie dată prin DS:DX de la adresa de fişier indicată de pointer-ul de citire/scriere şi lungime în număr
de octeţi dată în CX.
Intrare AH = 3FH cod funcţie DOS de citire din fişier
BX = indicator logic fişier referit (handle)
DS:DX =adresă zonă de memorie (buffer)
CX =număr de octeţi transferaţi (lungime)
Ieşire AX =număr de octeţi citiţi dacă CF=0 (AX=0 este EOF sfârşit de fişier).
Incrementare automată pointer citire/scriere cu lungimea citită.
40H Scriere într-un fişier (Write) indicat prin BX, care conţine indicatorul alocat (handle), dintr-o zonă de
memorie dată prin DS:DX, la adresa de fişier indicată de pointer-ul de citire/scriere şi lungime în număr de
77
octeţi dată în CX. Pointerul de scriere/citire se incrementează automat cu lungimea transferată după
operaţie.
Intrare AH = 3FH cod funcţie DOS de scriere în fişier
BX = indicator logic fişier referit (handle)
DS:DX =adresă zonă de memorie (buffer)
CX =număr de octeţi transferaţi (lungime)
Ieşire dacă CF=0 operaţie reuşită
41H Ştergerea unui fişier a cărui nume se dă ca text ASCII în DS:DX (inclusiv calea). Dacă se omite
discul sau calea se ia din directorul curent.
AH=41H cod funcţie DOS ştergere fişier
BX=indicator logic fişier referit (handle)
42H Poziţionare pointer citire/scriere (LSEEK) pentru fişierul asociat indicatorului logic (handle) dat în
BX şi păstrat în FCB-ul alocat de sistem, precizând referinţa (adresa curentă, începutul sau sfârşitul
fişierului). După fiecare transfer pointerul de citire/scriere se actualizează cu lungimea transferată.
AH=42H cod funcţie poziţionare pe fişier
AL codul metodei de poziţionare
0 – faţă de începutul fişierului
1 – faţă de poziţia curentă
2 – faţă de sfârşitul fişierului
BX = indicatorul logic al fişierului referit (handle)
CX:DX =adresa relativă în fişier în octeţi a informaţiei ce se transferă
43H Citire/Setare atribute fişier permite schimbarea atributelor fişierului setate la creare sau pe parcurs.
AH=43H funcţie DOS setare atribute fişier
AL = cod subfuncţie (0 – citire atribute, 1 – setare atribute)
DS:DX = adresă nume fişier ca text ASCII
CX valoare atribute citite sau de setat
(0 – normal, 1 –read/only,2 – ascuns, 4 sistem, 20H arhiva).
Prezentăm mai jos un exemplu de scriere şi citire rânduri de text într-un fişier exploatat cu indicator
logic. Se observă modul de definire a numelui fişierului.
La început se definesc macroinstrucţiunile utilizate la apelarea funcţiilor DOS, care pot fi plasate
într-un fişier program separat pentru a putea fi utilizate şi din alte programe. Prin directiva INCLUDE
fişierul de macroinstrucţiuni se copiază în secţiunea .CODE din program.
Se vor concepe alte programe care să utilizeze macroinstrucţiunile definite.
78
mov ah,0Ah ; functie dos citire sir
int 21h
xor bh,bh ; in BX lungime sir receptionat
mov bl,sir1+1
mov sir1[bx+3],10 ; cod LF (linie noua) la sfirsit
mov sir1[bx+4],'$' ; indicator sfirsit sir
mov dl,10 ; linie noua dupa receptie
mov ah,02h ; functie afisare un caracter
int 21h
endm
; INCHIDERE FISIER
;------------------------------------------
cl_fis macro handle1 ; adresa indicator logic
local cont
clc
mov ah,3eh ; functie inchidere fisier
mov bx,handle1 ; incarcare indicator logic
int 21h
jnc cont ; CF = 0 operatie corecta
tip_err al ; CF = 1 afisare eroare din AL
cont label near
endm
; PROGRAM PRINCIPAL
;=========================
dosseg
.model small
.stack 256
.data
nume_fis db 'C:\Stud\Pla\fis.txt',0 ; numele fisierului
handle dw 0 ; indicator logic fisier
buf db 50,0,50 dup (?) ; zona tampon pentru dialog
mes db 'Introduceti 10 siruri de caractere:',13,10,'$'
mes1 db 13,10,'Continutul fisierului:',13,10,'$'
err db 13,10,'Eroare scr/cit fisier nr: $'
.code
includedisclogi.inc ; definiri macro lucru cu fisiere
;======================================================
;program de exploatare fiserere disc cu indicator logic
;======================================================
;fisierul cu numele fis.txt se va crea vid din Norton Commander
; sau se va introduce macro de creare fisier vid(ah=3ch)
;indicatorul sfarsit de fisier(eof) este dat de ax=0
; normal dupa citire ax indica numarul de octeti cititi
;inainte de executie operatie i/e:
; bx=handle fisierului ds:dx=adresa buffer
; cx=lungime de transferat
dosseg
.model small
.stack 256
.data
nume_fis db 'fis.txt',0 ;numele fisierului
buf db 50,0,50 dup(?) ;zona dialog
mes db 'introduceti 10 siruri de caractere:',13,10,'$'
mes1 db 13,10,'continutul fisierului:',13,10,'$'
err db 13,10,'eroare scriere/citire fisier nr:$'
handle dw 0 ;indicator logic fisier
.code
include disclogic.inc ;definiri macro lucru cu fisiere
start:
mov ax,@data
mov ds,ax
82
pop cx
loop l2 ;ciclu citire de pe fisier
cl_fis handle ;inchidere fisier
mov ax,4c00h ;terminare program
int 21h
end start ;adresa de lansare
---------------------------------------
Fisier disclogic.inc
;===========================================
;UTILIZARE FISIERE PRIN IDENTIFICATOR LOGIC
;DEFINIRE MACROINSTRUCTIUNI FOLOSITE
;===========================================
;CITIRE SIR DE LA CONSOLA SI COMPLETARE LF SI $
;==============================================
cit_sir macro sir1
mov dx,offset sir1 ;adresa de receptie
mov ah,0ah ;functie dos citire sir
int 21h
xor bh,bh ;in bx lungime sir receptionat
mov bl,sir1+1
mov sir1[bx+3],10 ;cod lf(linie noua) la sfarsit
mov sir1[bx+4],'$' ;indicator sfarsit sir
mov dl,10 ;linie noua dupa receptie
mov ah,02h ;functie afisare un caracter
int 21h
endm
;AFISARE SIR TERMINAT CU CARACTER PE ECRAN
;==========================================
tip_sir macro sir2
mov dx,offset sir2 ;adresa sir de testat
mov ah,09h ;functie afisare sir
int 21h
endm
;AFISARE EROARE DUPA EXECUTIE MACRO
;====================================
tip_err macro nr
tip_sir err ;afisare mesaj eroare
mov dl,nr ;urmat de numar eroare
or dl,30h
mov ah,02h ;afisare un caracter
int 21h
mov dl,10 ;rand nou LF si CR
int 21h
mov dl,13
int 21h
mov ah,4ch ;terminare program
int 21h
83
endm
;DESCHIDERE FISIER EXISTENT
;============================
op_fis macro nume1,handle ;nume si adresa indicator logic
local cont ;eticheta locala in macro
clc ;anulare fanion CF
mov ah,3dh ;functie deschidere fisier
mov dx,offset nume1 ;adresa zona cu nume fisier
mov al,02h ;mod de deshidere R/W
int 21h
jnc cont ;cf=0 operatie corecta
tip_err al ;cf=1 afisare eroare din al
cont label near ;definitie eticheta locala
mov handle,ax ;salvare indicator logic din ax
endm
;INCHIDERE FISIER
;====================
cl_fis macro handlel ;adresa indicator logic
local cont
clc
mov ah,3eh ;functie inchidere fisier
mov bx,handle1 ;bx= indicator logic
int 21h
jnc cont ;CF=0 operatie corecta
tip_err al ;CF=1 afisare eroare din AL
cont label near
endm
84
;la adresa disc data de pointerul de citire/scriere
;--------------------------------------------------
scr_fis macro handle1,lung,buff
local cont
clc
mov ah,40h ;functie scriere fisier
mov dx,offset buff ;adresa zona mamorie
mov cx,lung ;nr octeti transferati
mov bx,handle1 ;BX=indicator logic fisier
int 21h
jnc cont ;CF=0 => corecta citirea
tip_err al ;afisare eroare
cont label near
endm
int 21h
jnc cont ;CF=0 => operatie reusita
tip_err al ;tiparire cod eroare
cont label near
endm
------------------------------------------------------
85
mov es, ax
cld
mov si, offset sir1
mov di, offset sir2
mov cx, sir1l ; se compara pe lungimea unui sir
mov E, '1' ; se considera ca sunt egale
repz cmpsb ; se repeta pana se intalneste o diferenta
jz egal ; daca ZF = 1 sirurile sunt egale
mov E, '0' ; nu exista egalitate
egal: nop
int 3
end st1
------------------------------------
; Procedura calcul factorial ( N! )
; intrare -
; ax - N (numarul)
; iesire -
; ax - N!
; Modifica bx !
factor1 proc far
dec ax
jz fact1
call factor1
inc bx ;N=N+1
imul bx ; N! = N * (N - 1)!
retf
fact1: mov bx,1 ;N=1
mov ax, bx ; 1! = 1
retf
factor1 endp
; varianta (necesita stiva !)
factor2 proc far
cmp ax, 1
jle fact2
push ax
dec ax
call factor2
pop bx ; N
imul bx ; N! = N * (N - 1)!
fact2: ret
factor2 endp
; macro pentru apelul procedurii recursive
; salveaza registrele folosite si pregateste parametrii pentru procedura
; returneaza valoarea calculata
; ax se modifica !
86
factor macro N, Nfact
push bx
mov ax, N
call factor1
pop bx
mov Nfact, ax
endm
------------------------------
;program de calcul exp(x)
.model small
.stack 256
.8087
.data
eps dd 0.00001
x dd 2.541
ex dd 0.
.code
start:
mov ax, @data
mov ds, ax
fld x
fld1
fld st
fld st
fld st
ciclu:
fmul st, st(4)
fdiv st, st(1)
fadd st(2),st
fincstp
fadd st, st(2)
fdecstp
fcom eps
; fstsw ax
fwait
sahf
jl gata
jmp ciclu
fld st(2)
fst ex
gata:
mov ah, 4ch
int 21h
end start
---------------------------------------
87
pr1 segment
assume cs:pr1, ds:pr1, es:pr1
l1 equ 26
l2 equ 4
sir1 db 'facultatea de calculatoare $'
sir2 db 'dexy'
mem dw 0
st1:
mov ax, pr1
mov ds, ax
mov es, ax
88
; - media elementelor pozitive
; - media elementelor negative
;
medie_s struc
vsp dw ? ; variabila locala pt. suma el. pozitive
vnp dw ? ; variabila locala pt. nr. el. pozitive
vsn dw ? ; variabila locala pt. suma el. negative
vnn dw ? ; variabila locala pt. nr. el. negative
vbp dw ? ;
vip dw ? ;
vcs dw ? ;
vne dw ? ; parametrul nr. elemente
vat dw ? ; parametrul adresa tablou
medie_s ends
m_z EQU [bp - vbp] ; constanta pentru acces la parametrii si variabile locale
medie1proc far
push bp
mov bp, sp ; setare bp
sub sp, vbp ; alocare spatiu pentru variabile locale
;
push dx ; salvare registre folosite
push cx ;
push si ;
push ax ;
89
mov ax, m_z.vsn ; ax = suma elementelor negative
cwd ; pregatire pentru impartire
idiv m_z.vnn ; calcul medie
mov m_z.vat, ax ; se suprascrie primul parametru cu media neg.
90
retf
bb1: push di
push dx
push cx
push bx ; salvarea registrelor folosite
dec cx ; se compara pe max cx-1 caractere
mov dx, cx ; salvare contor
bbl: mov si, bx ; index folosit
mov cx, dx ; restaurare contor
mov di, 0 ; (0 - sir sortat)
bbli: mov al, [si] ; bucla interna de parcurgere a sirului
cmp al, [si+1]
jle bbok ; salt daca [si] <= [si+1]
xchg al, [si+1] ; schimbarea valorilor [si] <-> [si+1]
mov [si], al ;
mov di,1 ; (1 - schimbare)
bbok: inc si
loop bbli ;
or di,di ; pozitionare indicatori logici
jnz bbl ; di = 1, sir neordonat
pop bx
pop cx
pop dx
pop di ; restaurare registre
retf
bubble endp
------------------------
MEMORIE CENTRALA
91
Programe 8x86/87
Date 8x86/87
PROCESOR PROCESOR VF
8 x8 6 8x87
Cele doua procesoare folosesc aceleasi magistrale de date si adresa (BUS). Coprocesorul nu are
mecanism propriu de calcul al adreselor (segment,baza,index), acest calcul se face in 8x86, care-i
furnizeaza adresa instructiunii curente (IP-instr.pointer) si adresa operandului (OP-operand pointer) in forma
reala. Sunt admise toate modurile de adresare, dar adresa se calculează în procesorul de bază 8x86.
Coprocesorul 8x87 nu are instrucţiuni propri de salt.
Instructiunile de VF sint recunoscute dupa primii 5 biti din codul operatiei, care sint aceeasi 11011 si
se numesc ESCAPE. Cind lucreaza coprocesorul pune BUSY=1 (primul bit din status word), pentru a putea
fi testat de procesorul 8x86 in WAIT.
Unitatea de comanda si control contine 5 registre (14 octeti), care pastreaza starea momentana a lui
8x87 (ENVIRONMENT). Ele pot fi memorate la adrese consecutive prin FSTENV (store environment) si
ulterior incarcate prin FLDENV (load environment).
15 0
+0 CONTROL WORD -precizie,masti de intrerupere
+2 STATUS WORD - indicatori,stare si intrerupere
+4 TAG WORD - indicatori reg
+6 INSTRUCTION - adresa reala,
+8 POINTER cod instructiune curenta
+10 OPERAND - adresa reala
+12 POINTER operand
92
Starea completa a coprocesorului cuprinde si cele 8 registre generale (stiva) de 10 octeti fiecare
(14+8*10=94 octeti),se poate memora prin FSAVE si restaura prin FRSTORE.Salvarea registrelor se face
cu octetii mai putin semnificativi in fata si in ordinea ST(0),ST(1),....ST(7), dupa registrele
ENVIRONMENT.
15 0
INSTRUCTION POINTER -low (bitii 15-0)
IP -high | 0 | OPERATION CODE
15 12 10 0
Registrul OPERAND POINTER contine pe 20 biti adresa reala (calculata de 8x86) a operandului
din memorie utilizat in instructiunea curenta.
15 0
OPERAND POINTER -low adress (bitii 15-0)
OP high | 0 0 0
15 12 0
Registrele generale organizate ca stiva circulara are fiecare 80 biti,pentru precizie maxima (1-
semn,15-exponent, 64- mantisa sau "significand"). Toate datele primite din memorie se convertesc si se
pastreaza in VF format lung (temporary).Din memorie se pot incarca numere intregi binare,numere in
zecimal codificat binar (BCD) de 18 cifre si numere codificate in VF. Conversiile necesare se fac la citirea
sau scrierea in memorie utilizind instructiuni specifice.
15 biţi 64 biţi
S EXPONENT MANTISA
R0 ST(6)
R1 ST(7)
R2 ST(0) <--TOP=2
R3 ST(1)
ST(2)
R7 ST(5)
79 63 0
La un moment dat oricare registru poate fi virful stivei ST(0), iar urmatorul ST(1).Celelalte registre
vor avea o adresa relativa fata de ST(0). Numarul registrului virf de stiva se gaseste memorat in zona TOP
din STATUS WORD. Operatiile de incarcare decrementeaza TOP cu 1 si incarca in noul registru
ST(0). Operatiile de memorare cu "pop" memoreaza din ST(0) si incrementeaza TOP cu 1.
93
- indicatorii de conditii, pozitionati dupa efectuarea instructiilor de comparatie/test, care se pot memora
cu FSTSW (store status word) pentru a fi analizate de 8x86, cind trebuie sa se faca salturi conditionate
(8x87 nu are instructiuni de salt).
- bitii care indica aparitia unor cereri intreruperi spre 8x86, sau datorate rezultatelor obtinute
- indicatorul registrului virf de stiva TOP
15 14 13 10 9 8 7 6 5 4 3 2 1 0
B C3 TOP C2 C1 C0 IR P U O Z D I
15 12 11 9 7 5 4 3 2 1 0
rezervat IC RC PC IEM x PM UM OM ZM DM IM
94
Raspunsurile la fiecare exceptie mascata (masca = 1)sint:
PM - Precision Mask - furnizeaza rezultatul rotunjit
UM - Underflow Mask - rezultat = 0
OM - Overflow Mask - rezultat = numar maxim cu semn
ZM - Zero divide Mask -rezultat = numar maxim cu semn
DM - Denormalized - continua calculul cu nr.nenormalizat
IM - Invalid operation Mask - rezultatul este valoarea nenumerica a operandului
(ex: radical din numar negativ)
Sint admise 7 tipuri de date, care pot fi operanzi din memorie si care prin incarcare se convertesc in
format intern Virgula Flotanta (VF) pe 80 biti numit Temporary Real.In registrele interne se pastreaza datele
numai in format VF de unde se pot memora in alte formate prin instructiuni specifice, care asigura si
conversia. Specificarea adresei operandului se poate face in toate modurile admise de 8x86, care asigura
calcularea adresei. In toate tipurile primul bit este considerat semn, iar bitii din stinga sint cei mai
semnificativi. Caracteristicile tipurilor admise sint date in tabelul urmator:
In real mantisa este pozitiva si da precizia, iar semnul este al mantisei (S = 1 negativ). Bitii de
exponent dau caracteristica (CAR), care este pozitiva. Valoarea exponentului (EXP) se calculeaza:
EXP = CAR - 7FH - pentru SHORT REAL
- 3FFH - pentru LONG REAL
- 3FFFH - pentru TEMPORARY REAL
Valoarea unui numar real - N (reprezentat in virgula flotanta) se calculeaza dupa formula:
N = M*2**EXP unde: M - este valoarea mantisei 1 < M < 2
EXP - valoare calculata exponent
Tipurile intregi cu semn sint cele acceptate de procesorul 8x86 si de Macroasamblor prin
directivele de definire date:
95
DW - define word - pentru WORD INTEGER ( 16 biti )
DD - define double-word - pt. SHORT INTEGER ( 32 biti )
DQ - define quad-word - pt. LONG INTEGER ( 64 biti )
Tipul PACKED DECIMAL utilizeaza 10 octeti si este un numar zecimal codificat binar cu semn
(BCD), avind 18 cifre zecimale, codificate fiecare pe 4 biti (doua pe octet). Primul octet contine doar
semnul pe primul bit.
79 71 63 56 .......... 15 7 0
S * D17D16 D15D14 D13 .......... D4 D3D2 D1D0
Tipul este recunoscut de macroasamblor prin definitia:
DT -define ten-byte in care valoarea se specifica in hexa
SHORT REAL
31 30 22 0
S E7 ... EO f1 f2 .... f22 f23 - in mantisa 1 este implicit
- EXP < 127 (7FH)
exponent mantisa - mantisa 6-7 cifre zecimale
LONG REAL
63 62 51 0
S E10 E0 f1 f2 f3 ....... f51 f52 EXP < 1023 (3FFH)
- mantisa 15-16 cifre zec.
TEMPORARY REAL
79 78 63 0
S E14.... E1 E0 1^f1 f2 f3 f14 ...... f62 f63
Pentru generare de cod pentru coprocesor Macroasamblorul se poate lansa in doua moduri
MASM ...... /R - genereaza cod real executabil pe 8x87 existent
/E - emulare - genereaza chemari de subprograme din biblioteca pentru
mnemonice 8x87 intilnite
Codurile instructiunilor 8x87 generate in modul /R pot fi executate fara a exista fizic coprocesorul daca se
lanseaza inainte :
EM87 /L
96
Acesta incarca un emulator 8x87 rezident in memorie, care se apeleaza prin intreruperile de exceptie
instructiune inexistenta, declansate de codurile 8x87 din program. La terminarea programelor care utilizeaza
mnemonici 8x87 emulatorul se elimina prin:
EM87 /U - descarcare emulator 8x87 din memorie
Coprocesorul 8x87 executa 69 instructiuni (72 la 80287). Instructiunile de transfer 8x87 executa
incarcarea(sau memorarea) datelor, de tipurile precizate, din memorie in registrul ST(0), sau intre registrele
8x87. Schimbul de date cu memoria este insotit de conversia lor in temporary real daca e cazul, sau
ajustarea mantisei si exponentului,pentru SHORT si LONG REAL.
Toate instructiunile de incarcare decrementeaza inainte stiva.Nu exista instructiuni imediate. Pentru
transferul datelor intre locatii de memorie se folosesc instructiunile 8x86 cunoscute. Pentru precizarea unei
adrese de operand din memorie se pot folosi toate modurile de adresare. Reg. ST(0) se poate nota ST.
Prezentam sintetic instructiunile din aceasta grupa:
97
Transferuri de numere reale intre ST si memorie:
FLD real - incarcare numar real din memorie in ST
FST real - memorare ST la o adresa de memorie
FSTP real - idem ca FLD urmat de decrem. stiva registre
Prin instructiunea FSTSW indicatorii de conditii 8x87, pozitionati dupa executia instructiunilor de
VF, se depun in memorie sau AX de unde se pot depune in reg. FLAGS al lui 8x86 prin SAHF (instructiune
8x86). Valoarea acestor indicatori se poate testa prin instructiunile de salt conditionat (Jcond), uzuale pentru
a realiza ramificari ale programului. Mentionam ca 8x87 nu are instructiuni proprii de salt. Indicatorii
C3 - C0 se vor memora automat peste Z si S. Reg. FLAGS se poate incarca in AH prin LAHF.
98
Toate unstructiunile din aceasta clasa includ un FWAIT pentru sincronizare cu 8x86. Ele au si forma
fara FWAIT cind au prefixul FN (ex: FNSTSW,FNSTCW, ...FNSAVE, FNRSTORE).
12.5.Instructiuni aritmetice in VF
Aceasta grupa cuprinde instructiuni puternice de calcul matematic, pentru care a fost conceput
coprocesorul matematic. La 80287 fata de 8x87, se adauga doar 3 instructiuni pentru control in mod
protejat. Setul lui 80387 cuprinde citeva instructiuni in plus care vor fi indicate.
FWAIT - asteapta terminarea unei instructiuni 8x87
FNOP - nici o operatie
FABS - valoare absoluta din ST |ST| => ST
99
0 1 ST > referinta (rezultat < 0)
1 0 ST = referinta (rezultat = 0)
1 1 -rezultat +infinit sau -infinit
Indicatorii C3--C0 fac parte din primul octet din STATUS WORD, se memoreaza cu FSTSW
AX, in AX de unde se depun cu SAHF in reg FLAGS si se pot testa cu instructiuni de salt
conditionat.
Instructiuni speciale
Folosind instructiunile prezentate si exemplele de program se vor scrie programe, care sa utilizeze
numere reale, intregi si zecimale codificate binar (BCD) pentru calcule matematice utizind coprocesorul
8x87, real s-au emulat cu EM87 /L. - Se va asambla programul si pentru datele constante generate cu
diferite lungimi se va studia modul de codificare si se vor calcula valorile in zecimal pentru numerele reale.
- Se va studia modul de codificare a instructiunilor de VF
- Se va scrie un program pentru una din problemele:
- rezolvarea unei ecuatii de gradul 2,
- calcul sin(x) si cos(x) prin dezvoltare in serie,
- extragerea radacinii patrate dupa formula iterativa:
X(i)= [N/X(i-1)+X(i-1)]/2 - unde X(1)=N/2
- calculul unei integrale definite cu metoda trapezelor
Prezentam mai jos listingul unui exemplu de program simplu in care se declara diferite tipuri de
variabile si se executa citeva instructiuni. Programul va trebui lansat din DOS sau CodeView. El va afisa pe
ecran rezultatul adunarii a doua numere zecimale codificate binar Y3 = Y1 + Y2. Cele doua numere au fost
alese incit rezultatul sa fie de "tip ASCII" pentru a putea fi afisat direct pentru verificare. Se va afisa 8754.
.model small
0100 .stack 256
* segment de date *
0000 .data
0000 1B2F5D40 x1 dd 3.456
0004 33338340 x2 dd 4.1
0008 08070504000000000000 y1 dt 4050708h
0012 30303030000000000000 y2 dt 30303030h
101
001C 00000000000000000000 y3 dt 0
0026 24 db '$'
0027 00000000 x3 dd 0
002B 0000803F x4 dd 1.0
002F 0000A040 x5 dd 5.0
DGROUP .. . . . . . . . . . . GROUP
_DATA . . . . . . . . . . 0033 WORD PUBLIC 'DATA'
STACK . . . . . . . . . . 0100 PARA STACK 'STACK'
_TEXT . . . . . . . . . . . 0031 WORD PUBLIC 'CODE'
Symbols:
Name Type Value Attr
102
@CODE . . . . . . . . . . . . . TEXT _TEXT
@CODESIZE . . . . . . . . . . . TEXT 0
@DATASIZE . . . . . . . . . . . TEXT 0
@FILENAME . . . . . . . . . . . TEXT ex1f
30 Source Lines
30 Total Lines
23 Symbols
0 Warning Errors
0 Severe Errors
-------------------------------------------------------------------
Se observa ca numerele zecimale Y1 si Y2 se aliniaza la stinga unde cifrele au si ponderea cea mai
mare.
Numerele X1 si X2 care sint reprezentate in VF (reale) au octetii inversati, incit exponentul si
ponderile mai mari apar in dreapta. Variabila X3=0 are atit mantisa cit si exponentul 0.
104
Consideram un numar binar intreg pe 4 octeti (32 biti), care il vom converti in virgula flotanta (VF)
pe 4 octeti (SHORT REAL)
23c.b.
Numar intreg N
, - virgula pentru mantisa VF , - virgula intreg
Consideram numarul pozitiv intreg N, care are virgula virtuala in dreapta, ca o mantisa supraunitara
cu o caracteristica CAR asociata:
N = N*2**0 => EXP = 0 => CAR = EXP+127 = 127
Daca N este considerat o mantisa pentru reprezentarea VF short real, atunci virgula va fi vazuta
deplasata cu 23 c.b. spre stinga. Pentru a nu schimba valoarea numarului, care devine N*2**(-23), trebuie sa
marim caracteristica cu 23. Pastrind separat mantisa si caracteristica vom avea un numar in VF cu:
M = N*2**(-23) si CAR = 127+23 = 150 -caracteristica initiala
Cum numarul nostru in VF este in general nenormalizat, il vom supune unei normalizari, utilizind o
macroinstructiune NF4, pe care o vom defini si care apeleaza un subprogram SNF4. Numarul ce se
normalizeaza va fi dat prin mantisa M1 si caracteristica C1 separate. Ele vor fi incarcate in DX:AX si
respectiv in BX de macroinstructiunea NF4, care dupa chemarea subprogramului SNF4 obtine numarul in
flotant in DX:AX si il memoreaza peste mantisa initiala (vezi programul alaturat).
Subprogramul SNF4 considera ca mantisa este nenormalizata, existind 2 cazuri:
a) - Este ocupata zona caracteristicii (primul octet), caz in care se fac deplasari spre dreapta a
mantisei si incrementari corespunzatoare ale caracteristicii, pentru a nu modifica valoarea numarului.
b) - Mantisa are zerouri pe primele pozitii dupa virgula si in acest caz se fac deplasari spre stinga si
decrementari ale caracteristicii, pina cind primul bit din octetul 2 al mantisei devine 1.
Deplasarile spre stinga sau dreapta ale mantisei, ce se gaseste in registrele DX:AX se face combinind
o deplasare a unui registru cu rotirea prin carry a celuilalt. Dupa ce mantisa a fost normalizata, primul bit
care este 1 implicit se sterge si mantisa se concateneaza cu caracteristica.
Daca avem macroinstructiunea de normalizare NF4, atunci conversia unui numar intreg in VF se
reduce la o normalizare cu o caracteristica initiala CAR=150
; --------------------------------
105
; PROGRAM DE CONVERSIE INTREG REAL
; ---------------------------------
.286c
.287
dosseg
.model small
.stack 100
.data
x dd 51420 ; nr intreg
xf dd 51420. ; nr in vf
cx1 dw 127+23 ; caracteristica implicita
.code
; Definitie macro pt normalizare vf
nf4 MACRO c1,m1 ; caract. si mantisa
PUSHA ; salvare registre
mov ax,word ptr m1 ; mantisa pe 4 octeti
mov dx,word ptr m1+2
mov bx,c1 ; caract. pe 2 octeti
CALL SNF4 ; subprogram normalizare
mov word ptr m1,ax ; memorare nr. normalizat
mov word ptr m1+2,dx ; peste mantisa initiala
POPA
ENDM
; ---------------------------
; Subprogram normalizare VF
; - intrare mantisa 4 oct in DX:AX si caract in BX
; - iesire nr in vf pe 4 oct in DX:AX
; ---------------------------
snf4 PROC near
; normalizare prin depl dreaapta mantisa si increm. CAR
c11: cmp dh,0 ; test octet1 din mant =0
jz c2 ; octet1=0 depl. stinga
inc bx ; car =car+1 si depl. dreapta DX:AX
shr dx,1 ; DX -> CF -> AX
rcr ax,1
jmp c11
; ------------------------------
; program principal conversie intreg flotant
; ------------------------------
st1: mov ax,@data
mov ds,ax
;
cif: nf4 cx1,x ; conversie intreg real
;
end st1
---------------------------------------------------
Si in acest caz separam caracteristica (CAR) de mantisa (M). Mantisa va furniza cifrele
semnificative ale numarului ( 6-7 la short real), iar caracteristica va da ordinul de marime. Algoritmul va fi
invers decit la conversia intreg - flotant.
8c.b. 23c.b.
MANTISA
'- virgula mantisa vf ' -virgula pt.numar intreg
CAR - caracteristica
Pentru a avea deplasari numai intr-un singur sens, deplasam initial mantisa la stinga cu 8 c.b. si
completam 1 implicit pe primul bit. Vom considera numarul intreg rezultat dupa mutarea virgulei mantisei
(care se gaseste acum dupa primul bit), spre dreapta cu nr. de pozitii indicate de exponent ( EXP = CAR-127
).
Exponentul specifica nr. de cifre binare intregi ale numarului, iar restul fiind biti ce dau zecimale, care se
pierd in cazul numerelor intregi. Vom avea urmatoarele cazuri:
a) EXP = 31 - virgula se va deplasa cu 31 c.b. spre dreapta, chiar peste virgula corespunzatoare numerelor
intregi. Mantisa va reprezenta chiar numarul intreg.
b) EXP < 0 - virgula va trebui mutata spre stinga si numarul va fi < 1, deci intregul rezultat va fi N = 0.
c) EXP > 31 - virgula trebuie mutata cu mai mult de 31 pozitii spre dreapta, rezultind depasire (numar cu
mai mult de 32 c.b.)
107
d) 0 =< EXP < 31 - virgula se va deplasa spre dreapta cu mai putin de 31 c.b. si va trebui adusa pe ultima
pozitie din dreapta, corespunzatoare numerelor intregi. Aceasta se realizeaza cu 31 - EXP deplasari spre
dreapta.
; -------------------------------------
; PROGRAM DE CONVERSIE FLOTANT - INTREG
; ---------------------------------------
.286c
.287
dosseg
.model small
.stack 100
.data
mdep db 10,13,'Depasire!! Nr. in VF prea mare $'
xf dd 51420. ; numar in VF x
dd 0 ; numar convertit intreg
xr dd 51420 ; numar intreg de referinta
109