Системне програмування та операційні системи

Зміст:

1. Робота в операційній  системі Linux. Програмування в оболонці shell.

2. Операційна система  Windows. Системне програмування в MASM.

3. Операційна система  Windows. Системне програмування в MASM32 з використанням функцій API.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


Робота в операційній  системі Linux. Програмування в оболонці shell.

Найпростіші засоби SHELL

Командний мова shell (у перекладі - раковина, шкаралупа) фактично є мовою програмування дуже високого рівня. На цій мові користувач здійснює управління комп'ютером. Зазвичай, після входу в систему ви починаєте взаємодіяти з командною оболонкою. Ознакою того, що оболонка (shell) готова до прийому команд служить видається нею на екран промптер. У найпростішому випадку це один долар ("$").

shell - це одна з багатьох  команд UNIX. Тобто в набір команд  оболонки "shell" входить команда  "sh" - виклик інтерпретатора "shell". Перший "shell" викликається автоматично  при вашому вході в систему  і видає на екран промтері. Після цього ви можете викликати  на виконання будь-які команди,  в тому числі і знову сам  "shell", який вам створить нову  оболонку всередині колишньої. 
    Так наприклад, якщо ви підготуєте в редакторі файл "file_1": 
echo Hello! 
то це буде звичайний текстовий файл, що містить команду "echo", яка при виконанні видає все написане правіше від неї на екран.

    Оскільки UNIX - система  розрахована на багато користувачів, ви можете навіть на персональному  комп'ютері працювати паралельно, скажімо, на 12-ти екранах), маючи  на кожному екрані нового (або  одного і того ж) користувача  зі своєю командною оболонкою.  Можете і в графічному режимі X-Window також відкрити велике число  вікон, а в кожному вікні  може бути свій користувач  зі своєю командною оболонкою. 
   Стрижневим елементом мови shell є команда.

 

Структура команд

Команди в shell зазвичай мають  наступний формат: 
<Ім'я команди> <прапори> <аргумент (и)> 
Наприклад: 
ls-ls / usr / bin 
Де ls - ім'я команди видачі вмісту директорія, 
-Ls - прапори ("-" - ознака прапорів, l - довгий формат, s - об'ем файлів в блоках), 
/ Usr / bin - директорій, для якого виконується команда. 
Ця команда видасть на екран у довгому форматі вміст директорії / usr / bin, при цьому додасть інформацію про розмір кожного файлу в блоках. 
На жаль, така структура команди витримується далеко не завжди. Не завжди перед прапорами ставиться мінус, не завжди прапори йдуть одним словом. Є різноманітність і в поданні аргументів. До числа команд, які мають екзотичні формати, відносяться і такі "ходові" команди, як сс - виклик компілятора мови С, tar - робота з архівами, dd - копіювання файлу з перетворенням, find - пошук файлів і ряд інших. 
Як правило, перше слово shell сприймає, як команду. Тому в командному рядку 
cat cat 
перше слово буде розшифровано shell, як команда (конкатенації), яка видасть на екран файл з ім'ям "cat" (друге слово), що знаходиться в поточному директорії.

Shell-змінні

Ім'я shell-змінної - послідовність, що розпочинається з букви, та вміщує цифри, знак підкреслювання.

Значення shell-змінної - рядок символів.

У shell всього два типи даних: рядок  символів та текстовий файл.

Ім'я  змінної аналогічно традиційному представленню  про ідентифікатор, тобто ім'ям може бути послідовність букв, цифр та підкреслювань, розпочинається з букви або підкреслення.

Для присвоювання значення змінним може використовуватися оператор присвоювання "=".

         var_1=13

var_2="OS Unix"

Змінна  та її значення повинні бути записані без пробілів відносно символа "=".

Можливі й інші способи присвоювання значення shell-змінним. Так, наприклад: DAT=`date` приводить до того, що спочатку виконується команда "date" а результат її виконання, замість видачі на стандартний вихід, прописується у якості значення змінної, у даному випадку "DAT".

Можна надати значення змінної за допомогою  команди "read", яка забезпечує прийом значення з клавіатури: read x.

Одна  команда "read" може прочитати значення відразу для декількох змінних, по черзі. Якщо змінних більше, чим  їх введено, то тим що залишилися змінним  присвоюється порожній рядок, якщо введено  більше, то зайві значення ігноруються.

Під час звернення до shell-змінної необхідно  перед ім'ям ставити символ "\$", так відповідно команда echo $var_2; виведе на екран "OS Unix".

 Екранування

Як  засоби екранування використовуються подвійні лапки (""), одинарні лапки (' ') та бек-слеш (\).

Можна в одному рядку записувати декілька присвоювань.

            x=22 y=33 z=$x

            A="$x" B='$x' C=\$x

            D="$x + $y + $z"  E='$x + $y + $z'  F=$x\ +\ $y\ +\ $z

Тоді 

            echo A = $A   B = $B   C = $C

            echo D = $D   E = $E   F = $F

            eval echo evaluated A = $A

            eval echo evaluated B = $B

            eval echo evaluated C = $C

виведуть на екран 

            A = 22 B = $x C = $x

            D = 22 + 33 + 22 E = $x + $y + $z F = 22 + 33 + 22

            evaluated A = 22

            evaluated B = 22

            evaluated C = 22

"eval" - команда, що  виконує означення змінних в  рядку, що є аргументом.

Бек-слеш не тільки екранує наступний за ним  символ, що дозволяє використовувати  спеціальні символи просто як символи, що представляють самих себе, він  може екранувати сам себе. Цей символ також може створювати ефект продовження  рядка. Ефект продовження командного рядка забезпечує також символ конвеєра - "|".

Програмні структури

Як і в будь-якій мові програмування  у тексті мовою shell можуть бути коментарі. Для цього використовується символ "#". Усе, що знаходиться в рядку  лівіше від даного символу, сприймається інтерпретатором як коментар.

Як і в будь-якій процедурній  мові програмування, в мові shell є  оператори. Ряд операторів дозволяє керувати послідовністю виконання  команд. У таких операторах часто  необхідна перевірка умови, яка  визначає напрямок продовження обчислень.

Умовний оператор ("IF").

У загальному випадку оператор "if" має структуру:

            if умова

                then список

                    [elif умова

                        then список]

                [else список]

            fi

Оператор вибору ("CASE").

Оператор вибору "case" має структуру:

 

            case рядок in

                шаблон) список команд;;

                шаблон) список команд;;

                    ...

            esac

