Буферизованный и произвольный доступ к файлам
БиВ АХ.СХ | ! 31 |
ХСНв 51,01 | ! 32 |
ЗТОБ | ! 33 |
ХСНв 51,01 | ! 34 |
СМР сх.о | ! 35 |
JNE 2Ь | ! 36 |
ЛР 1Ь | ! 37 |
МОУ 5Р.ВР | ! 38 |
Р115Н Ипе1п | ! 39 |
Р1БН егтеББ | ! 40 |
рли РШтТ | ! 41 |
5У5 | ! 42 |
РЛИ ЕХ1Т | ! 43 |
РЛИ ЕХ1Т | ! 44 |
БУЗ | ! 45 |
САН деЕпит | ! 46 |
СМР АХ,0 | ! 47 |
ЛЕ 8Г | ! 48 |
МОУ ВХ.(сигИп) | ! 49 |
СМР ВХ,0 | ! 50 |
ЛЕ 7Г | ! 51 |
СМР ВХ.СсоипЬ) | ! 52 |
00 7Г | ! 53 |
ЗН1_ ВХ.1 | ! 54 |
МОУ АХ,11пЬ-2(ВХ) | ! 55 |
МОУ СХ.ИгМВХ) | ! 56 |
рли 0 | ! 57 |
рли 0 | ! 58 |
РЛИ АХ | ! 59 |
РЛИ (Шс^) | ! 60 |
РЛИ 1_5ЕЕК | ! 61 |
ЗУБ | ! 62 |
511В СХ.АХ | ! 63 |
рли СХ | ! 64 |
РЛИ ЬиГ | ! 65 |
рли (Шск^) | ! 66 |
РЛН 1ЛА0 | ! 67 |
БУЗ | ! 68 |
АОО 5Р,4 | ! 69 |
РЛН 1 | ! 70 |
РЛИ 1л1Р1ТЕ | ! 71 |
ЗУЗ | ! 72 |
АОО 5Р.14 | ! 73 |
ЛР ЗЬ | ! 74 |
Р115Н эсапегг | ! 75 |
рли Р1ШТР | ! 76 |
ЗУЗ | ! 77 |
АОО 5Р,4 | ! 78 |
ЗМР ЗЬ | ! 79 |
рли 0 | ! 80 |
РЛИ ЕХ1Т | ! 81 |
ЗУЗ | ! 82 |
1 ЬиС: | ! 83 |
РЛН ЬиСэ-! г | ! 84 |
РиЗН ЬиГ | ! 85 |
РиЗН (Шс^) | ! 86 |
РиЗН 1ЛА0 | ! 87 |
ЗУЗ | ! 88 |
АОО ЗР,8 | ! 89 |
MOV CX.AX | ! 90 |
ADD BX.CX | ! 91 |
MOV Dl.buf | ! 92 |
RET | ! 93 |
getnum: | ! 94 |
MOV DI,1inein | ! 95 |
PUSH GETCHAR | ! 96 |
1: SYS | ! 97 |
CMPB AL.'\n' | ! 98 |
JL 9b | ! 99 |
JE If | ! 100 |
STOSB | ! 101 |
JMP lb | ! 102 |
1: MOVB (DI).' * | ! 103 |
PUSH curl in | ! 104 |
PUSH numfmt | ! 105 |
PUSH 1inein | ! 106 |
PUSH SSCANF | ! 107 |
SYS | ! 108 |
ADD SP.10 | ! 109 |
RET | ! 110 |
.SECT .DATA | ! Ill |
errmess: | ! 112 |
.ASCIZ "Open %s failed\n" | ! 113 |
numfmt: .ASCIZ ”%d" | ! 114 |
scanerr: | ! 115 |
.ASCIZ "Type a number.\n" | ! 116 |
.ALIGN2 | ! 117 |
.SECT .BSS | ! 118 |
1inein: .SPACE 80 | ! 119 |
fildes: .SPACE2 | ! 120 |
linh: .SPACE 8192 | ! 121 |
curl in: .SPACE4 | ! 122 |
buf: .SPACE bufsiz+2 | ! 123 |
count: .SPACE2 | ! 124 |
В первых пяти строках кода определяются номера системных вызовов и размер буфера, а указатель базы, как обычно, настраивается на вершину стека. В строках 6-13 из стандартного ввода считывается имя файла, а затем оно сохраняется в символьной строке с меткой 1 inein.
Если имя файла не закрыто новой строкой, выводится сообщение об ошибке, а процесс заканчивается с ненулевым состоянием. Все эти действия отражены в строках 38-45. Обратите внимание, что адрес имени файла помещается в стек в строке 39, адрес сообщения об ошибке — в строке 40. Само сообщение об ошибке (представленное в строке ИЗ) представляет собой запрос на строку $s в формате PRINTF. Здесь же выполняется вставка содержимого строки 1 inein.В случае успешного копирования имени файла его открытие производится в строках 14-20. Если вызов open завершается с ошибкой, возвращаемое значение становится отрицательным, и для отображения сообщения об ошибке производится переход к метке 9 в строке 28. Если вызов проходит успешно, возвращаемым значением является дескриптор файла, который сохраняется в переменной f i 1 des. Этот дескриптор понадобится при последующем выполнении вызовов read и 1 seek.
Далее файл считывается блоками по 512 байт, каждый из которых сохраняется в буфере buf. На самом деле под буфер выделяется на два байта больше необходимого объема (512 байт), но сделано это лишь для того, чтобы показать способ размещения символической константы и целого числа в одном выражении (строка 123). Аналогичным образом, в строке 21 в регистр SI загружается адрес следующего элемента массива linh, в результате на дне массива остается машинное слово с нулевым значением. Регистр ВХ получает адрес файла первого непрочитанного символа файла, а значит, в строке 22 перед первым наполнением буфера он инициализируется нулем.
За наполнение буфера отвечает подпрограмма fill buf, размещенная в строках 83-93. После введения в стек аргументов read делается запрос на системный вызов, который помещает число фактически считанных символов в регистр АХ. Это число копируется в СХ, и впоследствии по значению этого регистра можно будет узнать число оставшихся в буфере символов. Положение в файле первого непрочитанного символа хранится в регистре ВХ, и в строке 91 значение СХ прибавляется к значению ВХ. В строке 92 дно буфера помещается в DI; таким образом, осуществляется подготовка к просмотру буфера на предмет следующего символа новой строки.
После возврата из fill buf в строке 24 проводится проверка того, были ли какие-либо символы фактически считаны.
При отрицательном ответе происходит переход из цикла чтения с буферизацией ко второй части программы в строке 25.После этого начинается просмотр буфера. Символ \п загружается в регистр AL в строке 26, а уже в следующей строке это значение просматривается в цикле REP SCASB и сравнивается с буферизованными символами. Выход из цикла может произойти в двух случаях: когда в регистре СХ оказывается нулевое значение или когда просматриваемый символ оказывается символом новой строки. При установленном нулевом флаге последним просмотренным символом оказывается \п, а положения в файле текущего символа (расположенного после перевода строки) сохраняется в массиве linh. Далее происходит приращение счетчика, а положение в файле определяется по значению ВХ и числу символов, оставшихся в СХ (строки 29-31 кода). В строках 32-34 выполняется сохранение, но так как для команды ST0S целевым адресом является не регистр SI, а регистр DI, перед и после вызова команды ST0S эти регистры меняются местами. В строках 35-37 производится проверка оставшихся в буфере данных, после чего в зависимости от значения СХ выполняется переход.
По достижении конца файла в нашем распоряжении оказывается полный список положений в файле начальных элементов строк. Так как массив linh начинается с нулевого слова, нам известно, что первая строка начинается с адреса О, следующая строка находится в положении linh + 2, и т. д. Размер строки п можно вычислить путем вычитания начального адреса строки п из начального адреса строки n + 1.
В оставшейся части программы считывается номер символьной строки, эта строка передается в буфер, после чего она выводится при помощи вызова write. Все необходимые для выполнения этих операций данные имеются в массиве linh, где каждая n-ная запись содержит начальное положение строки п в файле. Если номер запрошенной символьной строки равен нулю или выходит за пределы допустимого диапазона, программа завершается путем перехода к метке 7.
Эта часть программы начинается с вызова подпрограммы getnum (строка 46 кода).
Она считывает символьную строку из стандартного ввода и сохраняет в буфере 1 inein (строки 95-103 кода). Далее подготавливается вызов SSCANF. Принимая во внимание обратный порядок следования аргументов, в стек сначала помещается адрес буфера curl in, где можно разместить целочисленное значение, затем адрес форматной строки для целочисленного представления numfmt, и, наконец, адрес буфера 1 inein, в котором содержится число в десятичном представлении. Если это возможно, системная подпрограмма SSCANF помещает двоичное значение в curl in. В случае ошибки она возвращает нулевое значение АХ. Проверка возвращаемого значения проводится в строке 48; при ошибке программа генерирует сообщение об ошибке посредством метки 8.Если подпрограмма getnum возвращает действительное целочисленное значение в curl in, оно сначала копируется в ВХ. Далее это значение проверяется на предмет принадлежности к допустимому диапазону (строки 49-53 кода). Если обнаруживается, что номер строки выходит за пределы этого диапазона, происходит выход (EXIT).
Далее необходимо определить конечное положение данной строки в файле и число считываемых файлов; с этой целью значение ВХ умножается на 2 посредством сдвига влево (SHL). В строке 55 положение текущей символьной строки в файле копируется в регистр АХ. Затем положение следующей символьной строки помещается в регистр СХ, и на его основе вычисляется число байтов в текущей строке.
Для произвольного чтения данных из файла применяется вызов 1 seek; он устанавливает смещение к байту, который предполагается прочесть в следующую очередь. Подпрограмма 1 seek выполняется относительно начала файла, и в этой связи в строке 57 в стек помещается нулевой аргумент. Следующим аргументом является смещение в файле. По определению этот аргумент является длинным (32-разрядным) целым, поэтому сначала в стек вводится пулевое слово, а затем — значение АХ (строки 58 и 59 кода); таким образом формируется 32-разряд- ное целочисленное значение. Далее в строке 62 в стек отправляются дескриптор файла и код LSEEK, а также выполняется вызов. Возвращаемое значение LSEEK определяет текущее положение в файле, а найти его можно в комбинации регистров DX : АХ. Если число умещается в рамки машинного слова (а размер файла не превышает 65 536 байт, по-другому быть и не может), адрес помещается в АХ; следовательно, если вычесть значение этого регистра из СХ (строка 63), мы получим число байтов, которые необходимо прочесть для помещения строки в буфер.
Все остальное очень просто. В строках 64-68 строка считывается из файла, а затем при помощи дескриптора 1 файла в строках 70-72 она записывается в файл стандартного вывода. Следует иметь в виду, что после частичной очистки стека, которая выполняется в строке 69, значения счетчика и буфера в нем остаются. Наконец, в строке 73, указатель стека сбрасывается полностью, после чего осуществляются обратный переход к метке 3 и очередной вызов getnum.
Еще по теме Буферизованный и произвольный доступ к файлам:
- ВОСПОМИНАНИЕ ПРОИЗВОЛЬНОЕ
- ЗАПОМИНАНИЕ ПРОИЗВОЛЬНОЕ
- ВНИМАНИЕ ПРОИЗВОЛЬНОЕ
- ДВИЖЕНИЕ ПРОИЗВОЛЬНОЕ
- ДВИЖЕНИЕ ПРОИЗВОЛЬНОЕ: ФОРМИРОВАНИЕ
- ВОСПРОИЗВЕДЕНИЕ ПРОИЗВОЛЬНОЕ
- 3. Доступ к источникам информации.
- Прямой доступ к информации и предузнавание
- Непосредственный доступ и предсказания
- § 6. Равный доступ к государственной службе
- 2.1.4. Классификация информации по доступу к ней
- Ключ доступен каждому.
- Прямой доступ к информации (на основе книг Барбары Энн Бреннан).
- Метод Ключ – защита от стресса и доступ к управлению внутренними ресурсами
- Принцип обеспечения потерпевшим права на доступ к правосудию и возмещение причиненного преступлением вреда
- Статья 200. Незаконные действия с документами на перевод, платежными карточками и иными средствами доступа к банковским счетам, оборудованием для их изготовления
- 15.6. Порядок доступа к Архивным фондам и использования архивных документов
- Статья 361-2. Несанкционированные сбыт или распространение информации с ограниченным доступом, которая сохраняется в электронно-вычислительных машинах (компьютерах), автоматизированных системах, компьютерных сетях или на носителях такой информации
- Статья 362. Несанкционированные действия с информацией, обрабатывается в электронно-вычислительных машинах (компьютерах), автоматизированных системах, компьютерных сетях или сохраняется на носителях такой информации, совершенные лицом, имеет право доступа к ней