Процедурада регистрлерді сақтау


Жұмыс түрі:  Материал
Тегін:  Антиплагиат
Көлемі: 32 бет
Таңдаулыға:   

Мазмұны

9. 2. 1. Подпрограмманы қай жерге орналастыру керек. 1

9. 2. 2. Подпрограмманы қалай безендіреді2

9. 2. 3. Процедураларды шақыру және олардан қайту. 3

9. 2. 4. CALL командасының басқа варианттары. 7

9. 3. Регистр арқылы параметр беру. 8

9. 3. 1. Мәндер бойынша параметрлерді беру. 9

9. 3. 2. Жөнелту арқылы параметрлер беру. 9

9. 3. 3. Процедурада регистрлерді сақтау. 11

9. 3. 4. Қиын түрдегі параметрлерді беру. 12

9. 4. Стек арқылы параметрлерді беру. 13

9. 5. Процедуралардың жергілікті берілгендері. 18

9. 6. Рекурсивті процедуралар. 21

10 ТАРАУ. Берілгендердің динамикалық құрылымдары. 25

10. 1. Жолдық командалар. 25

10. 1. 1. Жолдарды салыстыру командасы. 26

10. 1. 2. Қайталау префикстері. 29

10. 1. 3. Басқа жолдық командалар. 34

9. 2. 1. Подпрограмманы қай жерге орналастыру керек.

Бірінші проблема - ол қай жерге подпрограмманы орналастырамыз? Жалпы айтканда кез-келген жерде. Бірақта сонымен қатар подпрограмма өзінен өзі орындалмауы керек, ал тек оған жолдағанда ғана орындалуы тиіс екенін түсіну керек. Соңдықтан оларды байқаусыздан басқару оларға көшпегендей орналастыру керек. Егер бірнеше подпрограмма болса, әдетте оларды қатар орналастырады. Әдетте подпрограмманы (n/n) не FІNІSH командасынан кейін командалар сегментінің соңына (қар а сурет) не бағдарлама орындала басталатын команданың алдында, яғни осы сегментінің ең басында (б-суреті) . Үлкен бағдарламаларда подрпаграммаларды көбінесе бөлек командалар сегметінде орналастырады (в-суретің қар)

С SEGMENT С SEGMENT С1SEGMENT

BEG: ….

FІNІSH

BEG: …. C1 ENDS

С SEGMENT

C ENDS C ENDS BEG: ….

END BEG END BEG …. .

a) б) C ENDS

END BEG

в)

9. 2. 2. Подпрограмманы қалай безендіреді

Екінші проблема ол подпрограмманы қалай сипаттау керек? Жалпы жағдайда подпрограмма құрайтын командалар тобын бағдарлама тексінде ешқалай белгілемеуге болады. Бірақта ЯА-да подграммаларды әдейі безендіру бекітілген. Ол процедуалар түрінде. Ол белгілі бір пайда келтіреді. Бірақта ол туралы кейіңірек. Алдағы уакытта біз тек процедура ретінде сипатталған подрограммаларды қолданамыз.

Подпрограммаларды процедура түрінде сипаттау былай болады:

<процедура есімі>PROC<параметр>

<процедура денесі>

<процедура есімі>ENDP.

Көріп отырғандарыңыздай процедура денесінің /оның командаларының алдында РRОС /procedure/ директивасы қойылады, ал одан кейін -ENDP директивасы /end of procedure/. Бұл қос директивада да бір есім көрсетіледі. Ол есім болып табылады. РRОС директивасында есімнен кейін қос нүкте қойылмайтынына көңіл бөлу керек, бірақта ол есім белгі болып саналады. Ол процедуранын бірінші командасына бағытталған деп саналады. Мысалға, процедура есімін көшу командасында көрсетуге болады, онда процедураның бірінші командасына көшу жасалады.

РRОС директивасында параметр болмауы да мүмкін, онда ол NEAR-ға тең деп саналады. /осыған байланысты көбінесе NEAR параметрі көрсетілмейді/ NEAR параметрінде не параметр жоқ болғанда процедура жақын, ал FAR параметрінде -алыс болады. Жақын процедураға тек ол сипатталған командалар сегментінен жолдауға болады. Ал басқа сегменттерден болмайды, ал алыс процедураларға кез-келген сегменттен жолдануға болады. Жақын және алыс процедураларының айырмашылығы тек осында.

