Прекращение ввода чисел по нажатию клавиши - Assembler

Узнай цену своей работы

Формулировка задачи:

Прошу помощи. Вообщем нужно при нажатии клавиши 'z' прекратить ввод чисел с клавиатуры и перейти к метке после которой выполняются другие действия. Получилось скомпоновать некоторый код, который пока что вводит числа со знаком и преобразует их в противоположные, а после ввода цифры 0 выводит введенные числа с противоположным знаком. Вообще прошу помощи с внедрением в код прерывания которое сможет реагировать на клавишу 'z'.
ideal 
P386N
Model Small
 
Dataseg
    s_sword  db 'Enter number:',13,10,'$'
    output db 'Output number: ',13,10,'$'
    s_error  db 'ERROR!',13,10,'$'
    s_pak    db 'Press any key...$'
    endline  db 13,10,'$'
    buffer   db 9
 
Codeseg
 
;-------------------------------------------------------------------------------
;Процедура ввода слова с консоли в десятичном виде (со знаком)
; выход: AX - слово (в случае ошибки AX = 0)
;        CF = 1 - ошибка
input_sdec_word:
    push dx         ;Сохранение DX
    mov al,7            ;Ввод максимум 7 символов (-32768) + конец строки
    call input_str      ;Вызов процедуры ввода строки
    call str_to_sdec_word   ;Преобразование строки в слово (со знаком)
    pop dx          ;Восстановление DX
    ret
 
;-------------------------------------------------------------------------------
;Процедура ввода строки c консоли
;  вход: AL - максимальная длина (с символом CR) (1-254)
; выход: AL - длина введённой строки (не считая символа CR)
;        DX - адрес строки, заканчивающейся символом CR(0Dh)
input_str:
    push cx         ;Сохранение СX
    mov cx,ax           ;Сохранение AX в CX
    mov ah,0Ah          ;Функция DOS 0Ah - ввод строки в буфер
    mov [buffer],al     ;Запись максимальной длины в первый байт буфера
    push bx
    lea bx, [buffer+1]
    mov [byte bx],0    ;Обнуление второго байта (фактической длины)
    pop bx
    mov dx,offset buffer        ;DX = aдрес буфера
    int 21h         ;Обращение к функции DOS
    mov al,[buffer+1]       ;AL = длина введённой строки
    add dx,2            ;DX = адрес строки
    mov ah,ch           ;Восстановление AH
    pop cx          ;Восстановление CX
    ret
 
;-------------------------------------------------------------------------------
;Процедура преобразования десятичной строки в слово со знаком
;  вход: AL - длина строки
;        DX - адрес строки, заканчивающейся символом CR(0Dh)
; выход: AX - слово (в случае ошибки AX = 0)
;        CF = 1 - ошибка
str_to_sdec_word:
    push bx         ;Сохранение регистров
    push dx
 
    test al,al          ;Проверка длины строки
    jz stsdw_error      ;Если равно 0, возвращаем ошибку
    mov bx,dx           ;BX = адрес строки
    mov bl,[bx]         ;BL = первый символ строки
    cmp bl,'-'          ;Сравнение первого символа с '-'
    jne stsdw_no_sign       ;Если не равно, то преобразуем как число без знака
    inc dx          ;Инкремент адреса строки
    dec al          ;Декремент длины строки
stsdw_no_sign:
    call str_to_udec_word   ;Преобразуем строку в слово без знака
    jc stsdw_exit       ;Если ошибка, то возвращаем ошибку
    cmp bl,'-'          ;Снова проверяем знак
    jne stsdw_plus      ;Если первый символ не '-', то число положительное
    cmp ax,32768        ;Модуль отрицательного числа должен быть не больше 32768
    ja stsdw_error      ;Если больше (без знака), возвращаем ошибку
    neg ax          ;Инвертируем число
    jmp stsdw_ok        ;Переход к нормальному завершению процедуры
stsdw_plus:
    cmp ax,32767        ;Положительное число должно быть не больше 32767
    ja stsdw_error      ;Если больше (без знака), возвращаем ошибку
 
stsdw_ok:
    clc             ;CF = 0
    jmp stsdw_exit      ;Переход к выходу из процедуры
