Здравствуйте, ialmiev!
1) Прерывания похожи на подпрограммы. Но есть и существенные отличия.
Отличия: подпрограммы бывают с коротким (внутри сегмента) и с длинным вызовом (со сменой сегмента). При вызове в стек заносится только адрес возврата (короткий или длинный). Прерывания предусматривают только длинный вызов. Кроме того, перед записью в стек адреса возврата в стек заносится регистр флагов (.т.о. всего 3 слова). Прерывания бывают аппаратные и программные. Аппаратные возникают в любой момент времени (по этой причине и необходимо сохранять флажки) в ответ на некоторые события, например, нажатие на клавишу клавиатуры или тик таймера. Программные вызываются по команде int, либо по команде длинный call с предварительной записью в стек флажков. При необходимости и аппаратные можно вызвать непосредственно.
Общие черты: и то и то можно вызвать непосредственно (одно с помощью int и call, второе - call). Общим можно назвать и то, что в обоих случаях идет речь о некоторой последовательности команд, вызываемой специальным образом.
В прерываниях (только программных!) можно передать параметры только через регистры. В аппаратных, естественно, ни о каких параметрах речь не идет.
В подпрограммах параметры можно передавать как через регистры, так и через стек.
Да, подпрограмма в Ассемблере - это тоже самое, что и понятие функция в Си или subroutine в Фортране. В ЯВУ параметры передаются обычно только через стек.
2) См. выше
3) Все функции прерывания ДОС 21h, которые оперируют с именами файлов, каталогов требуют, чтобы строка с именем заканчивалась нулем (как в Си).
Единственной функцией, для которой используется другой символ для указания конца строки, а именно '$' - это функция 09h - функция вывода строки на экран.
Так исторически сложилось...
4) Совершенно верно, перед вызовом любой функции прерывания необходимо записать в AH и другие регистры номер функции и параметры.
После вызова в AX, других регистрах и во флажках возвращается результат выполнения функции прерывания.
В случае функции открытия файла AH=3Dh (AL=00h - режим открытия файла = чтение) возвращается описатель файла (handle). Это значение надо сохранить
и использовать во всех дальнейших операциях с данным файлом. Этот описатель должен потом быть в регистре BX.
5) см выше :)
Мы хотим закрыть данный файл, поэтому и должны указать handle именно этого файла
Одновременно могут быть открыты несколько файлов. Надо же указать, какой файл надо закрыть...
В Си ж тоже параметром указывается описатель закрываемого файла...
Да, для всех используемых переменных необходимо выделять память, что и делает инструкция dw (data word) - слово, два байта
0 - это инициализация переменной нулем. При необходимости можно записать что-то другое.
Если начальное значение переменной неважно, можно поставить знак вопроса (?)
Какую роль играет регистр BX для функций прерывания 21h, работающих с файлами, см выше. В других функциях по-другому.
6) Для работы с файлами используются следующие функции:
AH = 3Dh - открытие файла, AL=00h - на чтение, AL = 01h - на запись, получаем handle
AH = 3Fh - чтение из открытого на чтение файла, DS:DX - адрес приемного буфера, CX - количество читаемых байт, BX - handle
AH = 40h - запись открытого на запись файла, DS:DX - адрес приемного буфера, CX - количество читаемых байт, BX - handle
AH = 3eh - закрытие открытого файла, BX - handle
7) В целом, регистр CX используется универсально. Только в некоторых командах его использование строго регламентировано.
Команда цикла LOOP, циклические строковые команды, например, REP MOVB.
В них количество циклических операций всегда лежит в CX
Можно еще добавить команду JCXZ, которая проверяет только регистр CX
Все остальное - по договоренности. Как, например, в функциях чтения и записи из/в файл(а) количество лежит в CX
Можно еще добавить, что регистр CX не может использоваться там, где необходимы обязательно другие регистры.
Например, для косвенной адресации можно использовать только BX, BP, DI, SI или для работы с портами только DX и AX(AL)
И в некоторых других...
А так, использовать CX можно как и где угодно :)
8) Любая пользовательская программа и ОС работает только в памяти ОЗУ. На жестком диске они выполняться не может.
Перед работой программу надо прочитать в память.
Тоже самое относится и к данным. Все данные размещаются в ОЗУ.
Есть одно исключение
В компьютере есть специальная память (черная микросхема с ножками-ручками
), в которой записан, так называемый, BIOS.
Это то, что запускается, когда компьютер включается. В BIOS находится и программы, и некоторые данные.
И то, и другое можно только читать. При работе некоторые данные переносятся в ОЗУ, чтобы можно было писать.
После всех тестов происходит обращение к указанному диску, с него считывается ОС, которой и передается управление.
В современных компьютерах немного по-другому, но суть та же...
9) Так командой mov dx,offset Buffer как раз и заносится в DX адрес буфера buffer
Конкретное значение вычисляется на этапе ассемблирования. Или Вам хочется самому высчитывать байтики?
Значение сегментного регистра DS в модели Tiny изначально известно и равно CS
В других моделях, разумеется, значение сегментного регистра необходимо указывать.
10) Перед чтением файла, необходимо указать адрес буфера, куда читать.
Что мы и делаем, занеся адрес в DX.
Когда программа с диска загружается в память, то вся память после тела программы является свободной.
Именно этим мы и воспользовались.
Чтобы получить адрес байта за последним байтом программы мы дали команду
Buffer equ $
Доллар - это указание компилятору присвоить переменной значение, равное текущему адресу.
Т.о. значение Buffer - адрес за программой. Вы правы - получается первый свободный байт.
После чтения файла, а его имя 'c:\msdos.sys',0 (смотрите в тексте), его содержимое окажется, начиная с адреса Buffer
Сам файл лежит на диске. Он там и останется (если мы его не удалим, надеюсь, понимаете, данный системный файл удалять не следует
)
Надеюсь, описал все достаточно подробно.
Если что-то осталось непонятным, спрашивайте в мини-форуме...