@DVoropaev
Ставлю + к карме на хабре за ответы на вопросы

Почему программа некорректно завершается?

Задачей было написать резидентную программу для DOS, которая проигрывает ноты из массива (1сек на каждую ноту)
Программа запускается, в фоне проигрываются ноты. но как только ноты заканчиваются, DOS перестает на что либо реагировать

.model tiny
.code
org 100h 
.386
start:jmp load
ppresenceflag dw 1260h
old dd 0
outSound dw ?
la dw 2711
;массив частот соответсвующих нотам
notes dw 1B8h, 1BEh, 1EDh, 20BH, 22AH,24BH, 26EH, 293H,2BAH, 2E3H,310H,33EH,370H
counter db 18
i dw 0
isItFirst db 1
 
;процедура, проигрывающая звук  
bip proc 
    pusha
    mov al,0b6H;управляющтй бит
    out 43H,al
    mov ax,outSound;частота
    out 42H,al;младшая
    mov al,ah
    out 42H,al;старшая
    in al,61H
    mov ah,al
    or al,3
    out 61H,al
popa
ret
bip endp
 
;процедура задержки 
void proc 
pusha
    and al,11111100b
    out 61h,al
    mov cx,04h
    mov dx,93e0h
    mov ah,86h
    int 15h 
    popa
ret
void endp
handler:
 
 
 
handler proc
pushf                               ; создание в стеке структуры для IRET
    call    cs:old                   ; вызов старого обработчика прерываний
    push    ds                       ; сохранение модифицируемых регистров
    push    es
    push    ax
    push    bx
    push    cx
    push    dx
    push    di
    push    cs
    pop     ds
    
    ;для отсчета минтуы используется счетчик counter
    ;тк прерывание срабатывает 18 раз в секнуду
    ;смена звучащей ноты изменяется только тогда когда 
    ;counter становится равным 0
    dec counter
    cmp counter,0
    jne met1
    ;воспроизведениие ноты
    ;и смена ноты на следующуюю
    mov bx,i
    mov ax,notes[bx]
    mov outSound, ax
    call bip
    add i,2
    mov counter,18
    cmp i, 24 
    jle met1
    add i,2
    call void
    ;выход из обработчика прерывания
    met1:
    pop     di   
    pop     dx
    pop     cx
    pop     bx
    pop     ax
    pop     es
    pop     ds
    
iret   
handler endp
end_handler:
 
;не резидентная часть программы
 
;получаем адрес обработчика прерывания
load:mov ax, 351Ch
int 21h
 
cmp bx,ppresenceflag; флаг присутствия, если программа
; уже есть в памяти повтораная запись не будет производиться
jne exit
;сохранение контекста старого обработчика прерывания
mov word ptr old, bx
mov word ptr old+2,es
mov ax,251Ch
mov dx,offset handler; получаем адрес метки handler
int 21h
mov ax,3100h
mov dx,(end_handler-start+10Fh)/16; получение размера 
;обработчика прерывания в параграфах
int 21h
;выход из программы с сохранением нового обработчика прерывания
 
exit:
mov ax,3100h
int 21h
 
ret
end start
  • Вопрос задан
  • 231 просмотр
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
как только ноты заканчиваются, DOS перестает на что либо реагировать

а зачем ты вызываешь void когда ноты заканчиваются?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы