Индексті айнымалыны йымдастыру

Массивтермен жмыста туатын келесі сра – массивті элементтеріне алай атынауа болады, индексті айнымалылар алай йымдастырылады. Бл сратара жауап беру шін алдымен компьютерді адресті модификациялау трізді ерекшелігімен танысу ажет.

Адресті модификациялау.Бан дейін операндтар шін жадты натылы адрестері (атаулары) крсетілетін командалар арастырылды, мысалы: MOV CX,A. Бірата жалпы жадайда командада адреспен бірге тік жашада андай да бір регистр крсетілуі ммкін, мысалы: MOV CX,A[BX]. Онда команда крсетілген А адресімен емес, орындалатын адрес деп аталатын адреспен (Аорн) жмыс жасайды. Мнда ол адрес келесі формуламен есептеледі:

Аорн= (А+[BX]) mod 216,

мнда [BX] ВХ регистіріні рамы дегенді білдіреді. Басаша айтанда орталы процессор команданы орындамас брын А адресіне ВХ регистіріндегі мнді осады да, андай да жаа адрес алады, міне осы адрестен екінші операнд алынады. (Команда згермейді адресті есептеу процессорды ішінде жасалады.) Егер осу нтижесінде шамадан арты осынды шыса, онда оны соы 16 орны алынады, оны формуладаы mod амалынан креміз.

Командадаы адресті орындалатын адреске ауыстыру адресті модификациалау деп аталады, ал модификациалауда олданылатын регистрді регистр-модификатор немесе жай ана модификатор дейміз. Мнда, модификатор ретінде кез келген регистрді ала беруге болмайды, мысалы, Intil тобы микропроцессорларында ЕBX/BX,ЕBP/BP,ESI/SI жне EDI/DI регистрлеріні бірі ана алынады.

Мысала, ADD A[SI],5 командасын алайы. Мнда модификатор ретінде регистр SI алынан. Онда азір 100 саны тр делік. Олай болса Аорн= А+[SI]=А+100, бл командада 5 саны А адресті емес А+100 адресті яшытаы сана осылатын болады. Егер де SI-де -2(0FFFFh) саны трса, онда Аорн= А-2, сондытан 5 саны А-2 адресті яшытаы сана осылатын болады.

Мысалдан бір команданы зі р трлі адрестермен орындала алатынын креміз. Бл те маызды, осы шін адрестерді модификациялау жасалады. Адрестерді модификациялауды пайдалы болу жадайларыны бірі, индексті айнымалыларды йымдастыруда олданылатын, индекстеу болып табылады.

Индекстеу.Келесі мысалды арастырайы: айталы

X DW 100 DUP(?) ;X[0..99]

массиві берілсін, массивті элементтеріні осындысын АX регистріне жазу керек.

осындыны табу шін, алдымен АХ-ке 0 жазу керек, содан со мына амалды AX:=AX+X[i], мнда і 0-ден 99-а дейін згереді, орындау керек. Х[i] элементіні адресі х+2*і боландытан, оан сйкес команда мынандай болуы тиісті:

АDD AX, X+2*i

Біра мндай команда машиналы тілді жне Ассемблер тіліні ережелеріне айшы келеді: командада оны барлы бліктері, оны ішінде адресі, бекітілген болып, згермеуі керек. Ал, мнда і индексіні згеруімен бірге адрес згеріп отырады.

Сонымен келесі проблемаа тап болды: алгоритм бойынша команда ртрлі адрестермен жмыс істеуі керек (згеретін адрестермен жмыс істейді), ал машиналы тілде тек бекітілген адрес болуы ажет. Міне осы айшылыты болдырмау шін, есептеуіш машиналарында адресті модификациялау енгізілген.

Х+2*і згеретін адресті екі осылыша блеміз: і индексінен туелді емес траты осылыш Х-ке жне индекстен туелді осылыш 2*і-ге. Траты осылышты команданы зіне жазамыз, ал айнымалы осылышты андай да бір регистр-модификатора (айталы SI-ге) жазамыз да осы регистрді командада модификатор ретінде олданамыз:

Не шыты? Мнда команданы жазылу трі згермейді, яни машиналы тілді ережелерін анааттандырады. Екінші жаынан, команда орындалатын адреспен ж мыс жасайды, ал ол командадаы Х адресімен SI регіистріні рамы (2*і)-ді осындысынан шыады. Сондытан біз SI –ді мнін згерте отырып, згермейтін команданы ртрлі адрестермен жмыс жасатамыз. Сйтіп, машиналы тілді де, алгоритміні де талаптарын анааттандырамыз. Ендігі аланы тек SI регистріні рамын дрыс згерту. Ол былай орындалады: алдымен SI-ге 0 жазылады, содан со оны мні 2 адама артып отырады; нтижесінде бізді командамыз Х,Х+2, Х+4,...,Х+198 адрестерімен жмыс жасайды.

Регистр-модификатор индексті сатауа олданылатындытан (длірек айтанда – индекстен туелді рнек), ондай регистр - индекстік регистр, ал индексті айнымалыны адресін алуды сипаттау дісі - идекстеу деп аталады.

Осы айтыландарды ескере отырып, Х массивіні элементтеріні осындысын табу программасыны фрагменті тмендегідей болады:

MOV AX,0 ;осындыны бастапы мні AX:=0

MOV CX,100 ;цикл санаышы СХ:=100

MOV SI,0 ;индексті бастапы мні

L: ADD AX,X[SI] ;AX:=AX+X[I]

ADD SI,2 ;келесі индекс

LOOP L ;100 рет цикл айталануы

Жанама сілтемелер. Адресті модификациялауды пайдалануды таы бір жадайын арастырайы.

Айталы бізге келесі есепті шешу ажет болсын: адресі белгілі емес, біра ол адрес ВХ регистріне жазылан сз лшемді андай да бір яшы бар болсын, осы яшыа бір санды (мысалы 300 санын) жазу керек

Егер ол йяшыты адресі (Х) алдын ала белгілі болса, онда бл есеп MOV x, 300 командасымен шешіледі. Біра программаны ру стінде біз ол адресті білмейміз, сол себепті командада оны крсете алмаймыз. Не істеу керек? Команданы орындалатын адреспен жмыс істейтінін еске тсірейік, сондытан осындысында осы бізге белгісіз адресті беретіндей адрес жне модификатор алу ажет. Бізді жадайымызда нлінші адресті жне ВХ регистрін алу ажет, онда Аорын=0+[BX]=0+x=x. Сондытан бізді есебіміз

MOV [BX], 300

командасымен шешіледі.

Мндаы олданылатын адресті модификациялау тсіліні ерекшелігі: біз адресті екі осылышты осындысы арылы кескіндейміз оны бірі командаа жазылады, ал екіншісі регистрге жазылады, біра брын екі осылышта нлден згеше болатын, енді командаа жазылатын бір осылыш нл, сондытан адрес ттасымен регистрге «жасырылан». Командада біз адрес тран орынды (регистрді) ана крсетеді екенбіз. Мндай адресті аралы байланыс арылы крсету тсілі жанама сілтеме немесе жанама адрестеу деп аталады.

Жанама сілтемеде, детте, ол крсететін яшыты лшемін анытау ажет болатындыын айта кетелік. Егер, мысал шін, адресі ВХ регистрінде тран яшыа нлді жазу ажет болса, онда ол шін MOV [BX],0 командасын олдануа болмайды, бл командада операндтарды лшемі тсініксіз: 0 байт та, сз де бола алады, ВХ адресі де байтты та, сздік те адрес бола алады (жоарыда келтірілген мысалды мндай жадай болмады, себебі 300 саны тек сз лшемді бола алады). Сондытан РТR операторыны кмегімен, операндаларды лшемін крсету ажет:

MOV BYTE PTR [BX],0 ;байтты орналастыру

MOV WORD PTR [BX],0 ;сзді орналастыру

