Может ли процедура обработки прерывания сборки x86 вызывать другое прерывание?

Могу ли я вызвать прерывание из подпрограммы обслуживания прерываний в автономной среде x686?

Итак, можно сделать следующее:

isr:
    pusha
    call doSomething
    int 21h
    popa
iret

Если это возможно, то есть ли у этих вложенных прерываний какие-либо существенные провалы?


person The amateur programmer    schedule 30.08.2014    source источник


Ответы (2)


Вызов прерывания аналогичен обычному call с установленными флагами. И что делает iret, так это возвращает и поднимает флаги. Итак, да, прерывания можно вызывать рекурсивно. На самом деле вызов прерывания в другом обработчике прерывания происходит все время из-за аппаратных прерываний, постоянно работающих в системе, если вы, конечно, не отключите их.

Аппаратные прерывания имеют дополнительные ограничения и обычно не вызываются внутри того же обработчика до завершения его обработки. Обработчики прерываний уведомляют аппаратное обеспечение о новых прерываниях, сигнализируя контроллеру прерываний.

person Sedat Kapanoglu    schedule 30.08.2014
comment
На самом деле, если вы хотите, вы можете имитировать эффект прерывания, просто помещая в стек те же самые данные, которые оно помещает. Таким образом, одно прерывание может прервать другое из-за аппаратного обеспечения, но вы можете вызвать тот же эффект. Что сложно сделать, так это имитировать действие прерывания с более низким приоритетом. - person Ira Baxter; 30.08.2014

Хотя процессор не накладывает фундаментальных ограничений на вложенные прерывания, службы MS-DOS и BIOS не допускают повторного входа. То есть, как правило, их небезопасно вызывать во время аппаратного прерывания, поскольку прерывание может произойти, когда ЦП уже выполняет функции MS-DOS или BIOS.

Чтобы использовать службы MS-DOS и BIOS из подпрограммы обслуживания аппаратных прерываний, можно предпринять ряд шагов, чтобы обеспечить их безопасное использование. То, что вам нужно сделать, довольно сложно, среди прочего вам нужно отслеживать флаг InDos и перехватывать другие прерывания, поэтому я просто укажу вам на раздел о повторном входе в книге Искусство программирования на языке ассемблера. Он неплохо справляется со всеми деталями.

Вот выдержка из этого раздела. Это лишь часть того, что вам может понадобиться сделать:

MS-DOS предоставляет специальный однобайтовый флаг (InDOS), который содержит ноль, если DOS в данный момент активен, и ненулевое значение, если DOS уже обрабатывает запрос приложения. Проверив флаг InDOS, ваш TSR может определить, может ли он безопасно выполнить вызов DOS. Если этот флаг равен нулю, вы всегда можете сделать вызов DOS. Если этот флаг содержит один, вы не сможете выполнить вызов DOS. MS-DOS предоставляет вызов функции Get InDOS Flag Address, который возвращает адрес флага InDOS. Чтобы использовать эту функцию, загрузите ah с 34h и вызовите DOS. DOS вернет адрес флага InDOS в es:bx. Если вы сохраните этот адрес, ваши резидентные программы смогут проверить флаг InDOS, чтобы увидеть, активен ли DOS.

На самом деле есть два флага, которые вы должны проверить: флаг InDOS и флаг критической ошибки (criterr). Оба этих флага должны содержать ноль, прежде чем вы вызовете DOS из TSR. В DOS версии 3.1 и более поздних версиях флаг критической ошибки появляется в байте непосредственно перед флагом InDOS.

Так что же делать, если эти флаги не равны нулю? Достаточно просто сказать: «Эй, вернись и займись этим позже, когда MS-DOS вернется к пользовательской программе». Но как это сделать? Например, если прерывание клавиатуры активирует ваш TSR, и вы передаете управление реальному обработчику клавиатуры, потому что DOS занята, вы не можете ожидать, что ваш TSR будет волшебным образом перезапущен позже, когда DOS перестанет быть активным.

Хитрость заключается в том, чтобы подключить ваш TSR к прерыванию таймера, а также к прерыванию клавиатуры. [...]

person Ross Ridge    schedule 30.08.2014
comment
Я думаю, что этот ответ слишком далеко отклоняется от темы и вводит совершенно новые слои путаницы (DOS, TSR, ...), о которых ОП не спрашивал. - person Ira Baxter; 30.08.2014
comment
Первоначальный плакат привел пример, в котором используется int 21h, программное прерывание для основного API MS-DOS, а затем спросил, есть ли у этих вложенных прерываний какие-либо существенные провалы. В его конкретном примере есть пещера, которую я описал в своем ответе выше. В более общем случае вы не можете предположить, что безопасно вызывать прерывание из подпрограммы обслуживания прерывания, потому что прерывание, которое вы вызываете, могло быть прервано ISR и, вероятно, не является реентерабельным. - person Ross Ridge; 30.08.2014