· Model Pascal {модель пам’яті Pascal}
· Code {початок сегменту кода}
Sort Obme Proc Far Array Ptr : dword, kol: word
Public Sort Obme {п/п доступна в Pascal}
Push ds {зберегти DS Turbo Pascal}
Mov cx, kol {лічильник циклу}
Dec kol {зменьшимо kol}
Cikl1: puch cx {зберегти лічильник зовн. циклу}
Lds si, Array Ptr {адреса масива до регістра SI}
Cld {визначимо напрям перегляду масиву }
Mov cx, kol { визначимо лічильник внутр. циклу }
Cikl2: lodsw {завантажили a[i] в AxS}
Cmp ax, [si] {I порівняємо з а[I+1]}
Jge cout {якщо а[i]< a[i+1]}
X chg ax, [si] {поміняти місцями}
Mov [si - 2], ax {ці елементи}
Cout loop cikl2 {кінець внутр. циклу}
Pop cx {відновимо із стеку параметр зовн. циклу}
Loop cikl1 {поміняємо параметр зовн. циклу }
Pop ds {відновимо DS із стеку}
Ret {завершим п/п}
Sortobme End p
Code ends
end
Пояснення:
Команда LDS записує адресу масиву до регістру SI. Напрямок перегляду елементів масиву визначено командою CLD (з ліва – направо). Команда LODSW завантажує число з масиву в регістр АХ і збільшує значення в регістрі SI на 2, що дозволяє наступній команді CMP AX,[SI] порівняти два сусідні елементи масиву. Результат порівняння впливає на роботу команди JGE. Обмін місцями елементів масиву забезпечують команди XCHG AX, [SI] та MOV [SI-2], AX. Перша з них міняє місцями числа в регістрі АХ та в масиві, а друга – пересилає число з АХ в попереднє місце масиву.
Необхідно звернути увагу на маніпуляції з регістром СХ. В зв’язку з тим, що для сортування треба організувати 2-а цикли (кожен з них вживає лічильник з регістру СХ) в підпрограмі застосовано збереження параметру зовнішнього циклу в стеку (Push cx). Цей параметр відновлюється (Pop cx) після закінчення внутрішнього циклу.
Після завершення зовнішнього циклу із стеку відновлюється регістр DS, і робота підпрограми закінчується. Текст такої підпрограми на Асемблері можна набрати у будь-якому текстовому редакторі і записати в файл з розширенням .asm. Після цього, його треба відтранслювати, виконавши команду Tasm Sort Obme.asm. Якщо будуть виявлені синтаксичні помилки, з’явиться повідомлення:
Assembling file; Sort Obme.asm
**Error** Sort Obme.asm()…
В дужках вказується номер помилкового рядка, а за ним причина помилки. Після виправлення помилки треба повторити трансляцію. В разі відсутності помилок у тексті з’явиться повідомлення ERROR messages None, буде створено файл Sort Obme.obj Його треба записати в поточний каталог системи ТР, ввійти в турбосередовище і виконати програму. Існує іще один спосіб – стикування з асемблером, при якому передача параметрів між програмами забезпечуеться стеком (найчастіше застосування регістрів SP та BP).
Розглянемо можливість стикування з підпрограмами мовою ТС. Для мови С характерний простий доступ до даних не тільки за їх іменами, а і за відповідними адресами, можливість простої роботи з окремими двійковими розрядами, що зручно при використанні системних ресурсів, безпосередній доступ до деяких переривань на рівні стандартних функцій.
Недоліки:
Її важко вивчити, універсальність мови не сприяє надійності програм. Це пояснюється в першу чергу тим, що бібліотеки системи програмування ТС відкомпільовані з урахуванням вимог саме цієї мови, тобто із Pascal програми не можна підключати підпрограму на ТС, в якій є звернення до бібліотек. Але якщо в таких підпрограмах не вживаються бібліотечні функції, стикування можливе. Щоб викликати підпрограму на ТС треба, щоб і головна програма і підпрограма були написані з урахуванням погодження про зв’язки та імена. В мові ТР параметри, які передаються у підпрограму розміщуються в стеку в тому порядку, який вказано при виклику. Мова ТС розміщує параметри в зворотньому порядку (це дозволяє використовувати підпрограми зі змінною кількістю параметрів). В мові ТС після звернення до підпрограми стек відновлює та програма, яка викликає цю підпрограму, а в мові ТР стек відновлює сама підпрограма. Розглянемо один із способів стикування Pascal-CI.
В програмі на ТР треба виконати такі самі операції, як і при стикуванні з Асемблером, тобто описати заголовок зовнішньої підпрограми як External, за допомогою директиви {$L}підключити відповідний об’єктний файл, а потім викликати потрібну програму.
Приклад:
Program k1;
Var r:word;
Procedure Inc Pol (t:pointer);
External;
{$L c_ka.obj}
begin
r:=0;
Inc Pol (@r);
Writeln(r);
End.
Об’єктний файл треба сформувати таким чином: по правилам мови ТС оформити текст підпрограми, в заголовку якої повинно бути слово Pascal і від транслювати її для створення .obj- файлу (при роботі в турбосередовищі натиснути ALT/F9). Саме режим Pascal забезпечить погодження про зв’язки та імена.
{текст підпрограми мовою ТС}
void Pascal incpol (unsigned*t)
{
struct v{
unsigned pole1:5;
unsigned pole2:6;
unsigned pole3:5;
}*u;
u=(struct v*)t;
u-> pole2+=1;
}
Пояснення. В головній програмі мовою ТР описується заголовок зовнішньої підпрограми IncPol і підключається об’єктний файл с_ka.obj, до складу якого входить ця підпрограма. При звернені до підпрограми використовується аргумент – адреса змінної r типу word. Цьому аргументу в підпрограмі мовою ТС відповідає вказівник на структуру з бітовими полями, тобто змінна r співпадає зі структурою розміром 16 біт. В підпрограмі змінюється одне з полів структури, що природно змінює значення змінної r. В програмі на ТР буде виведено результат – число 32, тому що в підпрограмі було змінено шостий розряд ( тобто 2 в степені 5). Це приклад того, як зручно мовою ТС виконувати операції над бітовими даними. Однак, слід відмітити, що стикування Pascal-C потребує додаткової розробки.