Бірнеше регистр бойынша модификациялау. Адресті модификациялау бір регистр модификатор бойынша жргізілетін жадайды арастырды. Модификациялау идеясын бірнеше модификаторларды олдануа жеіл жалпылауа да болады. Ол шін командада адреспен бірге бірнеше осындай регистрлер крсету керек. ДК-де бірден екі модификатор крсетуге рсат берілген, оны біреуі міндетті трде ЕBX/BX немесе ЕBP/BP регистрлеріні бірі, ал екіншісі ESI/SI немесе EDI/DI регистрлеріні біреуі болуы ажет (ЕBX/BX жне ЕBP/BP немесе ESI/SI жне EDI/DI ережесін олдануа боламайды). Мысалы:

MOV АХ,А[BX][SI]

Бл жадайда орындалатын адрес, келесі формуламен есептеледі:

Аорын = (A+[BX]+[SI]) mod 2 16

Екі регистр бойынша модификациялау детте екі лшемді массивтермен жмыста олданылады. Айталы, мысал шін, 10×20 ретті А матрицасы берілсін:

A DB 10 DUP (20 DUP(?)) ;A [0..9,0..19].

Ассемблер тілінде модификацияланатын адрестерді жазу. Ассемблер тілінде модификацияланатын адрестерді жазу ережелерін натылайы. Айталы А адресі рнектерді білдірсін, ал Е кез келген рнек (адрестік немесе тратылы), онда ассемблер тілінде командада адрестерді жазылу формасыны келесі ш трін олдануа болады

A: Aорн=A

E[M]: Aорн=(E+[M]) mod 216 (M: BX,BP,SI,DI)

E[M1][M2]: Aорн=(E+[M1]+[M2]) mod 216 (M1:BX,BP;M2:SI,DI)

(Ескерту. Егер Е=0 болса, онда 0-ді жазбауа болады: 0[M]=[M])

Таыда айта кетейік, ДК-де регистр-модификатор ретінде тек ана ВХ,ВР,SІ немесе DI регистрлерін пайдалануа болады. Бір регистр бойынша модификациялауда ана, осы трт регистр олданылады. Ал екі регистр бойынша модификациялауда регистр-модификаторларды кез келген жбын олдануа рсат етілмеген, бір регистр ВХ немесе ВР, ал екінші регистр SI немесе DI бола алады.

ВР регистрі жайлы ескерту. Бл регистр детте элементтерге атынау шін стекпен жмыс істеуде олданылады, ол жайлы кейінірек арастырылады. Бл регистрді жадты баса айматарынан адресті модификациялауда олдануа болмайды (длірек айтанда, болады, біра ерекше тсілдермен).

Адресті модификациялау адресті типін згертпейді: егер Х - байтты айнымалыны аты болса, онда TYPE X[SI]=BYTE, егер модификатор алдында тратылы рнегі крсетілсе (мысалы, 1[BX]) онда ондай адресті типі аныталмаан болып есептеледі.

Ассемблер тілінде крсетілген адрестерді жазылуыны ш негізгі тсілдерден баса, осы шеуінен туындайтын, трлері рсат етілген.

Біра оларды арастырмас брын ассемблер тілінде келісілген команданы операндтарыны жазылуында олданылатын тік жашаларды олданылуын сипаттай кетейік:

1) тік жашаларда регистр-модификаторларды атауларыны жазылуы (ВХ,ВР,SI,DI) осы регистрлерді рамын алуды крсетеді (регистрді аты тік жашада жазылмаса сол регистрді зін крсетеді).

Мысалы:

A DW 99

AA DW A

. . .

MOV BX,AA ;A адресін BX-ке

MOV CX,[BX] ;CX:=A (CX:=99)

MOV CX,BX ;CX:=BX(CX:=А адресі)

Ескерету. Модификатор емес регистрлерді атауларын тік жашалара алып жазуа болмайды.

2) Кез келген рнекті тік жашалара алуа болады, одан оны маынасы згермейді (жашаны алып тастау, маынасын згертіп жіберу ммкін).

Мысалы:

MOV CX,[2] ;=MOV CX,2

MOV CX,[A] ;=MOV CX,A

MOV CX,[A+2[BX]] ;=MOV CX,A+2[BX]

