Багатомодульне програмування

Інформація про навчальний заклад

ВУЗ:
Національний університет Львівська політехніка
Інститут:
Не вказано
Факультет:
КН
Кафедра:
Кафедра ЕОМ

Інформація про роботу

Рік:
2014
Тип роботи:
Лабораторна робота
Предмет:
Засоби системного програмування

Частина тексту файла (без зображень, графіків і формул):

Міністерство освіти і науки України Національний університет „Львівська політехніка” Кафедра ЕОМ Лабораторна робота №7 з курсу: «Засоби системного прграмування» на тему: «Багатомодульне програмування» Варіант: №7 Вираз: X=A4/B2-C1*(D1+E2-K) K=717 МЕТА РОБОТИ: Оволодіти навиками створення багатомодульних програм. Засвоїти правила взаємодії різних модулів. ТЕОРЕТИЧНІ ВІДОМОСТІ: Багатомодульне програмування При роботі на мові Асемблер під багатомодульним програмуванням розуміють процес написання кількох процедур, підпрограм, у різних вихідних файлах з подальшим їх об’єднанням на етапі лінкування. Таке доцільно робити, коли: є необхідність компонування декількох програм написаних на різних мовах програмування (наприклад, для об’єднання потужності мов високого рівня та ефективності асемблера); програма, написана у вигляді одного модуля, може виявитись завеликою для асемблювання; окремі модулі можуть бути написані різними проектувальниками з метою подальшої інтеграції; з причини великого розміру виконавчого модуля може виникнути необхідність перекриття окремих частин програми в процесі виконання. Кожна програма асемблюється окремо і генерує власний унікальний об’єктний (OBJ) модуль. Програма  компонувальник (LINK) як правило виконання починається з основної програми, яка викликає одну або декілька підпрограм. Підпрограми, в свою чергу, можуть задіювати інші підпрограми. Виклик іншої програми зумовлює необхідність міжсегментного (довгого) виклику (CALL). Дана операція спочатку записує до стеку вміст регістру CS і заносить до цього регістру адресу іншого сегменту, потім записує до стеку значення регістру IP і заносить до цього регістру нову відносну адресу. Таким чином, в стеку запам’ятовуються і адреса кодового сегменту, і зміщення для наступного повернення з підпрограми. Наприклад, міжсегментний виклик (CALL) може складатись з такого об’єктного коду: 9A 0002 AF04 Машинний код для міжсегментного виклику CALL – 9A. При цьому команда CALL записує значення 0002 у вигляді 0200 до регістру IP, а значення 04AF – до регістру CS. Комбінація цих адрес вказує на першу виконувану команду у програмі, що викликається: Кодовий сегмент 04AF0  Зміщення в IP 0200  Дійсна адреса 04CF0   При виході з процедури, що викликалась, міжсегментна команда REТ відновлює обидві адреси в регістрах CS і IP і, таким чином, передає управління на наступну після CALL команду. Розглянемо, наприклад, основну програму MAINPROG та підпрограму, що викликається за допомогою міжсегментного виклику CALL - SUBPROG. EXTRN SUBPROG : FAR MAINPROG: . CALL SUBPROG .... PUBLIC SUBPROG SUBPROG: . .... RET Команда CALL в основній програмі повинна “знати”, що програма, яка викликається, знаходиться поза межами даного сегменту. Директива EXTRN вказує асемблеру, що посилання на SUBPROG має атрибут FAR, тобто є визначеним в іншому асемблерному модулі. Оскільки сам асемблер не має можливості точно визначити такі посилання, він генерує пустий об’єктний код для наступного його заповнення при компонуванні: 9A 0000 ---- E Підпрограма SUBPROG містить директиву PUBLIC, що вказує асемблеру і компонувальнику, що інший модуль повинен “знати” адресу SUBPROG. В результаті, після успішного асемблювання програм MAINPROG і SUBPROG в окремих об’єктних модулях, вони можуть бути скомпільовані наступним чином: D:\HOME\TASM > tasm MAINPROG /l D:\HOME\TASM > tasm SUBPROG /l D:\HOME\TASM > tlink MAINPROG + SUBPROG Компонувальник встановлює відповідності між адресами EXTRN в одному об’єктному модулі з адресами PUBLIC в іншому і заносить необхідні відносні адреси. Потім він об’єднує два об’єктних модуля в один виконавчий. В разі неможливості розв’язати посилання компонувальник видає повідомлення про помилку. Директива EXTRN має такий формат: EXTRN ім’я : тип [, … ] Можна призначити більше одного імені (до кінця рядка) або закодувати додаткові директиви EXTRN. В іншому асемблерному модулі відповідне ім’я повинно бути визначене і ідентифіковане як PUBLIC. Існують такі типи елементів: ABS, BYTE, WORD, DWORD, FAR, NEAR. Ім’я може бути визначене через EQU і повинно задовольняти реальному визначенню імені. Директива PUBLIC вказує асемблеру і компонувальнику, що адреса вказаного ідентифікатора є доступною з інших програм. Директива має такий формат: PUBLIC ідентифікатор [, … ] Можна призначити більше одного ідентифікатора (до кінця рядка) або закодувати додаткові директиви PUBLIC. Ідентифікатори можуть бути мітками (включаючи PROC-мітки), змінними або числами. Неправильними ідентифікаторами є імена регістрів та EQU-ідентифікатори, що призначають більш як двобайтні значення. Існує декілька способів компонування програм. Кожен з них характеризується одною або декількома такими рисами: директиви EXTRN і PUBLIC в якості міток; спільний кодовий сегмент - шляхом використання директиви PUBLIC в заголовку кодового сегменту кожної з програм, що компонуються; спільні дані. Використання директив EXTRN і PUBLIC в якості міток Програма, приведена нижче, складається з основної програми MAINPROG та підпрограми SUBMUL. Директива EXTRN в основній програмі визначає SUBMUL як точку входу в підпрограму. Підпрограма містить директиву PUBLIC, яка вказує компонувальнику на те, що точкою входу для виконання є мітка SUBMUL. Підпрограма перемножує вміст регістру AX (значення з поля даних PRICE) на вміст регістру BX (значення з поля даних QTY), при цьому результат операції буде розміщено в регістровій парі DX:AX (в даному випадку – 002E 4000). В підпрограмі відсутній сегмент даних, оскільки вона не визначає ніяких даних. *Примітка: Для успішного компонування компонувальник потребує знайти хоча б один стековий сегмент. В підпрограмі не визначено стекового сегменту, оскільки вона використовує ті ж самі стекові адреси, що й основна програма. Таким чином, стек, що визначається в основній програмі, є доступним і в підпрограмі. TITLE CALLMULL ;Головна програма EXTRN SUBMUL:FAR STACKSG SEGMENT PARA STACK 'Stack' DW 64 DUP(?) STACKSG ENDS DATASG SEGMENT PARA 'Data' QTY DW 0140H PRICE DW 2500H DATASG ENDS CODESG SEGMENT PARA 'Code' BEGIN PROC FAR ASSUME CS:CODESG,DS:DATASG,SS:STACKSG PUSH DS SUB AX,AX PUSH AX MOV AX,DATASG MOV DS,AX MOV AX,PRICE ;Занести вартість MOV BX,QTY ; і кількість CALL SUBMUL ;Викликати підпрограму RET BEGIN ENDP CODESG ENDS END BEGIN ТITLE SUBMUL ;Підпрограма множення CODESG SEGMENT PARA 'Code' SUBMUL PROC FAR ASSUME CS:CODESG PUBLIC SUBMUL MUL BX ;AX-вартість, BX-кількість RET ;Добуток в DX:AX SUBMUL ENDP CODESG ENDS END Використання спільного кодового сегменту В основній програмі та в усіх підпрограмах, що компонуються разом, необхідно використати атрибут PUBLIC в директиві SEGMENT: CODESG SEGMENT PARA PUBLIC 'CODE' В даному випадку з таблиці ідентифікаторів слідує, що узагальнений тип кодового сегменту – PUBLIC. Необхідно зауважити, що карта компонування вказує на наявність в програмі лише одного кодового сегменту - внаслідок того, що заголовки кодових сегментів основної програми та підпрограми співпадають, компонувальник об’єднує їх в один фізичний кодовий сегмент. Використання спільних даних Наявність спільних даних уможливлює обробку в одному асемблерному модулі даних, що є визначеними в іншому асемблерному модулі. Для того, щоби змінні PRICE та QTY визначались в основній програмі, але завантаження значень з цих областей пам’яті в регістри BX та AX виконувалась в підпрограмі, необхідно виконати такі зміни в програмах з попереднього пункту: в основній програмі ідентифікатори PRICE та QTY визначені як PUBLIC. Сегмент даних так само визначений як PUBLIC; в підпрограмі ідентифікатори PRICE та QTY визначені як EXTRN та WORD. Таке визначення вказує асемблеру на довжину цих полів в 2 байт. *Примітка: Основна програма та підпрограма можуть визначати будь-які інші елементи даних, але спільними елементами будуть лише ті, що мають атрибути PUBLIC та EXTRN. При компонуванні двох і більше асемблерних модулів необхідно визначити стек достатньо великого розміру – на практиці для великих програм визначення розміру в 64 слова є достатнім. TITLE CALLMULL ;Головна програма EXTRN SUBMUL:FAR PUBLIC QTY,PRICE STACKSG SEGMENT PARA STACK 'Stack' DW 64 DUP(?) STACKSG ENDS DATASG SEGMENT PARA PUBLIC 'Data' QTY DW 0140H PRICE DW 2500H DATASG ENDS CODESG SEGMENT PARA PUBLIC 'Code' BEGIN PROC FAR ASSUME CS:CODESG,DS:DATASG,SS:STACKSG PUSH DS SUB AX,AX PUSH AX MOV AX,DATASG MOV DS,AX CALL SUBMUL ;Викликати підпрограму RET BEGIN ENDP CODESG ENDS END BEGIN ТITLE SUBMUL ;Підпрограма множення CODESG SEGMENT PARA PUBLIC 'CODE' SUBMUL PROC FAR ASSUME CS:CODESG PUBLIC SUBMUL MOV AX,PRICE MOV BX,QTY MUL BX RET SUBMUL ENDP CODESG ENDS END SUBMUL Передача параметрів через стек Даний спосіб взаємодії програм характеризується тим, що програма, що викликає іншу, передає їй параметри шляхом запису даних до стеку. Кожна команда PUSH при цьому повинна записувати до стеку дані розміром в одне слово з пам’яті або з регістру. Програма, приведена далі, перш ніж викликати підпрограму SUBMUL заносить у стек значення з полів PRICE і QTY. Після команди CALL стек виглядає в так: ... │ 1600 │ D213 │ 4001 │ 0025 │ 0000 │ C213 │ 6 5 4 3 2 1 Ініціалізуюча команда PUSH DS заносить адресу сегменту даних у стек. Ця адреса може відрізнятися в різних версіях DOS. Команда PUSH AX заносить у стек нуль. Команда PUSH PRICE заносить у стек слово даних (2500). Команда PUSH QTY заносить у стек друге слово даних (0140). Команда CALL заносить у стек вміст регістра CS (D213) Оскільки що команда CALL представляє тут міжсегментний виклик, то в стек заноситься також вміст регістра IP(1600). Програма, що викликається використовує регістр BP для доступу до параметрів у стеку, але вона, також, запам'ятовує вміст регістра BP, записуючи його в стек. У даному випадку, припустимо, що регістр BP містить нуль, тоді цей нуль (два байти) буде записано у вершині стеку (ліворуч). Потім програма поміщає в регістр BP вміст із регістра SP, оскільки у якості індексного регістра може використовуватися регістр BP, але не SP. Команда завантажує в регістр BP значення 0072. Спочатку регістр SP містив розмір порожнього стека, тобто комірки 80. Запис кожного слова в стек зменшує вміст SP на 2: │ BP │ IP │ CS │ QTY │ PRICE│ AX │ DS │ │ 0000 │ 1600 │ D213 │ 4001 │ 0025 │ 0000 │C213 │ │ │ │ │ │ │ │ SP: 72 74 76 78 7A 7C 7E Оскільки BP тепер також містить 0072, то параметр ціни (PRICE) буде за адресою BP+8, а параметр кількості (QTY) - за адресою BP+6. Програма пересилає ці величини зі стеку в регістри AX і BX відповідно, і виконує множення. Перед поверненням у вихідну програму в регістрі BP відновлюється початкове значення, а вміст у регістрі SP збільшується на 2, з 72 до 74. Остання команда RET являє собою міжсегментне повернення (“довгий” перехід) у вихідну програму. По цій команді виконуються наступні дії: З вершини стека відновлюється значення регістра IP (1600). Вміст регістра SP збільшується на 2, від 74 до 76. З нової вершини стеку відновлюється значення регістра CS (D213). Вміст регістра SP збільшується на 2 від 76 до 78. У такий спосіб здійснюється коректне повернення у викликаючу програму. Залишилося одне невелике пояснення. Команда RET закодована як RET 4. Параметр 4 являє собою кількість байт у стеку, використаних при передачі параметрів (два слова в даному випадку). Команда RET додасть цей параметр до вмісту регістра SP, одержавши значення 7C. Таким чином, зі стеку вилучаються непотрібні більше параметри. Будьте особливо уважні при відновленні регістра SP - помилки можуть привести до непередбачуваного результату. TITLE CALLMULL ;Головна програма EXTRN SUBMUL:FAR STACKSG SEGMENT PARA STACK 'Stack' DW 64 DUP(?) STACKSG ENDS DATASG SEGMENT PARA 'Data' QTY DW 0140H PRICE DW 2500H DATASG ENDS CODESG SEGMENT PARA PUBLIC 'Code' BEGIN PROC FAR ASSUME CS:CODESG,DS:DATASG,SS:STACKSG PUSH DS SUB AX,AX PUSH AX MOV AX,DATASG MOV DS,AX PUSH PRICE PUSH QTY CALL SUBMUL ;Викликати підпрограму RET BEGIN ENDP CODESG ENDS END BEGIN ЗАВДАННЯ: Створити *.exe програму, яка реалізовує обчислення, заданого варіантом виразу. Програма повинна складатися з чотирьох модулів: головний модуль – містить спільний сегмент стеку, необхідні дані та виклик основних процедур; модуль вводу - забезпечує ввід даних з клавіатури в десятковій формі; модуль безпосередніх обчислень – здійснює всі необхідні арифметичні дії. модуль виводу – забезпечує вивід на екран результату в десятковій формі. Всі модулі повинні бути в різних файлах і об’єднані на етапі лінкування. Передача параметрів може здійснюватися довільним чином. Переконатися у правильності роботи кожного модуля зокрема та програми загалом. Скласти звіт про виконану роботу з приведенням тексту програми та коментарів до неї. Дати відповідь на контрольні запитання. КОД ПРОГРАМИ: ; main.asm головна програма DOSSEG EXTRN Input :FAR, Calculation :FAR, Output :FAR PUBLIC erFlag STACKSG SEGMENT PARA STACK 'Stack' DW 127 DUP(0) STACKSG ENDS DATASG SEGMENT PARA PUBLIC 'Data' erFlag DB 0 DATASG ENDS CODESG SEGMENT PARA PUBLIC 'Code' main: ASSUME CS:CODESG,DS:DATASG,SS:STACKSG MOV AX,DATASG MOV DS,AX CALL Input cmp erFlag,0 jne A30 CALL Calculation cmp erFlag,0 jne A30 CALL Output cmp erFlag,0 jne A30 A30: mov ah,4Ch int 21h CODESG ENDS END main ;Input.asm модуль вводу даних DOSSEG EXTRN erFlag:BYTE PUBLIC A,B,C,D,E,FlagSign ;-------------------------------------------------------------------- MY_MUL MACRO X,Y,Z mov z,0 mov z+2,0 MOV AX,X MUL Y MOV Z,AX MOV Z+2,DX MOV AX,X+2 MUL Y ADD Z+2,AX mov ax,Z mov dx,Z+2 ENDM ;==================================================================== DATASG SEGMENT PARA PUBLIC 'Data' ;-------------------------------------------------------------------- A dd 00h B dw 00h C db 00h D db 00h E dw 00h FlagSign db 00h ;-------------------------------------------------------------------- TempStr db 10 dup (0) TempBin dw 0,0 MaxLen dw 0 Mult10 dw 1,0 my_z dw 0,0 ;-------------------------------------------------------------------- MESSG_X DB 13,10,'X=A4/B2-C1*(D1+E2-K) K=717D (02CDh)','$' MESSG_A DB 13,10,'A= ','$' MESSG_B DB 13,10,'B= ','$' MESSG_C DB 13,10,'C= ','$' MESSG_D DB 13,10,'D= ','$' MESSG_E DB 13,10,'E= ','$' MESSG_X1 DB 13,10,'X= ','$' ;-------------------------------------------------------------------- erStr1 db 13,10,'Data not input_variable',13,10,'$' erStr2 db 13,10,'Incorrectly data ',13,10,'$' erStr2_1 db 13,10,' B =0 --> divide by zero ',13,10,'$' erStr3 db 13,10,'Data is too long ',13,10,'$' ;-------------------------------------------------------------------- DATASG ENDS CODESG SEGMENT PARA PUBLIC 'CODE' ASSUME DS:DATASG, CS:CODESG ;==================================================================== input proc FAR public Input LEA DX,MESSG_X MOV AH,09 INT 21H ;-------------------------------------------------------------------- LEA DX,MESSG_A MOV AH,09 INT 21H mov di,offset A mov MaxLen,10 mov cx,MaxLen call input_variable ;-------------------------------------------------------------------- LEA DX,MESSG_B MOV AH,09 INT 21H mov di,offset B mov MaxLen,5 mov cx,MaxLen call input_variable ;-------------------------------------------------------------------- cmp B,0 jne dali mov ah,09 mov dx, offset erStr2_1 int 21h mov ah,4Ch int 21h ;-------------------------------------------------------------------- dali: LEA DX,MESSG_C MOV AH,09 INT 21H mov di,offset C mov MaxLen,3 mov cx,MaxLen call input_variable ;-------------------------------------------------------------------- LEA DX,MESSG_D MOV AH,09 INT 21H mov di,offset D mov MaxLen,3 mov cx,MaxLen call input_variable ;-------------------------------------------------------------------- LEA DX,MESSG_E MOV AH,09 INT 21H mov di,offset E mov MaxLen,5 mov cx,MaxLen call input_variable ;-------------------------------------------------------------------- ret input endp ;==================================================================== input_variable PROC mov si,0 In_00: mov ah,01 int 21h cmp al,0Dh je In_1 cmp al,'-' jne In_0 mov FlagSign,1 jmp In_00 ;-------------------------------------------------------------------- In_0: mov dl,al call CHECK_BYTE mov TempStr[si],dl inc si loop In_00 ;-------------------------------------------------------------------- In_1: push si dec si cmp cx,MaxLen jne In_2 LEA DX,erSTR1 MOV AH,09 INT 21H mov erFlag,1 jmp In_5 ;-------------------------------------------------------------------- In_2: mov bh,0 mov bl,TempStr[si] MY_MUL Mult10,bx,my_z add TempBin,ax adc TempBin+2,dx mov bh,0 mov bl,10 MY_MUL Mult10,bx,my_z mov Mult10,ax mov Mult10+2,dx dec si cmp si,0 jge In_2 mov ax,TempBin mov dx,TempBin+2 pop si cmp si,MaxLen jl In_3 cmp MaxLen,10 jl In_2_1 js In_Err cmp dx,0FFFFh ja In_Err jmp In_3 ;-------------------------------------------------------------------- In_2_1: cmp MaxLen,5 jl In_2_2 cmp dx,00 ja In_Err cmp ah,0FFh ja In_Err jmp In_3 ;-------------------------------------------------------------------- In_2_2: cmp ax,00FFh jbe In_3 ;-------------------------------------------------------------------- In_Err: LEA DX,erSTR3 MOV AH,09 INT 21H mov erFlag,1 jmp In_5 ;-------------------------------------------------------------------- In_3: cmp FlagSign,1 jne In_4 mov bx,0 sub bx,ax mov ax,bx mov bx,0 sbb bx,dx mov dx,bx ;-------------------------------------------------------------------- In_4: mov [di],ax mov [di+2],dx mov TempBin,0 mov TempBin+2,0 mov Mult10,1 mov Mult10+2,0 mov FlagSign,0 ;-------------------------------------------------------------------- In_5: RET input_variable ENDP ;==================================================================== CHECK_BYTE PROC sub dl,30h cmp dl,00 jl ErS cmp dl,0Ah jl GO ErS: LEA DX,erSTR2 MOV AH,09 INT 21H GO: RET CHECK_BYTE ENDP ;==================================================================== CODESG ENDS END ; calc.asm модуль обчислень DOSSEG EXTRN A:DWORD,B:WORD,C:BYTE,D:BYTE,E:WORD PUBLIC X;,MESSG_Sign DATASG SEGMENT PARA PUBLIC 'Data' K EQU 2CDh Temp1 dd 00h,00h ;chastka_AB Temp2 dw 00h ;suma_DE Temp3 dd 00h ;riznitza_SumiDE&K Temp4 dd 00h ;riznitza_SumiDE&K X dw 00h,00h ;riznitza_Kinzeve DATASG ENDS ;==================================================================== CODESG SEGMENT PARA PUBLIC 'CODE' ASSUME DS:DATASG, CS:CODESG MOV AX,DATASG MOV DS,AX ;==================================================================== calculation proc public calculation xor ax,ax xor bx,bx xor cx,cx xor dx,dx ;-------------------------------------------------------------------- mov ax,word ptr A mov dx,word ptr [A+2] mov bx,B div bx mov Temp2,ax ;A4/B2 (4/2=2) ;-------------------------------------------------------------------- mov ax,word ptr D mov dx,E add ax,dx mov word ptr Temp1,ax ;D1+E2 (2+2=4) mov ax,0 adc ax,0 ;ax=ax+0+C mov word ptr [Temp1+2],ax ;-------------------------------------------------------------------- mov ax,word ptr Temp1 mov dx,K sub ax,dx mov word ptr Temp3,ax ;(D1+E2-K) (4-4=4) mov ax,word ptr [Temp1+2] mov dx,0 sbb ax,dx mov word ptr [Temp3+2],ax mov ax,0 sbb ax,0 ;ax=ax-0-C mov word ptr [Temp3+4],ax ;-------------------------------------------------------------------- xor dx,dx mov ax,word ptr Temp3 mul C mov word ptr Temp4,ax mov word ptr [Temp4+2],dx mov ax,word ptr [Temp3+2] mul C add ax,word ptr [Temp4+2] mov word ptr [Temp4+2],ax adc dx,0 mov word ptr [Temp4+4],dx ;C1*(D1+E2-K) (4*1=6) ;-------------------------------------------------------------------- clc mov ax,Temp2 mov dx,word ptr Temp4 sub ax,dx mov word ptr X,ax ;A4/B2-C1*(D1+E2-K) mov ax,0 mov dx,word ptr [Temp4+2] sbb ax,dx mov word ptr [X+2],ax mov ax,0 mov dx,word ptr [Temp4+4] sbb ax,dx mov word ptr [X+4],ax mov ax,0 sbb ax,0 mov word ptr [X+8],ax ;-------------------------------------------------------------------- ret calculation endp ;==================================================================== CODESG ENDS END ; Output.asm модуль виводу результату DOSSEG EXTRN X:DWORD;, MESSG_Sign :BYTE ;==================================================================== DATASG SEGMENT PARA PUBLIC 'Data' X_Str db 10 dup (0) MESSG_X1 DB 13,10,'X= ','$' X_div2 dw 0,0 Y_div2 dw 0 DATASG ENDS ;==================================================================== CODESG SEGMENT PARA PUBLIC 'CODE' ASSUME DS:DATASG, CS:CODESG MOV AX,DATASG MOV DS,AX ;==================================================================== output PROC FAR Public output mov di,0 mov Y_div2,10 mov cx,word ptr X mov bx,word ptr X+2 ;-------------------------------------------------------------------- O_1: mov X_div2,cx mov X_div2+2,bx call my_div2 add dl,30h mov X_Str[di],dl inc di cmp bx,0 ja O_1 cmp cx,10 jae O_1 add cl,30h mov X_Str[di],cl mov dx,offset MESSG_X1 mov ah,09 int 21h ;-------------------------------------------------------------------- O_2: mov dl,X_Str[di] mov ah,02h int 21h dec di jge O_2 ret output ENDP ;==================================================================== MY_DIV2 proc sub cx,cx sub bx,bx mov dx,X_div2+2 mov ax,X_div2 M2_D1: cmp dx,Y_div2 jb M2_D3 sub ax,Y_div2 sbb dx,00 add cx,01 adc bx,0 jmp M2_D1 M2_D3: div Y_div2 add cx,ax adc bx,00 ret MY_DIV2 ENDP ;==================================================================== CODESG ENDS END СКРІНШОТ ВИКОНАННЯ ПРОГРАМИ: / Рис. 1. Результатом виконання приведеної програми: вивід ВИСНОВОК: Під час виконання даної лабораторної роботи я оволодів навиками створення багатомодульних програм та засвоїтв правила взаємодії різних модулів.
Антиботан аватар за замовчуванням

29.05.2014 21:05-

Коментарі

Ви не можете залишити коментар. Для цього, будь ласка, увійдіть або зареєструйтесь.

Ділись своїми роботами та отримуй миттєві бонуси!

Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!
Нічого не вибрано
0%

Оголошення від адміністратора

Антиботан аватар за замовчуванням

Подякувати Студентському архіву довільною сумою

Admin

26.02.2023 12:38

Дякуємо, що користуєтесь нашим архівом!