Win32 в машинных кодах


Консольное приложение - часть 2


Работа со стандартными вводом и выводом "изнутри" подобна работе с файлами. Стандартный ввод выглядит как файл с разрешением "только для чтения", а стандартный вывод - как файл с разрешением "только для записи". Для работы с ними используют соответствующие функции API - ReadFile и WriteFile из модуля Kernel32.dll. Рассмотрим их подробнее.

При вызове функции ReadFile в стек помещаются 5 параметров в следующем порядке:

  1. адрес структуры, использующейся при асинхронном вводе-выводе. При обычном (синхронном) вводе значение этого параметра равно нулю;
  2. адрес переменной (4 байта), по которому будет записано количество действительно прочитанных функцией байтов (это значение может быть меньше заявленного - например, если кончились данные);
  3. число байтов, которые нужно прочесть ("заявка");
  4. адрес, по которому нужно разместить прочитанные данные (буфер);
  5. описатель файла, из которого производится чтение.

Внимания заслуживает последний аргумент. Для работы с файлом используется так называемый описатель (handle) - это некий идентификатор, который система присваивает файлу после его открытия. На самом деле, при открытии файла создается внутренняя системная структура, в которой хранятся различные вспомогательные данные, такие как текущая позиция, с которой нужно читать или записывать данные, и т.п. Все обращения к файлам возможны только после их открытия и только по их описателям.

Функция WriteFile также принимает 5 схожих параметров:

  1. адрес структуры для асинхронного вывода;
  2. адрес переменной (4 байта), в которую будет помещено количество действительно записанных байтов;
  3. число байтов, которые нужно записать ("заявка");
  4. адрес начала буфера, где находятся предназначенные для записи данные;
  5. описатель файла, в который производится запись.

Но как получить нужные описатели? В случае файлов существуют специальные функции API (наподобие CreateFile) для их открытия. Для стандартного ввода-вывода тоже существует своя функция - GetStdHandle, тоже из модуля Kernel32.dll. Она принимает лишь один аргумент - число, указывающее на тип нужного описателя (для стандартного ввода или вывода). На самом деле, существует еще и третий тип - стандартная ошибка, он, как и стандартный вывод, служит для отображения сообщений на экране. Его можно использовать в тех случаях, когда нужно как-то разделить обычные сообщения и сообщения об ошибках (например, можно использовать перенаправление только для стандартной ошибки - тогда эти сообщения будут записаны в файл и не попадут на экран). В качестве параметра функции GetStdHandle используются 0FFFFFFF6h для стандартного ввода, 0FFFFFFF5h для стандартного вывода и 0FFFFFFF4h для стандартной ошибки.




Начало  Назад  Вперед



Книжный магазин