stsdw_error:
    xor ax,ax           ;AX = 0
    stc             ;CF = 1 (Возвращаем ошибку
stsdw_exit:
    pop dx          ;Восстановление регистров
    pop bx
    ret
 
;-------------------------------------------------------------------------------
;Процедура преобразования десятичной строки в слово без знака
;  вход: AL - длина строки
;        DX - адрес строки, заканчивающейся символом CR(0Dh)
; выход: AX - слово (в случае ошибки AX = 0)
;        CF = 1 - ошибка
str_to_udec_word:
    push cx         ;Сохранение всех используемых регистров
    push dx
    push bx
    push si
    push di
 
    mov si,dx           ;SI = адрес строки
    mov di,10           ;DI = множитель 10 (основание системы счисления)
    movzx cx,al         ;CX = счётчик цикла = длина строки
    jcxz studw_error        ;Если длина = 0, возвращаем ошибку
    xor ax,ax           ;AX = 0
    xor bx,bx           ;BX = 0
 
studw_lp:
    mov bl,[si]         ;Загрузка в BL очередного символа строки
    inc si          ;Инкремент адреса
    cmp bl,'0'          ;Если код символа меньше кода '0'
    jl studw_error      ; возвращаем ошибку
    cmp bl,'9'          ;Если код символа больше кода '9'
    jg studw_error      ; возвращаем ошибку
    sub bl,'0'          ;Преобразование символа-цифры в число
    mul di          ;AX = AX * 10
    jc studw_error      ;Если результат больше 16 бит - ошибка
    add ax,bx           ;Прибавляем цифру
    jc studw_error      ;Если переполнение - ошибка
    loop studw_lp       ;Команда цикла
    jmp studw_exit      ;Успешное завершение (здесь всегда CF = 0)
 
studw_error:
    xor ax,ax           ;AX = 0
    stc             ;CF = 1 (Возвращаем ошибку)
 
studw_exit:
    pop di          ;Восстановление регистров
    pop si
    pop bx
    pop dx
    pop cx
    ret
 
;----------------------------------------------------------------------
;Процедура преобразования слова в строку в десятичном виде (без знака)
; AX - слово
; DI - буфер для строки (5 символов). Значение регистра не сохраняется.
word_to_udec_str:
    push ax
    push cx
    push dx
    push bx
    xor cx,cx           ;Обнуление CX
    mov bx,10           ;В BX делитель (10 для десятичной системы)
 
wtuds_lp1:          ;Цикл получения остатков от деления
    xor dx,dx           ;Обнуление старшей части двойного слова
    div bx          ;Деление AX=(DX:AX)/BX, остаток в DX
    add dl,'0'          ;Преобразование остатка в код символа
    push dx         ;Сохранение в стеке
    inc cx          ;Увеличение счетчика символов
    test ax,ax          ;Проверка AX
    jnz wtuds_lp1       ;Переход к началу цикла, если частное не 0.
 
wtuds_lp2:          ;Цикл извлечения символов из стека
    pop dx          ;Восстановление символа из стека
    mov [di],dl         ;Сохранение символа в буфере
    inc di          ;Инкремент адреса буфера
    loop wtuds_lp2      ;Команда цикла
 
    pop bx
    pop dx
    pop cx
    pop ax
    ret
 
;----------------------------------------------------------------------
;Процедура преобразования слова в строку в десятичном виде (со знаком)
; AX - слово
; DI - буфер для строки (6 символов). Значение регистра не сохраняется.
word_to_sdec_str:
    push ax
    test ax,ax          ;Проверка знака AX
    jns wtsds_no_sign       ;Если >= 0, преобразуем как беззнаковое
    mov [byte di],'-'       ;Добавление знака в начало строки
    inc di          ;Инкремент DI
    neg ax          ;Изменение знака значения AX
wtsds_no_sign:
    call word_to_udec_str   ;Преобразование беззнакового значения
    pop ax
    ret
 
;----------------------------------------------------------------------
;Процедура вывода слова на консоль в десятичном виде (со знаком)
; AX - слово
print_word_sdec:
    push di
    mov di,offset buffer        ;DI = адрес буфера
    push di         ;Сохранение DI в стеке
    call word_to_sdec_str   ;Преобразование слова в AX в строку
    mov [byte di],'$'       ;Добавление символа конца строки
    pop di          ;DI = адрес начала строки
    call print_str      ;Вывод строки на консоль
    pop di
    ret
 
;-------------------------------------------------------------------------------
;Процедура вывода строки на консоль
; DI - адрес строки
print_str:
    push ax
    mov ah,9            ;Функция DOS 09h - вывод строки
    xchg dx,di          ;Обмен значениями DX и DI
    int 21h         ;Обращение к функции DOS
    xchg dx,di          ;Обмен значениями DX и DI
    pop ax
    ret
 
;-------------------------------------------------------------------------------
;Процедура вывода конца строки (CR+LF)
print_endline:
    push di
    mov di,offset endline       ;DI = адрес строки с символами CR,LF
    call print_str      ;Вывод строки на консоль
    pop di
    ret
 
Main:
    mov ax, @data
    mov ds, ax
 
    mov cx,offset print_str     ;Адрес процедуры print_str
    mov bx,offset print_endline    ;Адрес процедуры print_endline
    
in_sword_lp:
    mov di,offset s_sword
    call cx         ;Вывод строки 'Enter number:'
    xor cx,cx       ;Обнуляем регистр CX
 
input_number:
    call input_sdec_word    ;Ввод слова со знаком
    mov bx,offset print_endline    ;Адрес процедуры print_endline
    call bx         ;Вывод конца строки
    cmp ax, 0
    je output_text
    neg ax
    push ax
    inc cx
    jmp input_number
 
output_text:
    lea di, [output]
    lea bx, [print_str]
    call bx
 
output_bumber:
    pop ax
    call print_word_sdec    ;Вывод AX в десятичном виде (со знаком)
    lea bx, [print_endline]    ;Адрес процедуры print_endline
    call bx
    loop output_bumber
 
    ;call bx            ;Вывод конца строки
    ;jnc exit           ;Если нет ошибки, переход к выходу из программы
    ;mov di,offset s_error
    ;call cx            ;Вывод строки 'ERROR!'
    ;jmp in_sword_lp        ;Переход к началу цикла
 
exit:
    lea di, [s_pak]
    lea bx, [print_str]
    call bx         ;Вывод строки 'Press any key...'
    mov ah,8            ;Функция DOS 08h - ввод символа без эха
    int 21h
 
    mov ax,4C00h        ;\
    int 21h         ;/ Завершение программы
 
Stack 100
End Main

Решение задачи: «Прекращение ввода чисел по нажатию клавиши»

textual
Листинг программы
 ; строка(38)
 lea bx, [buffer+1]
 
 ; определи этот буфер так (строка 11):
 buffer   db  9,0,9 dup(0)

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

12   голосов , оценка 3.667 из 5
Похожие ответы