Прекращение ввода чисел по нажатию клавиши - 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)