Опис програми, що призначена для вводу в текстові документи, за допомогою поєднання клавіш клавіатури, символи ASCII-коду які не можливо ввести з клавіатури, страница 2

З метою економії пам'яті секція ініціалізації розташовується в кінці програми і відкидається при її завершенні.

Першими ж командами нашої програми (пропозиції 1-2) управління передається в системний обробник. При цьому в стеку створюється структура (вміст регістра прапорів від команди pushf і двухсловна адреса повернення на пропозицію 3 від команди дальнього непрямого виклику call CS:old-09h), яка примусить завершуючу команду iret системного обробника повернути управління нашій програмі. Далі в стеку зберігаються використовувані в програмі регістри, а сегментний регістр ES настроюється на початок області даних BIOS (фізична адреса 400h, сегментна адреса 40h) і починається робота з вхідним буфером клавіатури.

Вважатимемо, що перед введенням даного символу буфер був порожній (мал. 52.1,а). Фактично в слові, на яке вказують обидва покажчики, знаходиться код символу, введеного раніше і вже вилученого програмою з буфера. Чергове натиснення клавіші викликає нашу програму, а з неї - системний обробник, який заносить двобайтовий код натиснутої клавіші в хвостовий елемент, переміщаючи хвостовий покажчик на наступне слово буфера (мал. 52.1,6). Здавалося б, одержати код натиснутої клавіші можна або за адресою в головному покажчику, або віднявши 2 з адреси хвостового покажчика. Проте ні те, ні інше невірно.

Головний покажчик дійсно указує на останній збережений в буфері код, лише якщо при запуску програми буфер був порожній. Якщо ж в процесі завантаження програми користувач натискав які-небудь клавіші, їх коди були поміщені в буфер клавіатури, і до моменту активізації нашої програми головний покажчик указуватиме не на порожній осередок буфера, а на найстаріший з введених символів. При цьому у міру занесення в буфер нових символів, обробці піддаватиметься все той же найстаріший символ. Тому надійніше визначати місцезнаходження останнього символу в буфері за адресою в хвостовому покажчику. Проте, враховуючи кільцевий характер буфера, не завжди ця адреса буде на 2 більше адреси останнього символу. У тому випадку, коли черговий вільний осередок буфера знаходився в самому його кінці, за адресою 40h:3Ch, після занесення туди чергового коду хвостовий покажчик переміститься в початок буфера, указуючи на адресу lEh. Тому в нашій програмі після віднімання 2 з адреси хвостового елементу (пропозиції 9-10), перевіряється, чи знаходиться набутого значення в межах буфера. Якщо воно рівне або більше за lEh, командою jae виконується перехід на продовження програми. Якщо ж набутого значення виявилося меншим lEh, це означає, що хвостовий покажчик указує на самий початок буфера, а занесений тільки що в буфер код знаходиться в самому його кінці (мал. 52.1,в). В цьому випадку у ВХ заноситься адреса останнього символу в явному вигляді (пропозиція 13).

Подальший алгоритм програми цілком очевидний. Двобайтовий код натиснутої клавіші витягується з буфера (пропозиція 14) і послідовно порівнюється з двобайтовими кодами, що утворюються при натисненні поєднань <Alt>/<Z>, <Alt>/<X> і <Alt>/<C> (які є при даному виборі перевизначених клавіш розширеними кодами ASCII). Якщо натиснуто одне з вказаних поєднань, код в кільцевому буфері замінюється на код ASCII відповідного символу псевдографіки (природно, без зсуву покажчиків) і здійснюється перехід на мітку outout для завершення програми. Якщо всі три операції порівняння не дали позитивного результату, код в буфері не змінюється.

По мітці outout відновлюються збережені регістри і командою iret управління передається в перервану програму.