"Рядок" (це може бути  і один символ), що порівнюється  із шаблоном. Потім "список  команд" вибраного рядка.

Приклад:

            echo -n " А какую оценку получил  на экзамене?: "

            read z

            case $z in

                5) echo Молодец !            ;;

                4) echo Все равно молодец !  ;;

                3) echo Все равно !          ;;

                2) echo Все !                ;;

                *) echo  !                   ;;

            esac

Оператор циклу із перерахуванням ("FOR").

Оператор циклу "for" має структуру:

            for ім'я [in список значень]

                do

                    список команд

                done

де "for" - це службове слово, що визначає тип циклу, "do" та "done" - це службові слова, що виділяють тіло циклу. Фрагмент "in список значень" може бути відсутнім.

Оператор циклу з істиною  умовою ("WHILE").

Оператор циклу "'while' має структуру:

            while умова

                do

                    список команд

                done

де "while" - службове слово, що визначає тип циклу з істиною  умовою. Список команд у тілі циклу  повторюється до тих пір, доки зберігається істинність умови (доки умови не дорівнює 0) або цикл буде перерваний командами "break", "continue" або "exit".

Оператор циклу з хибною умовою ("UNTIL").

Оператор циклу "until" має структуру:

            until умова

                do

                    список команд

                done

де "until" - службове слово, що визначає тип циклу з хибною умовою. Список команд в тілі циклу  повторюється стільки разів, скільки  буде зберігатися хибність умови  або цикл не буде перерваним спеціальними командами.

Відмінність від "while" полягає  в тому, що умова циклу перевіряється  на хибність, перевіряється після  кожного виконання тіла циклу.

Пустий оператор.

Пустий оператор має формат:

Нічого не робить. Повертає значення "0". Наприклад, в конструкції "while :" або ставить у початок  командного файлу, щоб гарантувати, що файл не буде прийнятий за виконавчий для "csh".

 

 

 

 

 

 

 

 

 

 

 

 

 

Завдання №1:

27. Дан текст, каждый символ которого может быть малой буквой, большой буквой, цифрой или одним из знаков “+”, “-”, “*”. Группой букв будем называть такую совокупность последовательно расположенных букв, которой непосредственно не предшествует и за которой непосредственно не следует буква. Аналогично определим группу цифр и группу знаков. Найти все такие группы букв, в которые буква “а” входит не менее 2-х раз.

Код програми:

#!/bin/bash  

#1 #вивід інформації про  виконавця роботи та ввід вхідних  даних

gdialog --title "Виконав" --msgbox "Башинський Олег БІТ-3-09"

gdialog --title "Вхідні дані" --inputbox  "Введіть текст" 10 50 2> lab6text.txt

 

#ввід вхідних даних

if [ $? -ne 1 ];