ЯА-да процедурада сипатталған есімдер мен белгілер оның ішінде жерлігіктенбейді, сондықтан олар уникальды болуы тиіс, яғни басқа есімдермен сәйкес келмеуі тиіс. ЯА-да бір процедураны екінші процедура ішінде сипаттауға болса да, ол ешқандай пайда бермейді, сондықтан ЯА-да процедураларды бір-біріне салу қолданылмайды.

9. 2. 3. Процедураларды шақыру және олардан қайту.

Келесі проблема - ол процедураларды қалай шақыру және олардан қалай қайту? Жоғары деңгейдегі тілге программалағанда процедураны жұмысқа қосу үшін тек оның есімін және параметрлерін жазу жеткілікті. Сонымен қатар процедура жұмысын қалай бастайды, басқаруды негізгі бағдарламаға қалай қайтаратыны бізді ойландырмайды: осының барлығы үшін транслятор жауап береді. Ал егер біз ЯА-да бағдарлама жасасақ, онда негізгі бағдарламамен процедуралар арасындағы көшулерді өзімізге жасуға тура келеді. Ол қалай жасалатынын қарастырайық.

Мұнда екі проблема: негізгі бағдарламадан процедураны жұмыс істетуге болады және процедурадан негізгі бағдарламаға қалай қайту. Бірінші проблема қарапайым түрде шешіледі: процедураның бірінші командасына көшу жасасақ жеткілікті, яғни көшу командасында процедура есімін көрсетсек жеткілікті. Екінші проблема қиындау. Себебі процедураға негізгі бағдарламаның кез-келген жерінен жолдауға болады, және сондықтан процедурадан әртүрлі жерге қайту керек. Процедураның өзі басқаруды қай жерге қайтару керек екенін білмейді, бірақта оны негізгі бағдарлама біледі. Сондықтан процедураға жолдағанда негізгі бағдарлама міндетті түрде қайтатын адресті - процедура өз жұмысын бітіргеннен кейін көшу жасауға міндетті негізгі бағдарлама командасының адресін хабардар ету керек. Әдетте бұл процедураға жолдау командасынан кейінгі команда. Нақты осы адресті негізгі бағдарлама процедураға хабарлайды, нақты осы адрес бойынша процедура негізгі бағдарламаға қайтады.

Процедураға әртүрлі жерден жолдау жасағандықтан және қайту адресі әртүрлі көрсеткендіктен, басқаруды негізгі бағдарламаның әртүрлі жерінен қайтарады.

Қайтару адресін қалай хабардар етеді? Оны әртүрлі жолдармен жасауға болады. Біріншіден, регистр арқылы беріп жіберуге болады: негізгі бағдарлама қандайда бір регистрге қайтару адресін жазады, ал процедура оны сол регистрден алып сол бойынша көшу жасайды. Екіншіден, стек арқылы жасауға болады: процедураға жолданбастан бұрын негізгі бағдарлама қайтару адресін стекқа жазады, ал процедура оны содан алып сол бойынша көшу жасайды. ПК-да қайтару адресі стек арқылы беру бекітілген, сондықтан алдағы уақытта біз қайтару адресін берудің тек осы жолын қарастырамыз.

Қайтару адресін стек арқылы беру және осы адрес бойынша қайтаруды біз білетін командалар көмегімен жүзеге асыруға болады. бірақта реал бағдарламаларда процедуралар өте жиі қолданылады, сондықтан ПК командалар жүйесіне негізгі бағдарлама мен процедуралар арасындағы көшулерді жасауды оңайлататын әдейі командалар қосылған. Олар CALL және RET командалары. Бұл командалардың негізгі варианттары келесі:

процедураны шақыру (қайтарымды көшу) : CALL<процедура>

процедурадан қайту (return) :RET

CALL командасы стекқа өзінен кейін келетін команданы жазады және содан кейін келетін команданы жазады және содан кейін көрсетілген процедураның бірінші командасына көшу жасайды. RET командасы стек шынынан адресті оқып көшуді сол бойынша жасайды.

Келесі мысалда қарастырайық. Біз өз бағдарламамызды реттелік делік және ол үшін оның әртүрлі жеріне х және у бірдей айнымалылардың реттеуші жазуларын қоямыз. Мұндай жазулар бірнеше командамен жүзеге асады, олар бірнеше рет қайталанады, сондықтан бұл жазуды процедура ретінде сипаттап негізгі бағдарламада оған тек қысқа жолдаулар көрсету мәнді болады:

; негізгі бағдарлама ; процедура

. . . PR PROC

CALL PR OUTІNT X

(a) . . . OUTІNT Y, 8

. . . NEWLІNE

CALL PR RET

(b) . . . PR ENDP

Бірінші CALL командасы орындалғанда ол өзінен кейін келетін команданың адресін стекқа жазып басқаруды PR процедураның басына - OUTІNT X командасына береді. Процедура жұмыс істей бастайды: ол Х және У-ті жазып жолды тасымалдайды. Содан кейін RET командасы стектағы адресін алып сол бойынша көшу жасайды. Осылайша бірінші CALL командасынан кейін келетін командадан негізгі бағдарлама жұмысы қайта басталады. Процедураға кезекті жолдау осылайша жасалады, бірақта екінші CALL командасы бойынша стекқа басқа адрес - в адресі жазылады, сондықтан процедура осы жолы басқаруды негізгі бағдарламаның басқа жеріне - екінші CALL командасынан кейін келетін командаға.

Енді CALL және RET командаларға қатысты кейбір нақтылаулар жасайық.

ПК-да келесі болып орындалатын команда CS және ІP регистлерімен берілейтінің айтып кетейік. Егер процедура сипаттамасыз біз оған жолданатын командалар сегментінде орналасса, онда оған көшу және одан қайту жақын болуы тиіс, яғни тек ІP команда көрсеткіші ғана өзгеруі тиіс. Өйткені біз әрдайым бір командалар сегментінде қаламыз. Ал егер процедура басқа командалар сегментінде орналасса, онда оған көшу және одан қайту алыс болуы тиіс, яғни қос регистрде өзгеруі тиіс.

Осының барлығы ескеріледі және іс жүзінде ПК-да CALL және RET машиналық командалардың екі-екі варианттары бар. Егер АВ арқылы қайту адресі - CALL командасынан кейін келетін команда адресін белгілесек, онда CALL Р командасының, мұндағы Р-процедура есімі, қос вариантында былай сипаттауға болады:

жақын қайтару: стек → ІP

алыс қайтару: стек→ ІP, стек CS.

CALL және RET командалары келісімді жасалуы тиіс екені түсінікті: процедураға шақыру жақын болғанда одан қайту да жақын болуы тиіс, ал шақыру алыс болғанда қайту да алыс болуы тиіс, кері жағдайда бағдарлама дұрыс жұмыс істемейді. Сонымен қатар ЯА-да әрбір команданың қос варианттары бірдей жазылады әрине, онда ЯА-да негізгі бағдарлама мен процедура арасында көшу түрлері қалай көрсетіледі екен деген сұрақ туындайды? Жауабы мындай: ол нақты көрсетілмейді, бұл проблеманы біз үшін ассемблер шешеді. Егер біз процедураны жақын ретінде сипаттасақ онда осы процедура есімі көрсетілген барлық CALL командаларын ассемблер жақын шақыру машиналық командаларына жөнелтеді, ал барлық осы процедураның ішінде орналасқан RET командаларын ассемблер жақын қайтару машиналық командаларға жөнелтеді. Егер процедура алыс болып сипатталса, онда барлық оған жолдаулар алыс шақыру ретінде ал оның ішіндегі барлық RET командалары - алыс қайтарулар ретінде жөнелтіледі (процедуралар сыртында RET жақын қайтару ретінде қарастырылады) . Осылайша CALL және RET командалар арасындағы сәйкестікті қарауды ассемблер өзіне алады, ал біздің оған басымыз ауырмауы тиіс. Подпрограммаларды процедуралар түрінде жазудың нақты пайдасы осында, нақты осы себепті ЯА-да подпрограммаларды процедура ретінде сипаттау бекітілген.

Бірақта мұнда бір құлық бар. Ассемблер CALL командасы үшін дұрыс вариантты тек егер процедура осы командаға дейін сипатталса ғана таңдайды. Егер процедура кейін сипатталатын болса, онда ассемблер бұл процедураның түрін (жақын не алыс) білмей CALL командасын кездестіргенде оны жақын деп санап (көбінесе солай болады) әрқашан жақын шақырудың машиналық командасын жасайды. Ал егер одан кейін ассемблер берілген процедура алыс екенін біосе, қате деп табады. Мұндай қателік жібермес үшін CALL командасында PTR операторы көмегімен процедура алыс екенін нақты көрсету керек:

CALL ҒАR PTR Р

9. 2. 4. CALL командасының басқа варианттары.

Біз CALL командасының негізгі варианттары - оның операнды ретінде процедура есімі көрсетілетін жағдайды қарастырдық. Бірақта операндтың JMP шартсыз көшу командасындағыдай SHORT операторымен жағдайдан басқа, басқа да варианттары мүмкін.

Мысалдар:

NA DW P

FA DO Q

. . .

P PROC

. . .

P1: . . .

. . .

P ENDP

Q PROC FAR

. . .

Q1: . . .

. . .

Q ENDP

. . .

CALL P1; P1-ге

CALL FAR PTR Q1; Q1-ге қайтымды алыс көшу

CALL Q1; Q1-ге қайтымды жақын (!) көшу

CALL NA; P процедурасын жақын шақыру

CALL FA; Q процедурасын алыс шақыру

LEA BX, Q

CALL [BX] ; Q процедурасын жақын (!) шақыру

CALL QWORD PTR [BX] ; Q процедурасын алыс шақыру

CALL командасының бұл варианттарын қолданғанда абайлық сақтау керек. Біріншіден, қайтарымды көшу көшу түрінің RET командасы бойынша қайтару түрімен келісімділігін байқау керек, өйткені бұл жағдайларда ассемблер мұндай келісімділікке жауап бермейді. Екіншіден JMP командасындағыдай CALL командасында алға жөнелту немесе жанама жөнелтулерде егер керек болса жөнелту түрлерін нақтылау керек (үндемеушіліктен алға жөнелтуде ассемблер тура шақыруды шығарады, ал жанама жөнелтуде жақын жанама шақыруды) .

9. 3. Регистр арқылы параметр беру.

Енді процедура параметрлерімен байланысты проблемаларды қарастырайық.

Жоғары деңгейдегі тілдерде процедуралар үшін параметрлерді беру үшін оларды процедураларды шақыру операторында жазу жеткілікті. ЯА-да параметр беру проблемасы жеңіл емес, сондықтан біз оны нақтырақ қарастырамыз.

Сонымен қатар процедура нәтижесі қалай қайтарылатынын қарастырамыз. ЯА-да процедура мен функцияға формалды бөлулер жоқ, екеуінде процедуралар деп аталады. Бірақта оларға қатысты оларды функцияға және таза процедураларға бөлуге болады. олар нәтиже шығарма жақ екеніне байланысты.

Процедураларға параметрлерді әртүрлі жолдармен беруге болады. Ең қарапайым тәсіл - ол параметрлерді регистр арқылы беру: негізгі бағдарлама параметрлерді қандайда регистрлерге жазады, ал процедуралар одан кейін оны өз жұмысында регистрден алып қолданады. Осылайша егер нәтиже болса, жасауға болады: процедура өз нәтижесін бір регистрге жазады ал негізгі бағдарлама содан кейін регистрден нәтижені алады. Параметрлермен нәтижелерді қандай регистр арқылы беру ол бағдарлама авторының өз қалауы регистрлерді өзі анықтайды.

9. 3. 1. Мәндер бойынша параметрлерді беру.

Мындай мысал қарастырайық. c=max(a, b) +max(5, a-1) -ны есептеу керек, мұндағы барлық сандар таңбалы және сөз өлшемді. max(х, у) -ті есептеуді процедура-функция ретінде сипаттаймыз, сонымен қатар келесі жайлы келісейік: негізгі бағдарлама бірінші параметрді (х) АХ регистрі арқылы беру керек, екінші параметрді (у) ВХ регистрі, ал нәтижені (max) процедура АХ регистрі арқылы қайтаруы тиіс. Бұл шарттарда процедура және негізгі бағдарламаның фрагменті былай көрінеді.

; процедура: АХ=max(АХ, ВХ) ; негізгі программа

MAX PROC FAR . . .

CMP AX, BX MOV AX, A ; AX:=a

JGE MAX1 MAX BX, B ; BX:=b

MOV AX, BX CALL MAX ; AX:=max(a, b)

MAX1: RET MOV C, AX ; AX-ті құтқару

MAX ENDP MOV AX, S ; AX:=S

