Прекращение ввода чисел по нажатию клавиши - 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)
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д