#Рядок опрацьовується  якщо ввід підтверджено («Ок»)

then

 

ptext=$(cat lab6text.txt)

#вхідний рядок

text=$ptext;

#його копія 

n=${#ptext};

#кількість символів  

i=0;  

j=0;  

m=0;

#2  

while [ $i -le $n ];

#цикл по символах строки

do   

k=${ptext:$i:1}

#вибір  і-го символу  в строці  

case $k in

#перевірка чи належить  символ до літер, і формування  груп літер

1|2|2|3|4|5|6|7|8|9|0) grup=' '; m=$(($m+1));;

#якщо не літера, очищаємо  буфер групи літер

"*"|"-"|"+") grup=' '; m=$(($m+1));;

?) grup=$grup$k; #якщо  літера, добавляємо  до буфера групи літер

    ns[$m]=$grup; #зберігаємо  в масив

                               

esac

 

i=$(($i+1)) #переходимо до  наступного символу строки

   done

 

#3  

for p in ${ns[*]}; #цикл по групах  літер

do

j=0;

i=0;

 

ind='no';#індекатор присутності  в групі "аа"

     n=$((${#p} - 1));

#кількість символів групи   

while [ $i -lt $n ];#цикл по символах  групи

do

j=$(($i+1));

if  [ ${p:$i:1} = 'a' ] && [ ${p:$j:1} = 'a' ] && [ $ind = 'no' ]

#перевірка чи є в  групі "аа"

then

GrupAA=$GrupAA"  "$p #якщо  так, добавляємо до вихідних  даних

 

ind='yes'

#"аа" присутні  

    fi

i=$(($i+1));

#переходио до наст. групи

done

ind='no' #в наст. груні ще  невідомо чи є "аа"

    done

 

#4 Виведення вхідного  та зміненого тексту та набору  спец. символів. Кінець алгоритму.

 

gdialog --title "Вихідні дані" --msgbox "Вхідний текст:$text\nВихідні  дані:$GrupAA"

fi

gdialog --clear

#Кінець програми.

exit 0

 

 

Операційна система  Windows. Системне програмування в MASM.

Регістри

Крім комірок оперативної  пам'яті для короткочасного збереження даних використовуються регістри - комірки, що входять до складу процесора. Доступ до регістрів здійснюється значно швидше, ніж до комірок пам'яті, тому використання регістрів помітно зменшує час виконання програм. Крім того, у деяких випадках без регістрів узагалі неможливо обійтися.

Усі регістри мають розмір слова (16 бітів), за кожним з них закріплена визначена назва. За призначеням та способом використання регістри можна розбити на наступні групи:

  • регістри загального призначення (AX, BX, CX, DX, BP, SI, DI, SP);
  • сегментні регістри (CS, DS, SS, ES);
  • лічильник команд (IP);
  • регістр флагів (Flags).

Тлумачення цих назв:

  • A accumulator, акумулятор;
  • B base, база;
  • C counter, лічильник;
  • D data, дані;
  • BP base pointer, покажчик бази;
  • SI source index, індекс джерела;
  • DI destination index, індекс приймача;
  • SP stack pointer, покажчик стеку;
  • CS code segment, сегмент команд;
  • DS data segment, сегмент даних;
  • SS stack segment, сегмент стеку;
  • ES extra segment, додатковий сегмент;
  • IP instruction pointer, лічильник команд.

Регістри загального призначення  можна використовувати у всіх арифметичних і логічних командах. У той же час кожен з них має визначену спеціалізацію, тобто для деяких команд необхідні тільки визначені регістри. Наприклад, команди множення і ділення вимагають, щоб один з операндів знаходився в регістрі AX чи в регістрах AX і DX (у залежності від розміру операнду), а команди керування циклом використовують регістр CX як лічильник циклу. Регістри BX і BP зазвичай використовуються як базові регістри, а SI і DI - як індексні. Регістр SP як правило вказує на вершину стеку, апаратно підтримуваного ПК.

Регістри AX, BX, CX і DX конструктивно  влаштовані так, що можна отримувати доступ до їх старшої і молодшої половин; можна сказати, що кожний з  цих регістрів складається з двох регістрів, розмір яких один байт і що позначаються через AH, AL, BH, BL, CH, CL, DH, DL відповідно (H - high, старша; L - low, молодша). Таким чином, з кожним з цих регістрів можна працювати як з єдиним цілим, так і з його частинами. Наприклад, можна записати слово в AX, а потім зчитати тільки частину слова з регістра AH чи замінити тільки частину в регістрі AL і т.д. Така структура регістрів дозволяє використовувати їх для роботи і з числами так і із символами.

Всі інші регістри не діляться на частині, тому зчитувати чи записувати їхній зміст (16 бітів) можна тільки повністю.

Сегментні регістри CS, DS, SS і ES не можуть бути операндами ніяких команд, окрім стекових команд і команд пересилання. Ці регістри використовуються тільки для сегментування адрес.

Лічильник команд IP завжди містить  адресу (зсув від початку програми) тієї команди, що повинна бути виконана наступною (початок програми зберігається в регістрі CS). Зміст регістра IP можна змінити тільки командами переходу.

Флаги

Процесор має спеціальний  регістр флагів. Флаг - це біт, що приймає значення "1", якщо деяку умову було виконано, і значення "0" у іншому випадку. Використовуються 9 флагів, кожному з них привласнена визначена назва. Усі вони зібрані в регістрі флагів, тобто кожен флаг - це один з розрядів регістра. Структура регістра флагів:

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

x

x

x

x

OF

DF

IF

TF

SF

ZF

х

AF

x

PF

x

CF


 

Умовно флаги розділяються на флаги умов і флаги станів. Флаги умов автоматично змінюються при виконанні команд і фіксують ті чи інші властивості їх результату, наприклад, було чи ні переповнення або результат рівний нулю. Флаги станів встановлюються програмою і визначають подальшу роботу процесора, наприклад, блокують переривання.

До флагів умов відносять:

  • CF (carry flag) - флаг переносу. Приймає значення 1, якщо операція призвела до перенесення зі старшого біта результату. Старшим є 7-й, 15-й, 31-й біти в залежності від розмірності операнда. Це відбувається, наприклад, якщо при додаванні цілих чисел результат вийшов за межі розрядної сітки, чи якщо при відніманні чисел без знаку перше з них було менше за друге. У командах зрушення в CF заноситься біт, що вийшов за розрядну сітку;
  • OF (overflow flag) - флаг переповнення. Встановлюється в 1, якщо в результаті операції було виконано перенос у старший, знаковий біт (7-й, 15-й, чи 31-й). Встановлюється в 1, якщо відбувається позика з цих розрядів. Ця ознака необхідна для роботи з числами зі знаком;
  • ZF (zero flag) - флаг нуля. Дорівнює 1, якщо результат операції виявився рівним 0;
  • SF (sign flag) - флаг знаку. Встановлюється в 1, якщо в операції над знаковими числами було отримано від’ємний результат;
  • PF (parity flag) – флаг парності. Дорівнює 1, якщо результат чергової команди містить парну кількість двійкових одиниць. Враховується звичайно при операціях вводу-виводу;
  • AF (auxiliary carry flag) - флаг додаткового переносу. Фіксує особливості виконання операцій над двійково-десятковими числами.

До флагів станів відносять:

  • DF (direction flag) - флаг напрямку. Встановлює напрямок перегляду рядків у строкових командах: при DF=0 рядки проглядаються від початку до кінця, при DF=1 - у зворотному напрямку;
  • IF (interrupt flag) - флаг переривань. При IF=0 процесор перестає реагувати на переривання, що надходять до нього, при IF=1 блокування переривань знімається;
  • TF (trap flag) - флаг трасування. При TF=1 після виконання кожної команди процесор робить переривання (з номером 1), що використовується при налагодженні програми для її трасування (виконання по кроках).

 

 

 

 

 

Завдання №2:

4. Даны натуральное число n, целые числа a1, …, an (в последовательности могут быть повторяющиеся члены). Получить все числа, которые входят в последовательность по одному разу.

 

EXE модуль програми:

 

assume CS:code, DS:Data

code segment

begin:  mov ax,data

          mov  ds,ax

 

dec len   ;будем делить на 2

mov bx,0  ;обнуляем регистры

mov ax,0

mov si,-1 

 

ii: inc si

cmp si,len

ja fin

 

mov al,mas1[SI]

mov di,-1

 

jj: inc di

cmp di,len

ja k

 

cmp si,di

je jj

mov ah,mas1[di]

cmp ah,al

je ii

jmp jj

k: mov mas2[bx],al

inc bx

jmp ii 

 

 

fin: mov si,bx

dec si

mov di,-1

vyv: inc di

mov bl,10

xor ax,ax

mov al,mas2[di]

 

div bl

 

add al,48

add ah,48

mov bl,ah

 

mov y,al

     mov ah,09h

mov dx,offset y

int 21h

 

mov y,bl

     mov ah,09h

mov dx,offset y

int 21h

mov bl,0

mov y,bl

     mov ah,09h

mov dx,offset y

int 21h

 

cmp si,di

jne vyv

 

exit:

mov ah,4ch

        int 21h

code  ends

data segment

len dw 10 

mas1 db 2,44,11,5,15,3,12,11,44,90

mas2 db 20 dup (0)

y db " $"

data ends

stk segment stack

     db 256 dup()

stk ends

    end begin

 

 

 

 

COM модуль програми:

 

CODESG  SEGMENT PARA 'Code'

        ASSUME  CS:CODESG,DS:CODESG,SS:CODESG,ES:CODESG

        ORG     100H            ;Начало в конце PSP

begin: jmp l1

len dw 10 

mas1 db 2,44,11,5,15,3,12,11,44,90

 mas2 db 20 dup (0)

 y db " $"

 

l1: dec len   ;будем делить на 2

mov bx,0  ;обнуляем регистры

mov ax,0

mov si,-1 

 

ii: inc si

cmp si,len

ja fin

 

mov al,mas1[SI]

mov di,-1

 

jj: inc di

cmp di,len

ja k

 

cmp si,di

je jj

mov ah,mas1[di]

cmp ah,al

je ii

jmp jj

k: mov mas2[bx],al

inc bx

jmp ii 

 

 

fin: mov si,bx

dec si

mov di,-1

vyv: inc di

mov bl,10

xor ax,ax

mov al,mas2[di]

 

div bl

 

add al,48

add ah,48

mov bl,ah

 

mov y,al

     mov ah,09h

mov dx,offset y

int 21h

 

mov y,bl

     mov ah,09h

mov dx,offset y

int 21h

mov bl,0

mov y,bl

     mov ah,09h

mov dx,offset y

int 21h

 

cmp si,di

jne vyv

 

exit:

mov ah,4ch

        int 21h

codesg ends

    end begin

 

 

 

 

 

 

 

 

Операційна система  Windows. Системне програмування в MASM32 з використанням функцій API.

Завдання №3:

23. В матрице С(n,n) удалить в каждом столбце минимальный элемент столбца.

 

Код програми:

assume CS:code, DS:Data

code segment

begin:  mov ax,data

        mov  ds,ax

 

mov bx,row 

mov ax,col 

mul bx 

sub ax,col 

mov dob,ax

 

mov bl,mas1

mov min,bl

mov cx,col

 

incCol:    ;цикл по колонкам

push cx

 

mov di,cx

dec di

mov cx,row

 

mov min,254

 

incRow:  ;цикл по рядкам

mov si,cx

dec si

mov bx,col

mov ax,si

mul bx

mov bx,ax

mov al,mas1[bx][di] ;в al заносим элемент масива

 

cmp min,al  ;сравниваем текущий элемент с минимальным

jb less   ;если минимальный меньше, то переход к след ел

mov min,al  ;иначе присваиваем в мин текущий ел.

mov ind,si  ; и сохраняем индекс мин элемента

 

less: loop incRow

mov si,ind

dec si

ii: inc si  ;цикл по том же столбцу,

cmp si,row ; где мы начиная с сохраненного индекса сдвигаем элементы по столбику

je jj

 

mov bx,col  

mov ax,si

mul bx

mov bx,ax

add bx,col

mov al,mas1[bx][di]

sub bx,col

mov mas1[bx][di],al

jmp ii

 

jj: pop cx

loop incCol

 

mov si,0

mov DI,0

dec col

fin: mov bl,10

xor ax,ax

mov al,mas1[DI]

div bl  ;делим число на 10

 

add al,48 ;добавляем к младшей части 48, чтобы на вывод шел символ числа

add ah,48 ;добавляем к старшей части 48

mov bl,ah

 

mov y,al ;выводим младшую часть

mov ah,09h

mov dx,offset y

int 21h

 

mov y,bl  ;выводим старшую часть

     mov ah,09h

mov dx,offset y

int 21h

 

mov bl,0 ;после каждого элемента выводим пробел

mov y,bl

     mov ah,09h

mov dx,offset y

int 21h

cmp si,col

jne s

 

mov bl,10 ;после каждых col элементов выводим перевод строки

mov y,bl

     mov ah,09h

mov dx,offset y

int 21h

mov si,-1

s: inc si

inc DI

cmp DI,dob

jne fin

 

mov ax,4c00h

int 21h

code  ends

data segment

 row dw 4

 col dw 5

 dob dw 1

 min db 0

 ind dw 0

 mas1 db 61,31,13,99,1

      db 11,22,6, 11,9

      db 8, 12,5,  9,5

      db 12, 3,12, 1,6

 

 y db " $"

 msg db ?

data ends

stk segment stack

     db 256 dup()

stk ends

    end begin

 

 


Системне програмування та операційні системи