MOV BX, A

DEC BX ; BX:=a-1

CALL MAX ; AX:=MAX(5, a-1)

ADD C, AX ; C:=MAX(a, b) +MAX(5, a-1)

Егер Паскаль тілінің терминологиясын пайдалансақ, онда бұл мысалда параметрлер мәндер арқылы беріледі: процедураға жолданбастан бұрын негізгі процедура параметр мәндерін есептеп осы мәндерді регистрлерге жазады. Ал енді параметрлерді берудің басқа тәсілі - жөнелту арқылы тәсілін қарастырайық.

9. 3. 2. Жөнелту арқылы параметрлер беру.

Паскаль тілінде келесі процедураны алайық:

Produce D(var x:іnteger) ; begіn x:=xdіv 16 end;

Программада оларға мындай жолдау болсын: D(А) және D(В), мұндағы А және В - мәндері теріс емес сандар болып табылатын айнымалылар есімі.

Көріп отырғандарыңыздай процедура өз параметрлеріне бірдеңе атайды. Машиналық тіл терминдерінде атау зерденің қандайда бір ұяшығына жазуды білдіреді, ал ұяшыққа бірдеңе жазу үшін бұл ұяшықтың адресін (есімін) білу керек. Сондықтан процедура жазу жазуы керек ұяшықтың (А не В) адресін білу керек, ал оны негізгі бағдарлама хабардар етуге міндетті Осылайша параметрлерді жөнелту арқылы беру сәйкес параметрге ұяшық адресін (есімін) беруді білдіреді.

Адресті қалай беру керек? Регистр арқылы: негізгі бағдарлама қандайда бір регистрге айнымалының адресін жазады, ал процедура оны сол регистрден алады. Ол қандай регистр? Жалпы айтқанда кез-келген бірақта регистр-модификатор болса жақсы, яғни ВХ, ВР, SІ немесе DІ, өйткені процедураға осы регистр бойынша модификациялауға тура келеді.

Біздің D процедура үшін біз ВХ регистрін таңдайық. Онда ол оның орындалуға басталғанда ВХ регситрінде біз мазмұнын өзгертуіміз керек ұяшық адресі болатынын білдіреді. Мұндай жағдайда бұл ұяшыққа дейін (ВХ) конструкция көмегімен жетуге болады.

Айтылғанның барлығын ескере келе D(А) және D(В) -жолдауларға сәйкес келетін негізгі бағдарламаның келесі фрагментін және келесі D процедурасын аламыз: ( PUSH және POP командаларына көңіл аудармай тұра тұрыңыз)

; негізгі бағдарлама ; процедура: ВХ=адресі,

. . . x:=x dіv 16

LEA BX, A ; BX:=A адресі D PROC

CALL D ; D(A) PUSH CX ; CX-ті құтқару

LEA BX, B ; BX=B адресі MOV CL, 4

CALL D ; D(B) SHR WORD PTR [BX], CL;

. . . X:=X DІV 16

POP CX ; CX-ті қайта құру

RET

D ENDP

9. 3. 3. Процедурада регистрлерді сақтау.

Көріп отырғандарыңыздай, біздің D процедурамызға жылжыту мәнін жазатын СL регистрі керек болды. Процедураның осы регистрді өзгертуге, бұзуға құны бар ма деген сұрақ туындайды.

Бұл өте маңызды проблема. Себебі ПК-да регистрлер саны сондай көп емес және әрбір командада дерлік қандайда бір регистр қолданылады. Сондықтан негізгі бағдарлама мен процедураға үлкен ықтималдықпен жұмыс істеуге бірдей регистр қажетті болуы мүмкін және осымен олар бір-біріне кедергі жасайды, Әрине, негізгі бағдарламамен процедура өзгеше регистрлер қолданғандай келісуге болады, бірақта оны істеу қиын, себебі ПК-да регистрлер өте аз. Сондықтан көбінесе өзгеше жасайды: негізгі бағдарламағада, процедураға да бір регистрмен жұмыс істеуге рұқсат берілді, бірақта процедурадан регистрге негізгі бағдарлама жазған мәндерді еске сақтауын талап етеді. Оған жету оңай: өз жұмысының басында процедура стекта оған жұмыс кезінде керек болатын регистрлер мәндерін құтқарып, бұл регистрлерді өз қалауынша қолданып және шығардың алдында ол бұл регистрлердің мәндерін стектан оқып қайта құру керек. Дәл осылай біз D процедурасында жасадық. Шындығында, мұнда бір құлық бар: бізге а байттық регистр мәнін сақтау керек, ал біз білетініміздей стекқа тек сөз өлшемдігі ғана жазуға болады. Сондықтан стекта с регистрін емес, ал толық СХ регистрін құтқарып жұмыс соңында толық сх регитрін қайта қалпына келтіреміз.

