Доброго времени суток! Мне нужно реализовать программу, которая выводила бы последовательно цифры от 0 до 9 в одно место экрана. При вводе с клавиатуры какой-либо цифры темп вывода менялся. Значение задержки между выводом очередного символа определяется следующим способом: введённую цифру умножить на 2 в степени 9, это и будет число повторений цикла задержки. Для анализа нажатия клавиши использовать вектор 1Ch. (завершение программы осуществляется при вводе цифры 0)
Проблема возникла непосредственно при написании подпрограммы обработки прерывания 1Ch...
Вот мои наработки по данной программе:
data segment
exit db 0 ;признак завершения программы
sym db "0","1","2","3","4","5","6","7","8","9" ;символ, выводимый на экран
pos dw 3840 ;позиция начального вывода символа
atr db 10 ;атрибут символа(зелёный)
old_cs dw ? ;адрес сегмента старого вектора 1Сh
old_ip dw ? ;адрес смещения старого вектора 1Ch
data ends
code segment
assume cs:code, ds:data
New_1Ch proc ;подпрограмма обработки прерывания 1Ch
iret
New_1Ch endp
ClnScr proc ;программа очистки экрана
push cx
push ax
push si
xor si,si
mov ah, 7
mov dl,' '
mov cx, 2000
cln1:
mov es:[si], ax
inc si
inc si
loop cln1
pop si
pop ax
pop cx
ret
ClnScr endp
Delay proc ;программа задержки
push cx
xor cx,cx
mov cl,9
sal count,cl
xor cx,cx
mov cx,count
d:
loop d
pop cx
ret
Delay endp
Out_Sym proc
push ax
push bx
push si
mov al,[sym+si]
mov ah,atr
mov bx,pos
call Delay
mov es:[bx],ax
pop bx
pop ax
ret
Out_Sym endp
;основная программа
start:
mov ax,data
mov ds,ax
mov ax, 4c00h
int 21h
code ends
end start
Ну, с процедурами - это ты сам как нибудь додумаешь, вот основа программы: получение символа через $1C, и вывод счетчика на экран:
.model small
s_data segment
old_cs dw ? ; для хранения «старого» вектора
old_ip dw ? ; прерываний с номером 1Ch
atr db 10 ; атрибут символов (зеленый)
msg db '0' ; строка, выводимая на экран
cycles dw ? ; 1*2^9
multCycle dw 2048 ; 512 - очень мало, задержку побольше
symbol db '1' ; Символ, нажатый пользователем. В начале = "1"
curr db 0 ; Номер символа, который печатается в данный момент
Pressed db 1 ; Нажал ли пользователь чего-нибудь?
; Куда будет выводиться символ
X equ 40
Y equ 14
s_data ends
s_stack segment stack
db 256 dup(?)
s_stack ends
s_code segment
assume cs: s_code, ds: s_data, ss: s_stack
; подпрограмма обработки прерываний 1Ch
new_1c proc far
; Сохраняем значения всех регистров, которые будут меняться
push ax
push bx
push ds
push es
; DS <- сегмент данных
mov ax, s_data
mov ds, ax
; Проверяем, было ли нажатие
mov ax, 40h ; ES <- BIOS
mov es, ax
mov ax, es:[1Ch] ; AX <- Конец буфера клавиатуры
mov bx, es:[1Ah] ; BX <- Начало буфера клавиатуры
cmp bx, ax ; (BX = AX) => Буфер пуст
jne get_char ; Нет
; Да
jmp go_out
get_char:
mov al, es:[bx] ; Забираем символ из буфера
mov es:[1Ch], bx ; Буфер пуст
mov symbol, al
inc Pressed ; Признак нажатия
go_out:
pop es
pop ds
pop bx
pop ax
iret
new_1c endp
start:
mov ax, s_data
mov ds, ax
; Запомним текущий вектор 1ch
mov ah, 35h
mov al, 1Ch
int 21h
mov old_ip, bx
mov old_cs, es
; Подменим обработчик
push ds ; DS:DX <- Новый обработчик
mov dx, offset new_1c
mov ax, seg new_1c
mov ds, ax
mov ah, 25h
mov al, 1Ch
int 21h ; Установили его
pop ds
mov ax, s_data
mov es, ax ; ES <- s_data
; основной цикл программы
main_loop:
cmp Pressed, 0 ; Проверяем, было ли нажатие?
je make_delay ; Нет, идем к паузе
; Да, было... Сбрасываем флаг нажатия, и проверяем,
; если нажат "0" - на выход
mov Pressed, 0
cmp symbol, 30h
je q
xor ax, ax
mov al, symbol
sub al, 30h ; Число, введенное пользователем
mul multCycle ; Домножаем на коэффициент
mov cycles, ax ; И сохраняем в cycles
make_delay:
; У меня ничего не получалось разглядеть, пока я не стал
; повторять эту задержку 3000 раз... Если хочешь - убери этот доп. цикл
mov cx, 3000
m2:
push cx
mov cx, cycles
m1:
nop
loop m1
pop cx
loop m2
mov al, curr
add al, '0'
mov msg[0], al ; Конвертируем curr в символ
xor bh, bh
mov ah, 13h ; Функция вывода строки с атрибутом
mov al, 0
mov dh, Y
mov dl, X
lea bp, msg ; ES:BP <- выводимая строка
mov cx, 1 ; Длина выводимой строки
mov bl, atr
int 10h
; это я добавлял для тестирования,
; в каком порядке выводятся символы
; mov ah, 0eh
; mov al, msg[0]
; mov bh, 0
; int 10h
inc curr
cmp curr, 10 ; Дошли до десятки?
jne main_loop ; Нет еще
; Да, сбрасываем на 0
mov curr, 0
jmp main_loop
q:
; Восстановливаем все назад
push ds
mov dx, old_ip
mov ax, old_cs
mov ds, ax
mov ah, 25h
mov al, 1Ch
int 21h
pop ds
mov ax, 4C00h ; И выходим
int 21h
s_code ends
end start
mov msg[0], alздесь используется относительно регистровая адресация?т.е. адрес вычисляется как сумма содержимого регистра и смещения...
xor bh, bh
mov ah, 13h
mov al, 0
mov dh, Y
mov dl, X
lea bp, msg
mov cx, 1
mov bl, atr
int 10h
mov msg[0], alздесь используется относительно регистровая адресация? т.е. адрес вычисляется как сумма содержимого регистра и смещения...