Консультация № 191509
18.10.2017, 22:52
0.00 руб.
0 2 1
Уважаемые эксперты, здравствуйте,

прошу помощи в следующих вопросах по книге О.А.Калашникова,

1) имеются прерывания BIOS и прерывания DOS. в книгах объясняется, что "прерывание" это подпрограмма, а "mov ax, ..." - это определенная функция для определенного прерывания.
прошу объяснить по аналогии с Си и Фортраном-77 - является ли понятие-термин "подпрограмма" тоже самое что и понятие функция в Си или subroutine в Фортране ?"
2) что такое понятие "функция" - "mov ax, ..." - в рамках понятия-термина "прерывание" в Ассемблере ? можно ли понимать понятие-термин "функция" какого-либо прерывания как тоже самое, что и параметр какой-либо функции в Си или параметр сабрутины в Фортране ?

теперь вопросы по главе 8 книги О.А.Калашникова.
3) листинг 8.2,
Код:
File_name db 'command.com',0

почему в конце записан нуль "0" ? почему нельзя записать как
Код:
File_name db 'command.com$' 

либо просто как
Код:
File_name db 'command.com' 


4)
Код:
mov ax,3D00h
mov dx,offset file_name
int 21h

стр. 80, после рис.8.2,
Код:
При успешном открытии файла в ax возвращается уникальный идентификационный номер файла. В дальнейшем, при обращении к данному файлу, будет указываться не его имя, а этот номер. Флаг переноса сброшен. После вызова функции 3Dh необходимо сохранить номер файла, переданный ею в регистре ax!

с одной стороны, в регистр ax записывается команда-функция 3D00h, с другой стороны говорится, что при успешном открытии файла в регистр ax возвращается уникальный идентификационный номер файла. означает ли это, что регистр ax меняет содержимое - с команды 3D00h на другое число ? означает ли это, что для дальнейшей работы с открытым файлом необходимо использовать новое число (а уже не команду-функцию прерывания int 21h), которое записывается в микропроцессоре в регистр ax ?

5) листинг 8.4,
команда mov ah,3Eh - мне это понятно - это эквивалентно fclose(...) в Си.
откуда возникает регистр bx ? почему он нужен здесь для этой команды ?
далее,
Код:
mov Handle,ax
mov ah,3Eh
mov bx,Handle
int 21h
...
Handle dw 0

что означает строка "Handle dw 0" ? является ли это таким описанием переменных в Ассемблере наподобие int/float/char/double в Си ? зачем нужна эта строка в Ассемблере ? зачем нужен в этой строке нуль "0" ? является ли этот нуль-0 обязательным ? правильно ли я понимаю, что как и в Си и как в Фортране также и в Ассемблере - необходимо описывать-объявлять переменные ?
неужели в "Handle" записывается команда "3D00h" ? а затем - и в регистр bx ? какую роль играет регистр bx, в частности, для прерывания int 21h ?

6) стр. 81,
Код:
Для чтения информации из файла используется функция 3Fh, а для записи в файл — 40h. При этом bx должен содержать тот самый номер файла — Handle, cx — количество читаемых или записываемых байтов, ds:dx — адрес буфера для чтения/записи. Пример чтения файла в память с использованием функции 40h при-веден в разд. 8.3.


но ведь для чтения файла используется команда mov al,00h или mov ax 3D00h ? откуда возникает команда 3Fh ? в какой регистр она должна записываться и когда ? аналогично - для записи в файл используется команда mov ax,3D01h. тогда, откуда возникает команда 40h ? в какой регистр она должна записываться и когда ?

7) назначение регистра cx - мне понятно - он используется Ассемблером в качестве счетчика (counter),

8) что такое понятие-термин "буфер (buffer)" ? это область памяти ? где - в ОЗУ (черная микросхема с ножками-ручками) или ПЗУ (жесткий диск) ?

9) "...ds:dx - адрес буфера для чтения/записи ...", но ведь в листинге 8.5,
используется строка:
Код:
mov dx,offset Buffer

где
Код:
Buffer equ $

но ведь используется не команда например "mov dx, 0F1B02h" ? более того регистр "ds", в общем случае, тоже должен инициализироваться, то есть ему нужно присваивать какое-либо шестнадцатиричное число (в общем случае - не для модели tiny) ?