3) Келесі жазулар эквиваленті

[x] [y] = [x]+[y] = [x+y]

Басаша айтанда, екі рнекті атар тік жашалара жазу, осы рнектерді осындысын білдіреді.

Мысалы:

MOV CX,[BX][SI] ;= MOV CX,[BX]+[SI] = MOV CX,[BX+SI]

Осы келісімдерді осуды коммутативтік асиетімен бірге олданса жне командаларда адрестерді жазылуыны ш негізгі тсіліне сйенсек, онда адрестерді жазуды баса нсаларын алуа болады. Мысалы, келесі р жолда бір адресті жазылуыны эквивалентті формалары келтірілген:

A+1,[A+1],[A]+[1],[A][1],A[1],1[A],[A]+1, …

5[SI],[5][SI],[5]+[SI],[SI+5],[SI]+5, …

A-2[BX],[A-2]+[BX],[A-2+BX],A[BX-2],A[BX]-2, …

A[BX][DI],A[BX+DI],[A+BX+DI],A[BX]+[DI], …

0[BX][SI],[BX][SI],[BX]+[SI],[BX+SI],[SI][BX], …

Сонымен, ассемблер тілінде бір адресті ртрлі тсілдермен жазуа болады. Дегенмен, мнда олданылатын тсілдерді адрестерді жазуды негізгі ш формасыны біріне эквивалентті болу керектігін есте сатау керек. олдануа болмайтын кейбір жадайлар:

· екі адресті осындысы (А+В);

· біреуі (ВХ+2) регистрі болатын осылыштарды осындысы;

· регистрлерді тыйым салынан жазылу трлері ([SI+DI]);

· модификатор болмайтын регистрлер (A[CX],2[BL]);

· тік жашаларды сыртындаы атаулар мен сандар ([SI]5,[BX]A).

Сонымен атар, адрес сан трінде берілмейді ([5]), онда ол адрес емес тратылы рнегі болып саналады. Баса жадайларда шектулер жо, ркім зіне наан жазуды трін тадайды. Келешекте біз жашаларды алдында айнымалыны аты, ал баса осылыштары тік жашада жазылатын трін олданамыз. Бл жазулар программалау тілдерінде индексті айнымалыларды белгілеуге сас (A[i+3]).

Таыда бір ескерту. Модификаторлы адрестік рнектерді командаларды операндтарын жне кейбір директиваларды (EQU,PTR жне т.б.) жазуда олдануа болады, біра мліметтерді анытау директиваларында еш ашан олдануа болмайды. Мысалы,

Х DW 1[SI]

асссемблер оны операндтарын программаны трансляциялау сатысында оны мнін х яшыына жазатын боландытан бл директива ате болып табылады.

Мысалдар

Мнда массивті деуге арналан мысалдар арастырылады. Бл мысалдарда индекстік регистрлерді олдану жне есепті шешімдерін тсіндіру келтіріледі. Мліметтерді енгізу-шыаруды Паскальда жасалан. Паскальдаы программа негізгі программа болады да, одан ассемблер модулі шаырылады немесе кіріктірілген Ассемблер олданылады.

Мысал

N EQU 10

X DW N DUP(?) ;X[0..N-1]

Х массивіні элементтерін табалы бтін сандар деп арастырып, массивті максималды элементін (егер мндай элементтер бірнешеу болса біріншісін) жне оны индексін табу керек.

Шешуі.Адрес (X[i]=X+2*i) боландытан индекстік регистр ретінде олданылатын регистрде (айталы SI регистрінде) екі еселенген индексті (2*і) олдануа тура келеді. зірге максималды элемент жне оны индексі ізделгенде екі еселенген индекспен жмыс жасалады, содан со ана соында максимальды элементті екі еселенген индексін, натылы индексті табу шін, екіге блеміз.

Паскальда жазылан Mas_Max.pas программасыны мтіні:

Program Mas_Max; {$L Mas_Max.obj} { SIM.obj Ассемблер модулін осу} {$f+}{FAR–процедуралар мен функцияларды шаыру директивасы} label l1,l2; type m: array[0..100] of byte; var n: word; i: byte; Max: word; x: m; {Ассемблерде жазылан сырты процедураны сипаттамасы} Procedure Mas_Max(var n:word;X:m; var i:byte; mas:word);{FAR;}external; begin Writeln('Массииті элементтер саны='); Readln(N); For i:=1 to n Do Read(X[i]); Mas_Max (n,x,I,Max); Writeln('i=',I,’ Max=’,Max); Readln end.

Ассемблерде жазылан Mas_Max.asm модуліні мтіні:

;Mas_Max.asm Ассемблер модуліні мтіні .MODEL Large .data ;Мліметтер Паскальдан алынып-беріледі ;n массивті элементтер саны, Х берілген массив Extrn n:Word, x:word ;нтижесі: Max жне оны индекісі І Extrn i:byte, max:word .code Public Mas_Max Mas_Max proc far MOV BX,X ;BX=X[0] (бастапы max) MOV ax,0 ;AX=2*(max-ты индексі),аашыда 0 MOV SI,0 ;SI=2*і MOV CX,N ;цикл есептегіші l1: CMP X[SI],BX ;X[i]= max? JLE l2 ;X[i]<= max боланда àL2 MOV BX,X[SI] ;жаа max-ды сатау MOV ax,si ;max-ні индексі l2: ADD SI,2 ;SI=SI+2 LOOP l1 ;àL1 MOV CL,2 ;CL=2 DIV CL ;CL div 2 mov,bx ;max mov i,al ;i ret Mas_Max endp End

Мысал

N EQU 50

S DB N DUP(?) ;S[0 . . N-1]

Y массивіні элементтерін екі орына ала біртіндеп жылжыту керек.

(S[0],S[1],S[2],…,S[N-1])à(S[2],…,S[N-1],S[0],S[1])

Шешуі.Мнда циклда S[i]=S[i+2] амалын орындау керек. Осылайша, егер индекстік регистрде (айталы DI –де) оларды біреуіні индексі (і) жазылса, онда Y массивіні кршілес элементіне де сілтеме жасайды. Y[i+2] элементіне сілтеме жасау алдында ол регистрді мнін арнайы жолмен рине згертуге (і+2-ні жазуа), содан со оны алашы мнін (і) алпына келтіру арылы жасауа болады. Біра та басаша жасаан жеілірек:

(S[i])=Y+i

(S[i+2])= S+(i+2)=(S+2)+i

болса, онда DI=i боланда S[i]-ге cілтеме S[DI] адрестік рнегімен беріледі, ал S[i+1]-ге сілтеме S+2[DI] немесе S[DI+2] рнегімен беріледі. Сйтіп, 2-ні осуды, индекстік регистрде жасаудан крі, команданы зінде крсеткен ыайлы.

Кіріктірілген Ассемблерді пайдаланып Паскальда жазылан Mas_ Misal_2.pas программасыны мтіні:

Program Mas_Misal_2; label l1; type m: array[0..100] of byte; var n: word; i: byte; Y: m; begin Writeln('Массииті элементтер саны='); Readln(N); For i:=1 to n Do Read(X[i]); asm LEA BX,Y MOV AH,[BX] ;Y[0] жне Y[1]-ді тару MOV AL, [BX+1] MOV CX,N ;цикл есептегіші ADD CX,2 ; CX=N+2(ала жылжулар саны) L1: MOV DH,[BX+2] MOV [BX],DH ;Y[i]:=Y[i+2] INC BX ;i:=i+1 LOOP L1 MOV [BX],AH ;Y[n-2]:=Y[0] MOV [BX+1],AL ;Y[n-1]:=Y[1] end; For i:=1 to n Do WRITELN(‘Y[‘ , I, ’]=’, Y[i]); end.

Мысал

N EQU 50

Y DB N DUP(?) ;Y[0 . . N-1]

S массивіні симметриялы екендігін, яни оны массивті шеттерінен бірдей ашытытарда орналасан элементтері те екендігін анытау ажет жне 1 (симметриялы) немесе 0 (симметриялы емес) нтижені AL регистріне жазу ажет.

