ПРИЛОЖЕНИЕ Б. ПРОГРАММЫ ВВОДА-ВЫВОДА

Приведённые программы могут использоваться как простое средство для выполнения функций ввода-вывода в программах, написанных на языке ассемблера. Эти программы можно применять или для ввода и печати чисел, или для ввода и печати символьных строк. Для включения в программу пользователя их можно скопировать и выполнить их ассемблирование вместе с программой пользователя. Можно поступить и иначе: выполнить ассемблирование программ ввода-вывода только один раз, а их подключение к программам пользователя осуществлять на этапе компоновки, связывая эти программы через глобальные имена.

Всего для выполнения функций ввода-вывода используется пять подпрограмм, а именно IOINIT, RNUM, PNUM, RLINE и PLINE. Все они вызываются с помощью инструкции JSB. Ниже дано описание функций, выполняемых этими подпрограммами.

IOINIT

Подпрограмма IOINIT используется для установки начальных значений в четырёх других подпрограммах ввода-вывода. Она вызывается только один раз, но при этом должна быть вызвана перед тем, как будет использована какая-либо из этих других подпрограмм. Вызов подпрограммы осуществляется следующим образом:

JSB     IOINIT

Подпрограмма IOINIT возвращает управление, сохраняя содержимое всех регистров. Кроме того, что она позволяет выполнять другие подпрограммы из данного набора, явным результатом её работы является печать сообщения об её успешном завершении.

RNUM

Подпрограмма RNUM предназначается для ввода шестнадцатеричного числа из файла системного ввода. Преобразованное во внутреннее представление число помещается в регистр R0. Содержимое всех других регистров не изменяется. При работе в интерактивном режиме на терминал выдаётся запрос "ВВЕДИТЕ ШЕСТНАДЦАТЕРИЧНОЕ ЧИСЛО - ". Обращение к подпрограмме следующее:

JSB     RNUM
результат возвращается в R0

PNUM

Подпрограмма PNUM служит для выполнения печати содержимого регистра R0 (содержимое рассматривается как длинное слово) в шестнадцатеричном и десятичном виде. Содержимое всех регистров не изменяется. Обращение к подпрограмме осуществляется следующим образом:

загрузить число в R0
JSB     PNUM

RLINE

Подпрограмма RLINE предназначена для чтения строки символов в коде ASCII из файла системного ввода. Введённые символы помещаются в массив, находящийся в программе пользователя. При вызове подпрограммы ей необходимо передать адрес байтового массива, в который будет помещена строка символов, и длину этого массива. Адрес в формате длинного слова должен находиться в регистре R0, а длина массива в формате слова помещается в регистр R1. После того, как подпрограмма RLINE передаёт управление обратно, в массиве будут находиться все символы, присутствовавшие во вводимой строке, а в регистре R1 будет содержаться в формате слова число, соответствующее количеству в действительности введённых символов. Это число может изменяться от 0 до заданной длины массива, но не может превышать заданную длину массива. В регистре R0 будет находиться в формате слова код ошибки. Если ошибок не было, то регистр R0 будет содержать число 1. Наличие в регистре любого другого числа означает, что произошла ошибка. Наиболее вероятными являются ошибки, связанные с тем, что длина буфера слишком мала, чтобы вместить всю строку, или же была предпринята попытка продолжить ввод после того, как был встречен признак конца вводимых данных. Содержимое всех других регистров не изменяется. Последовательность действий при вызове подпрограммы RLINE приведена ниже.

загрузить адрес буфера в R0
предельную длину буфера в R1 
JSB     RLINE
R0 содержит код ошибки
R1 содержит число введённых символов

PLINE

Подпрограмма PLINE используется для вывода на печать в файл системного вывода строки текста в коде ASCII. В регистр R0 должен быть помещён адрес массива символов, а регистр R1 должен содержать в формате слова число символов в этом массиве. Содержимое всех регистров сохраняется. Так как подпрограмма PLINE сопровождает вывод каждой строки управляющими символами "Возврат каретки" и "Перевод строки", то в выводимой строке эти символы не должны присутствовать, если только нет необходимости вывести дополнительные строчки. Последовательность вызова для подпрограммы PLINE даётся ниже.

загрузить адрес буфера в R0
число символов в R1
JSB     PLINE

ПРОГРАММЫ ВВОДА-ВЫВОДА НА ЯЗЫКЕ АССЕМБЛЕРА

Для использования программ ввода-вывода в программе пользователя приведённые ниже исходные тексты программ могут быть помещены между последней строчкой текста программы пользователя и директивой .END. Программы сопровождаются комментариями, поясняющими их действие. Однако предполагается, что не всё будет полностью понятно, пока не будут прочитаны гл. 1-11. Для ускорения ввода текста программ можно опустить комментарии. Программы могут быть ассемблированы как отдельный программный модуль, а полученный в результате ассемблирования объектный файл может быть скомпонован с основной программой.

RNUMBUFSIZ=80                           ;УСТАНОВИТЬ ДЛИНУ БУФЕРОВ 80
PNUMBUFSIZ=80
                .PSECT  IOROUTINE,LONG              ;FAB И RAB ВЫРОВНЕНЫ
RNUMFILE:       $FAB    FNM=<SYS$INPUT>             ;НА ГРАНИЦУ ДЛИННОГО СЛОВА
PNUMFILE:       $FAB    FNM=<SYS$OUTPUT>,RAT=<CR>
RNUMIREC:       $RAB    FAB=RNUMFILE,UBF=RNUMBUF,USZ=RNUMBUFSIZ,-
                        PBF=RNUMPRO,PSZ=RNUMPROL-RNUMPRO,ROP=<PMT>
PNUMOREC:       $RAB    FAB=PNUMFILE,RBF=PNUMOUT
RLINEREC:       $RAB    FAB=RNUMFILE,-
                        PBF=RLINEPRO,PSZ=RLINEPROL-RLINEPRO,ROP=<PMT>
PLINEREC:       $RAB    FAB=RNUMFILE
 
PNUMTEMP:       .BLKL   1               ;ВРЕМЕННАЯ ПАМЯТЬ И БУФЕРЫ
PNUMOUT:        .BLKB   PNUMBUFSIZ
RNUMBUF:        .BLKB   RNUMBUFSIZ
 
;СИМВОЛЬНЫЕ СТРОКИ И ДЕСКРИПТОРЫ
 
PNUMSTR:        .ASCID  "ВЫВОД !XL(ШЕСТНАДЦАТЕРИЧНОЕ) !SL(ДЕСЯТИЧНОЕ)"
IOINITSTR:      .ASCID  "ВВОД И ВЫВОД ИНИЦИАЛИЗИРОВАНЫ !%D"
RNUMPRO:        .ASCII  "ВВЕДИТЕ ШЕСТНАДЦАТЕРИЧНОЕ ЧИСЛО - "
RNUMPROL:
RLINEPRO:       .ASCII  "ВВЕДИТЕ СТРОКУ - "
RLINEPROL:
PNUMDES:        .LONG   PNUMBUFSIZ
                .LONG   PNUMOUT
 
 
; ПРОГРАММА ИНИЦИАЛИЗАЦИИ
 
IOINIT::
        PUSHR   #^M<R0,R1>              ;СОХРАНИТЬ СОДЕРЖИМОЕ РЕГИСТРОВ
        $OPEN   FAB=RNUMFILE            ;ОТКРЫТЬ ФАЙЛ ВВОДА
        $CREATE FAB=PNUMFILE            ;ОТКРЫТЬ ФАЙЛ ВЫВОДА
        $FAO_S  CTRSTR=IOINITSTR,OUTBUF=PNUMDES,-       ;ФОРМАТ
                OUTLEN=PNUMOREC+RAB$W_RSZ,P1=$0         ;СООБЩЕНИЯ
        $CONNECT RAB=PNUMOREC           ;ПОДКЛЮЧИТЬ RAB СООБЩЕНИЙ
        $PUT    RAB=PNUMOREC            ;ПЕЧАТЬ СООБЩЕНИЯ ОБ ИНИЦИАЛИЗАЦИИ
        POPR    #^M<R0,R1>              ;ВОССТАНОВИТЬ РЕГИСТРЫ
        RSB                             ;ВОЗВРАТ
 
 
; ПРОГРАММА ПЕЧАТИ ЧИСЛА
 
