То, что вы делаете, неправильно по нескольким причинам:
- Обычные функции C нельзя безопасно использовать в качестве подпрограмм обработки прерываний, поскольку они неправильно сохраняют, загружают и восстанавливают ЦП.регистры.Они должны быть объявлены с ключевым словом
interrupt
.И они будут иметь iret
для вас в конце. - Переменные, которые могут асинхронно изменяться в программе от подпрограмм прерывания, должны быть объявлены как
volatile
, в противном случае вы рискуете получить к ним неправильный доступоптимизировано компилятором. - Ваш встроенный код сборки, вероятно, повреждает содержимое регистров процессора.В этом коде неправильно то, что ваш
asm
блокирует беспорядок с указателем стека.Первый блок выходит с несколькими дополнительными словами в стеке.Это может быть совершенно неожиданным для компилятора и может сломать вашу программу.Могут быть и другие проблемы, но я не собираюсь сверяться с документацией компилятора, какие регистры должны быть сохранены встроенными блоками сборки.Я бы вообще не делал этого и выбрал бы функцию setvect()
. - Вызов большинства стандартных функций библиотеки изнутри подпрограмм обработки прерываний вызывает проблемы, потому что эти функции, как правило, не реентерабельныебезопасный.Они могут изменять некоторые глобальные переменные или состояния совершенно неожиданным образом для остальной части программы.То же самое относится и к вызову функций службы DOS из подпрограмм обработки прерываний (на которые полагается ваш printf (), кстати).Вы можете звонить только тогда, когда DOS говорит, что все в порядке.Он делает это через переменную флага
InDos
, и все же не все безопасно вызывать, когда InDos
= 0.
Узнайте, как изменить векторы прерываний, определить подпрограммы обработки прерываний и вызвать функции DOSот них, все с Turbo C, в ответе на этот вопрос .
Вы также можете найти этот вопрос и его ответы полезными.
РЕДАКТИРОВАТЬ :
Вот как вы делаете это без функциональности dos.h со встроенным asm:
#include <stdio.h>
volatile int a = 1;
void interrupt (*pOldInt9)(void);
void func(void);
void interrupt keyboard(void)
{
printf("\n\nkeyboard!!!\n");
asm {
in al, 0x60
in al, 0x61
mov ah, al
or al, 0x80
out 0x61, al
mov al, ah
out 0x61, al
}
a = 0;
asm {
mov al, 0x20
out 0x20, al
}
}
int main(void)
{
printf("starting...");
func();
return 0;
}
void func(void)
{
printf("\n*****\n");
asm {
push bx
push es
mov bx, 9 * 4
mov ax, 0
mov es, ax
cli
mov ax, es:[bx]
mov word ptr pOldInt9, ax
mov word ptr es:[bx], offset keyboard
mov ax, es:[bx + 2]
mov word ptr pOldInt9[2], ax
mov es:[bx + 2], cs
sti
pop es
pop bx
}
while (a) {}
asm {
push bx
push es
mov bx, 9 * 4
mov ax, 0
mov es, ax
cli
mov ax, word ptr pOldInt9
mov es:[bx], ax
mov ax, word ptr pOldInt9[2]
mov es:[bx + 2], ax
sti
pop es
pop bx
}
}