Шешуі.Мнда циклда S[i]-ші жне S[N-1-і], і 0-ден (N div 2)-ге дейін згереді, элементтерін салыстыру керек. рине бірінші элементке атынау шін і-ші индексті біліп, екінші элементке атынау шін N-1-i индексін алуа болады, дегенмен ол шін бірнеше команда орындау ажет. N-1-i шамасын жаа (j) индексі деп есептеп, бірден і мен j-ді бір уаытта бірге арттыру арылы екі индекспен жмыс істеуге болады.

Паскальда жазылан SIM_PAS.pas программасыны мтіні:

Program SIM_PAS;

{$L SIMMET.obj} { SIM.obj Ассемблер модулін осу}

{$f+}{FAR–процедуралар мен функцияларды шаыру директивасы}

label l1,l2;

type m:array[0..10] of byte;

var n:word; x,i:byte;

s:m;

{Ассемблерде жазылан сырты процедураны сипаттамасы}

Procedure SIM(var n:integer;s:m; var d:integer);{FAR;}external;

begin

Writeln('Массииті элементтер саны='); Readln(N);

For i:=1 to n Do Read(s[i]);

SIM (n,s,x);

Writeln('X=',X);

Readln

end.

Ассемблерде жазылан SIM.asm модуліні мтіні:

;mis_Mas.asm

;Sim_Mas Ассемблер модуліні мтіні

.MODEL Large

.data

;мліметтер Паскальдан алынып-беріледі

;n массивті элементтер саны, s

Extrn n:Word, s:byte

;нтиже: массив симмериялы болса X=1, йтпесе X=0

Extrn x:byte

.code

Public sim

sim proc far

mov dl,2 ;dl=2

MOV x,0 ;x=0

MOV SI,0 ;i:=0

MOV DI,N

dec di ;j:=n-1

mov ax,n

div dl ;n div 2

MOV Cl,al ;Cl=n div 2

mov ch,0 ;CX=n div 2

;салыстырылатын жптар саны

L1: MOV AH,S[SI]

CMP AH,S[DI] ;S[i]=S[j]?

JNE FIN ;те емес ? AL=0-мен шыу

INC SI ;i:=i+1

DEC DI ;j:=j-1

LOOP SYM ;à L1

MOV x,1 ;барлы жптар те ? X=1

L2:

ret

sim endp

End

8.1.3.4-мысал. Матрицаны жолыны алашы элементі сол жолда таы да кездесетін жолдар санын АL регистріне жазу керек.

Шешуі. Матрицаны элементтерін жол бойымен орналастыруда (алашы 20 байт – матрицаны бірінші жолы, келесі 20 байт - екінші жолы жне т.с.с.) А[I,j] элементіні адресі А+20*i+j. Мндаы 20*і шамасын сатау шін ВХ регистрін аламыз, ал j-ді сатау шін SI регистрін аламыз, онда A[BX] - матрицаны і-ші жолыны алашы адресі, ал A[BX] [SI] сол жолды j-ші элементіні адресі.

MOV AL,0 ;ізделетін жолдар саны, алашыда 0

;сырты цикл (жолдар бойынша)

MOV CX,10 ;сырты цикл есептегіші

MOV BX,0 ;А-дан (20*і) жолды басына дейін ту

L: MOV AH,A[BX] ;АН жолды алашы элементі

MOV DX,CX ;сырты циклды СХ-ін тару

;баандар бойынша ішкі цикл

MOV CX,19 ;ішкі цикл есептегіші

MOV SI,0 ;j-ші жолдаы элементті индексі

L1: INC SI ;j:=j+1

CMP A[BX][SI],AH ;A[i,j]=AH?

LOOPNE L1 ;зірше A[i,j]<>AH боланынша циклды айлалау

JNE L2 ;AH айталанан жо àL2

INC AL ;жолды есепке алу

;ішкі цикл соы

L2: MOV CX,DX ;СХ-ті сырты цикл шін алпына келтіру

ADD BX,20 ;келесі жолды басына ту

LOOP L ;10 рет циклды айталау

Дріс №11,12