Шаг 40.
Процедуры ввода и вывода многозначных чисел

    На этом шаге мы приведем текст процедур, позволяющих вводить с клавиатуры и выводить на экран многозначные числа.

    Приведем тексты процедур, которые можно использовать для организации ввода и вывода многозначных чисел. Эти процедуры можно взять за основу при разработке собственных аналогичных процедур.

    Дадим краткое описание алгоритмов, использованных при реализации этих процедур.

    Процедура ввода принимает символ с клавиатуры и помещает его в стек, увеличивая на единицу значение регистра CX, сохраняющего количество введенных символов. После нажатия пользователем клавиши Enter, из стека извлекается очередная цифра, которая умножается соответственно на 1, 10, 1000 и т.д. Полученное значение прибавляется к результату, находящемуся в регистре BX. Эти операции осуществляются в цикле.

    Например, если было введено число 124, то тело цикла будет выполнено 3 раза и при извлечении цифр из стека будет вычислена такая сумма: 4*1+2*10+1*100, что составляет 124.

    Процедура позволяет вводить отрицательные числа. В этом случае знак '-' будет последним в стеке, что является признаком завершения цикла.

    Процедура вывода числа осуществляет деление значения, находящегося в регистре BX, на 10 и размещение в стеке остатков от деления. После того, как получившееся на очередном шаге частное стало равно нулю, осуществляется извлечение из стека находящихся там символов и вывод их на экран.

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

    Приведем текст модуля, содержащего описанные процедуры.

        PUBLIC Vvod,Vyvod   ;Экспортируемые процедуры.
;------------------Сегмент стека -------------------
StackSg SEGMENT  PARA Stack 'Stack'
DW      132   DUP (?)
StackSg ENDS
;------------------Сегмент кодов -------------------
CodeSg  SEGMENT PARA PUBLIC
        ASSUME CS:CodeSg
Vvod    PROC  FAR   ;Процедура ввода числа.
                    ;Число помещается в регистр BX. 
;------------------ Сохранение регистров --------------
        PUSH AX
        PUSH CX
        PUSH DX
;------------------ Ввод с клавиатуры -----------------
        MOV BX,0000 ;Введенное число.
        MOV CX,0000 ;Количество помещений в стек.
        MOV DX,1    ;Множитель.
@V1:    MOV AH,01
        INT 21H
        CMP AL,0DH  ;Это клавиша Enter?
        JE @V2      ;Переход на обработку числа.
        CMP AL,'-'  ;Это знак '-'?
        JE @V3      ;Ничего вычитать не надо.  
        SUB AL,30H
@V3:    MOV AH,0
        PUSH AX     ;Поместить цифру в стек.
        INC CX      ;Увеличить счетчик на 1.
        JMP @V1     ;Переход на ввод новой цифры.
;------------------ Получение числа --------------------
@V2:    POP AX      ;Достать цифру из стека.
        CMP AL,'-'  ;Это '-'?
        JNE @V4     ;Нет - перейти на обработку.
        NEG BX      ;Да - сменить знак числа.
        JMP @V5     ;Выход из процедуры.
@V4:    MUL DL      ;Умножить ее на множитель.
        ADD BX,AX   ;Прибавить произведение к результату.
                    ;Получить очередной множитель.
        MOV AX,DX
        MOV DX,000AH
        MUL DL
        MOV DX,AX   ;Поместить множитель в DX.
        LOOP @V2    ;Извлечь очередную цифру.         
;-- Выход из процедуры. Восстановление регистров --------
@V5:
        POP DX
        POP CX
        POP AX
        RET
Vvod    ENDP
 
Vyvod   PROC  FAR   ;Процедура вывода числа на экран.
                    ;Число находится в регистре BX. 
;------------------ Сохранение регистров --------------
        PUSH AX
        PUSH CX
        PUSH DX
;------------------ Проверяем знак числа --------------
        CMP BX,0
        JGE @K1     ;Да - число неотрицательное.
        MOV AH,02   ;Выводим на экран символ '-'.
        MOV DL,'-'
        INT 21H
        NEG BX      ;Меняем знак.
;------------------ Получаем цифры числа ---------------
@K1:    MOV AX,BX
        MOV BX,0000
        MOV DX,000AH;Делитель.
        MOV CX,0000 ;Количество помещений в стек.
@K2:    DIV DL     
        MOV BL,AH   ;Остаток от деления - в стек.
        PUSH BX
        MOV AH,0
        INC CX      ;Увеличить счетчик на 1.
        CMP AX,0    
        JNE @K2     ;Получение следующей цифры.
;------------------ Вывод цифр на экран -----------------
        MOV AH,02
@K3:    POP DX
        ADD DL,30H
        INT 21H
        LOOP @K3
;-- Выход из процедуры. Восстановление регистров --------
        POP DX
        POP CX
        POP AX
        RET
Vyvod   ENDP
CodeSg  ENDS
        END
Текст этого модуля можно взять здесь.

    Понятно, что эти процедуры далеки от совершенства. Они могут послужить основой для написания полнофункциональных процедур.

    Отметим, что можно добавить к этим процедурам еще несколько процедур (например, процедуры очистки экрана, установки курсора, вывода строки на экран и т.д.) и оформить их в виде файла, который присоединять к файлу с программой на этапе компоновки при выполнении, например, следующей команды:

            LINK.EXE    PROG.OBJ + SERVIS.OBJ                     .

    Здесь PROG.OBJ - откомпилированный файл с основной программой, SERVIS.OBJ - откомпилированный файл с набором процедур.

    Отметим также, что крайне желательно в создаваемых процедурах сохранять используемые в процедуре регистры в начале и восстанавливать их в конце процедуры. Это позволит при разработке основной программы не вспоминать, какие регистры были задействованы в реализации той или иной процедуры.

    На следующем шаге мы приведем несколько примеров использования операторов условного перехода.




Предыдущий шаг Содержание Следующий шаг