PNUM::
        PUSHR   #^M<R0,R1>              ; СОХРАНИТЬ СОДЕРЖИМОЕ РЕГИСТРОВ
        MOVL    R0,PNUMTEMP             ; ПОЛУЧИТЬ И ПРЕОБРАЗОВАТЬ ЧИСЛО
        $FAO_S  CTRSTR=PNUMSTR,OUTBUF=PNUMDES,OUTLEN=PNUMOREC+RAB$W_RSZ,- 
                P1=PNUMTEMP,P2=PNUMTEMP
        $CONNECT RAB=PNUMOREC           ;ПОДКЛЮЧИТЬ RAB ВЫВОДА
        $PUT    RAB=PNUMOREC            ;И НАПЕЧАТАТЬ ЧИСЛО
        POPR    #^M<R0,R1>              ;ВОССТАНОВИТЬ РЕГИСТРЫ
        RSB                             ;ВОЗВРАТ
 
 
; ПРОГРАММА ВВОДА ЧИСЛА
 
RNUM::
        PUSHR   #^M<R1>                 ;СОХРАНИТЬ РЕГИСТР R1
        $CONNECT RAB=RNUMIREC           ;ПОДКЛЮЧИТЬ RAB ВВОДА
        $GET    RAB=RNUMIREC            ;ВВЕСТИ ЧИСЛО
        CLRL    R0                      ;ОЧИСТИТЬ РЕГИСТР ПРЕОБРАЗОВАНИЯ
        MOVAB   RNUMBUF,R1              ;УКАЗАТЕЛЬ НА БУФЕР ЧИСЛА
10$:    DECW    RNUMIREC+RAB$W_RSZ      ;УМЕНЬШИТЬ СЧЁТЧИК СИМВОЛОВ
        BLSS    30$                     ;ЗАКОНЧИТЬ, ЕСЛИ В СЧЁТЧИКЕ 0
        ASHL    #4,R0,R0                ;УМНОЖИТЬ НА 16
        SUBB2   #48,(R1)                ;ПРЕОБРАЗОВАТЬ В ДВОИЧНОЕ ЧИСЛО
        СМРВ    (R1),#10                ;БОЛЬШЕ ЧЕМ 10?
        BLSS    20$                     ;НЕТ
        SUBB2   #65-48-10,(R1)          ;ДА, ПРЕОБРАЗОВАТЬ ASCII "А" В 10
20$:    BISB    (R1)+,R0                ;ДОБАВИТЬ К ПОЛУЧЕННОМУ ЧИСЛУ
        BRB     10$                     ;ПОВТОРИТЬ ДЛЯ ОСТАВШИХСЯ ЦИФР
30$:    POPR    #^M<R1>                 ;ВОССТАНОВИТЬ РЕГИСТР R1
        RSB                             ;ВОЗВРАТ
 
 
; ПРОГРАММА ВВОДА СТРОКИ
 
RLINE::
        MOVL    R0,RLINEREC+RAB$L_UBF   ;УСТАНОВИТЬ АДРЕС БУФЕРА
        MOVW    R1,RLINEREC+RAB$W_USZ   ;И ЕГО ПРЕДЕЛЬНУЮ ДЛИНУ
        $CONNECT RAB=RLINEREC           ;ПОДКЛЮЧИТЬ RAB
        $GЕТ    RAB=RLINEREC            ;ВВЕСТИ СТРОКУ
        MOVZWL  RLINEREC+RAB$W_RSZ,R1   ;ВЕРНУТЬ ДЛИНУ ВВЕДЁННОЙ СТРОКИ
        RSB                             ;И КОД ОШИБКИ В R0
 
 
;ПРОГРАММА ПЕЧАТИ СТРОКИ
 
PLINE::
        PUSHR   #^M<R0,R1>              ;СОХРАНИТЬ СОДЕРЖИМОЕ РЕГИСТРОВ
        MOVL    R0,PLINEREC+RAB$L_RBF   ;ПОЛУЧИТЬ АДРЕС БУФЕРА
        MOVW    R1,PLINEREC+RAB$W_RSZ   ;И ДЛИНУ СТРОКИ
        $CONNECT RAB=PLINEREC           ;ПОДКЛЮЧИТЬ RAB ВЫВОДА
        $PUT    RAB=PLINEREC            ;НАПЕЧАТАТЬ СТРОКУ
        POPR    #^M<R0,R1>              ;ВОССТАНОВИТЬ РЕГИСТРЫ
        RSB                             ;ВОЗВРАТ

 

< НАЗАД ОГЛАВЛЕНИЕ ВПЕРЁД >