Мұндай сақтауларды кез-келген процедурада негізгі бағдарламамен процедура регистр қолданбағаны нақты көрініп тұрса да жасалуы ұсынылады. Себебі бағдарламаның бастапқы мәтіні өзгеріп (ал ол өте жиі болады) бұл өзгерістерден кейін негізгі бағдарламаға осы регистрлер керек болып қалуы мүмкін және егер біз процедураны дұрыстап теруді еске түсірсек жақсы. Себебі көп жағдайларда бұл туралы ұмытылып кетеді және негізгі бағдарламамен процедура бір-біріне кедергі жасай бастайды. Сондықтан процедурада регистрлерді сақтауды алдын ала ойласақ негізгі бағдарламаның кез-келген өзгерісінде біз регистрлер жайлы уайымдамаймыз.

Процедура нәтижені қайтаратын регистр мәнін әрине сақтап керегі жоқ. Себебі процедураның жұмысының мәні осы регистрдің өзгерісінде жатыр.

9. 3. 4. Қиын түрдегі параметрлерді беру.

Енді параметр болып күрделі түрде берілгенде параметрді жөнелтулер бойынша беруді қарастырайық. Процедура бұл берілгенде ауыстырмаса да оған көбінесе берілгеннің өзі емес ал оның бастапқы адресі беріледі. Бұл адресті біле, процедура осы берілгеннің кез-келген жеріне жете алады келесі мысалды қарастырайық. Таңбасыз сандар массивтері болсын:

X DB 100 DUP(?)

Y DB 25 DUP (?)

және DL регистрінеосы массивтердің максимал элементтерінің қосындысын жазу керек:

DL=max(x[і] ) +max(y[і] )

Мұнда максимал элементті екі рет табу керек болғандықтан бұл әрекетті қайталамас үшін процедура түрінде сипаттаған мәнді болады. Оны MAX деп атап процедураға массивтің бастапқы адресі ВХ регистрі арқылы, массивтегі элементтер саны СХ- регистр арқылы беріледі, ал процедура өз нәтижесін AL регистрі арқылы қайтарады деген шартпен сипаттаймыз. Бұл келісімдерге процедура сипаттамасы және қойылған есепті шешетін негізгі бағдарлама фрагменті келесі көріністе болады:

; MAX процедурасы: AL:=max(w[0. . N-1] ),

мұндағы ВХ= W-ның баст. адресі, СХ=N.

MAX PROC

PUSH BX ; процедурада қолданылатын регистрлерді

; құтқару.

PUSH CX

MOV AL, 0 ; AL=0 (максимумның баст. мәні)

MAX1: CMP[BX], AL

JLE MAX2 ; W[і] >AL🡺AL:=W[і]

MOV AL, [BX]

MAX2: ІNC BX

LOOP MAX1

... жалғасы

Сіз бұл жұмысты біздің қосымшамыз арқылы толығымен тегін көре аласыз.
Ұқсас жұмыстар
Регистрлер
Параллель кодты тізбектіге түрлендіру сұлбасы
Әмбебап регистр
And және xlat командалары
ЭЕМ архитектурасы жайлы
Толық анықталмаған функцияларды минимизациялау Компьютерлік схемотехниканың тізбекті (жинақтаушы) түйіндері: регистрлер, санауыштар
Жылжымалы регистрлер
PROFIBUS, MODBUS Протоколодары
Регистрлер және есептегіштер
Тізбекті регистр
Пәндер



Реферат Курстық жұмыс Диплом Материал Диссертация Практика Презентация Сабақ жоспары Мақал-мәтелдер 1‑10 бет 11‑20 бет 21‑30 бет 31‑60 бет 61+ бет Негізгі Бет саны Қосымша Іздеу Ештеңе табылмады :( Соңғы қаралған жұмыстар Қаралған жұмыстар табылмады Тапсырыс Антиплагиат Қаралған жұмыстар kz