Ассемблер Это просто! Учимся программировать

         

Программа из прошлого выпуска


Давайте разберем программу из прошлого выпуска.

Вот она: ... ;опустим код CSEG и пр. (1) Begin: mov ax,3D00h ;будем открывать файл для чтения ;обратите внимание, как мы записываем операторы (сразу за меткой). Так тоже можно (2) mov dx,offset File_name ;DS:DX указывают на путь к файлу (3) int 21h ;открываем (4) jc Error_file ;если произошла ошибка (нет такого файла, слишком много открытых файлов, ошибка чтения) - то на метку Error_file (5) mov Handle,ax ;запомним номер файла в переменной Handle (6) mov bx,ax ;для того, чтобы прочитать файл нужно в BX указать его номер, полученный после открытия. Он у нас в AX. Загрузка числа в регистр с другого регистра (а, тем более, если используется AX) происходит быстрее, чем с памяти (переменной). Поэтому загружаем с AX, а не с переменной. Хотя запись mov bx,Handle не будет ошибочной (7) mov ah,3Fh ;функция 3Fh - чтение файла (8) mov cx,0FF00h ;будем читать 0FF00h (9) mov dx,offset Buffer ;DS:DX указывает на буфер в памяти для чтения (10)int 21h ;все готово. Читаем (11)mov ah,3Eh ;закрываем файл (12)mov bx,Handle ;номер файла должен быть в BX. Но т.к. он менялся, то зарузим его с нашей переменной (Handle) (13)int 21h ;закрываем файл (14)mov dx,offset Mess_ok ;загрузим в DX строку с сообщением о том, что все в порядке (15)Out_prog: mov ah,9 ;функция 09h - вывод строки на экран (можно было и не писать!) (16)int 21h ;выводим строку int 20h ;выходим из программы (17)Error_file: mov dx,offset Mess_error ;загрузим в DX строку с сообщением о том, что не смогли открыть файл (18)jmp Out_prog ;и пойдем на метку Out_prog (зачем нам дублировать код, если он уже есть?) ;Данные (19)Handle dw 0 ;резерв 2 байта для нашей переменной (20)Mess_ok db 'Файл загружен в память! Смотрите в отладчике!$' ;понятно (21)Mess_error db 'Не удалось открыть (найти) файл ' ;эти строки... (22)File_name db 'c:\msdos.sys',0,'!$' ;... рассмотрим ниже... (23)Buffer equ $ ;...

Для многих (я бы сказал, почти для всех) остались непонятными строки (21) - (23). Кто полазил в отладчике - много чего понял и узнал нового. Давайте подробней рассмотрим указанные команды.

Запомните оператор: $. При ассемблировании нашей программы Ассемблер заменит этот знак на адрес, по которому он расположен. Вот пример: (1) CSEG segment (2) assume cs:CSEG (3) org 100h (4) Begin: (5) My_lab equ $ (6) My_lab2 equ $+2 (7) mov bx,offset My_lab (8) mov bx,offset My_lab2 (9) int 20h (10) CSEG ends (11) end Begin


Строки (5) и (6) места в памяти не занимают (как и метки). Ассемблер ( при ассемблировании) запомнит, что метка My_lab находится по адресу 100h (помните: org 100h?), а метка My_lab2 - 102h. Рекомендую Вам посмотреть в отладчике эту программу.

В программе из прошлого выпуска (как вы уже поняли) мы размещаем Buffer в конце кода. Т.о. оператор: mov dx,offset Buffer

занесет в DX адрес (смещение) на первый свободный байт, расположенный за телом программы, в нашем сегменте (CSEG). По этому адресу мы и будем загружать в память данные из файла. В отладчике это хорошо видно.

Что касается строк (21) - (22). На сколько вы помните из прошлых выпусков, функция 09h прерывания 21h выводит на экран строку. Сама строка должна заканчиваться символом $. Я уже говорил, что если этот знак убрать, то функция, выведя строку на экран, продолжит выводить остальные символы до тех пор, пока в памяти не встреится тот самый "бакс" - $.

Теперь внимательно смотрите на строки (21) - (22): (21)Mess_error db 'Не удалось открыть (найти) файл ' (22)File_name db 'c:\msdos.sys',0,'!$'

Что мы видим? Мы видим то, что не видим в конце строки (21) символ $ (да простят меня за каламбур!). Функция 09h (если файл не был найден) выведет на экран следующее:

Не удалось открыть (найти) файл c:\msdos.sys !

Символ '0' будет отображен как пробел. А для чего нужен '0' в строке (22)? При открытии файла в DS:DX должен быть указан сам файл. Строка должна завершаться символом '0'. Если этот символ убрать, то функция скорее всего вернет ошибку. Ведь файла c:\msdos.sys!$ не существует!

Можем сделать и так, конечно. Только мы потеряем байты: Mess_error db 'Не удалось открыть (найти) файл c:\msdos.sys!$' File_name db 'c:\msdos.sys',0

Какой смысл?

Вот и разобрались... Мы будем очень часто на практике использовать данный метод. Поэтому, если у вас и остались "темные моменты", мы их постепенно "просветлим".


Содержание раздела







Forekc.ru
Рефераты, дипломы, курсовые, выпускные и квалификационные работы, диссертации, учебники, учебные пособия, лекции, методические пособия и рекомендации, программы и курсы обучения, публикации из профильных изданий