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