10) глава 9, стр. 86,
Код:
В программе из главы 8 мы размещаем метку Buffer в конце кода. Таким образом, команда mov dx,offset Buffer занесет в dx последний свободный байт в нашем сегменте CSEG. По этому адресу мы и будем загружать программу в память.

почему все-таки в dx заносится последний свободный байт ? "свободный байт" - откуда ? из какого файла ?
на что все-таки указывает и что описывает оператор "$" ?
почему "последний свободный байт", а не "первый свободный байт" ? - ведь понятие "файл" - это всего-лишь означает область памяти в ПЗУ (или ОЗУ все-таки ?), и поэтому так как "файл" занят различными командами и данными, то свободное место имеется (точнее может иметься) только и только после самого "файла", а не до него (точнее не в нем самом).

Спасибо.

Обсуждение

давно
Посетитель
7438
7205
19.10.2017, 11:57
общий
это ответ
Здравствуйте, ialmiev!
1) Прерывания похожи на подпрограммы. Но есть и существенные отличия.
Отличия: подпрограммы бывают с коротким (внутри сегмента) и с длинным вызовом (со сменой сегмента). При вызове в стек заносится только адрес возврата (короткий или длинный). Прерывания предусматривают только длинный вызов. Кроме того, перед записью в стек адреса возврата в стек заносится регистр флагов (.т.о. всего 3 слова). Прерывания бывают аппаратные и программные. Аппаратные возникают в любой момент времени (по этой причине и необходимо сохранять флажки) в ответ на некоторые события, например, нажатие на клавишу клавиатуры или тик таймера. Программные вызываются по команде int, либо по команде длинный call с предварительной записью в стек флажков. При необходимости и аппаратные можно вызвать непосредственно.
Общие черты: и то и то можно вызвать непосредственно (одно с помощью int и call, второе - call). Общим можно назвать и то, что в обоих случаях идет речь о некоторой последовательности команд, вызываемой специальным образом.
В прерываниях (только программных!) можно передать параметры только через регистры. В аппаратных, естественно, ни о каких параметрах речь не идет.
В подпрограммах параметры можно передавать как через регистры, так и через стек.
Да, подпрограмма в Ассемблере - это тоже самое, что и понятие функция в Си или subroutine в Фортране. В ЯВУ параметры передаются обычно только через стек.

2) См. выше

3) Все функции прерывания ДОС 21h, которые оперируют с именами файлов, каталогов требуют, чтобы строка с именем заканчивалась нулем (как в Си).
Единственной функцией, для которой используется другой символ для указания конца строки, а именно '$' - это функция 09h - функция вывода строки на экран.
Так исторически сложилось...

4) Совершенно верно, перед вызовом любой функции прерывания необходимо записать в AH и другие регистры номер функции и параметры.
После вызова в AX, других регистрах и во флажках возвращается результат выполнения функции прерывания.
В случае функции открытия файла AH=3Dh (AL=00h - режим открытия файла = чтение) возвращается описатель файла (handle). Это значение надо сохранить
и использовать во всех дальнейших операциях с данным файлом. Этот описатель должен потом быть в регистре BX.

5) см выше :)
Мы хотим закрыть данный файл, поэтому и должны указать handle именно этого файла
Одновременно могут быть открыты несколько файлов. Надо же указать, какой файл надо закрыть...
В Си ж тоже параметром указывается описатель закрываемого файла...

Код:
Handle dw 0

Да, для всех используемых переменных необходимо выделять память, что и делает инструкция 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
Сам файл лежит на диске. Он там и останется (если мы его не удалим, надеюсь, понимаете, данный системный файл удалять не следует )

Надеюсь, описал все достаточно подробно.
Если что-то осталось непонятным, спрашивайте в мини-форуме...
5
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
401339
51
23.10.2017, 02:55
общий
Адресаты:
Уважаемый Игорь Витальевич,
здравствуйте,

спасибо за Ваше сообщение-консультацию. извините за задержку. в настоящее время иду дальше - будут вопросы по главе 9 из книги О.А.Калашникова - эти вопросы задам завтра.

Спасибо.
Форма ответа