#assembly #x86 #dos #x86-16
#сборка #x86 #dos #x86-16
Вопрос:
Я просматривал спецификации для int 21h
прерываний DOS здесь http://spike.scu.edu.au /~barry/interrupts.html
Я мало что знаю о сборке, но похоже, что регистр AL является стандартом для хранения возвращаемых значений из прерывания. Например, служба 01h (прочитанный символ) сохраняет прочитанный там символ. И служба 02h (запись символа в стандартный вывод) сохраняет там последний выводимый символ.
Но когда дело доходит до AH = 09h (запись строки в стандартный вывод), возвращаемое значение ВСЕГДА равно 24h . Почему это так?
Сначала я подумал, что по какой-то технической причине должно быть установлено какое-то значение, но, похоже, это не так. Существует множество служб DOS, которые вообще не указывают возвращаемое значение. И некоторые хранят возвращаемое значение в других регистрах, таких как 2Ch (получение системного времени), которое вместо этого сохраняет результат в регистрах CH, CL, DH и DL вместо AL.
Итак, почему служба прерываний AH = 09h сохраняет значение в AL? И почему 24 часа?
Комментарии:
1. Это немного странно и кажется мне «случайным» …. т. Е., Может быть, это то, что всегда происходит в AL, когда он делает то, что делает, а затем возвращается, так что это то, что они говорят. Но тогда зачем вообще это говорить в этом случае? Интересный вопрос. В конечном итоге это может быть закрыто как основанное на мнении, если кто-то не ответит, основываясь на знании деталей реализации прерывания.
2. @lurker Да, старый добрый «основанный на мнениях» 🙂 Это так злоупотребляет. И тем более, что этот вопрос вообще не основан на мнениях. У него есть четкий ответ. Может быть, никто не знает ответа, но это совершенно другое дело.
3.В другом источнике говорится :»AL = 24h (‘$’, завершающий строку, несмотря на официальные документы, в которых указано, что ничего не возвращается)»
4. @Jester О, но тогда это действительно имеет смысл. Это последний символ в строке, который всегда является $-терминатором
5. @Jester Должен ли я написать ответ или вы хотите честь?
Ответ №1:
Еще несколько деталей:
Вы можете увидеть здесь исходный код для этого системного вызова в MS-DOS версии v1.25:
PRTBUF: ;System call 9
MOV SI,DX
OUTSTR:
LODSB
CMP AL,"$"
JZ RET20
CALL OUT
JMP SHORT OUTSTR
Он использует LODSB
инструкцию в цикле для загрузки байтов из строки, сравнения их $
и их записи. Поскольку LODSB
он жестко подключен для загрузки AL
, и цикл завершается, когда $
он виден, это то, что осталось AL
.
API DOS указал, что AX не нужно сохранять системными вызовами (см. Справочное руководство программиста MS-DOS, 1.10.4, «Обработка регистров»), а возвращаемое значение из службы 09h просто описывается как «None». Таким образом, нет никакой документированной гарантии относительно того, что AL должен содержать при выходе; его содержимое просто не указано. Другие версии DOS могли вести себя по-другому, поэтому вам, очевидно, не следует полагаться на такое поведение.
Ответ №2:
@Jester сделал очень хорошее наблюдение. 24h — это код ascii для $, а служба 09h ожидает строку, завершающуюся $ . Сравните со службой 02h, которая выводит последний символ на вывод, и этот символ заканчивается в AL. А теперь мы говорим о функции, которая выводит строку, завершающуюся $, и оставляет $ в регистре AL.
Эта гипотеза также объясняет, почему в официальной документации не указано какое-либо возвращаемое значение для этого прерывания. Это не часть спецификации, а просто результат внутренней работы.
Поэтому, хотя я (или Джестер) не могу с уверенностью сказать, что за этим нет никакой мысли, это объяснение имеет большой смысл.
И, как указал @ecm. Это не «прервать 09h». Это «прерывание обслуживания 21h 09h».
Комментарии:
1. Правильное место для обращения к «не прерывать 9» — это редактирование вопроса (которое я только что сделал, прежде чем увидеть комментарий ecm: P), а не в ответе. Это тот комментарий, который на самом деле предлагает улучшить сообщение, а не отвечает.
2. @PeterCordes Да, вы правы. Я думал об этом, но я хотел отстоять свои ошибки, но, конечно, вы правы.